diff --git a/inst/include/population_dynamics/population/population.hpp b/inst/include/population_dynamics/population/population.hpp index d33b60c06..b4b8d795b 100644 --- a/inst/include/population_dynamics/population/population.hpp +++ b/inst/include/population_dynamics/population/population.hpp @@ -380,7 +380,6 @@ struct Population : public FIMSObject { << this->recruitment->evaluate(this->spawning_biomass[year - 1], phi0) << std::endl; - this->numbers_at_age[index_ya] = this->recruitment->evaluate(this->spawning_biomass[year - 1], phi0) * this->recruitment->recruit_deviations[year]; diff --git a/inst/include/utilities/fims_json.hpp b/inst/include/utilities/fims_json.hpp new file mode 100644 index 000000000..ebf17beb5 --- /dev/null +++ b/inst/include/utilities/fims_json.hpp @@ -0,0 +1,416 @@ +/// @file fims_json.hpp +/// @brief A simple JSON parsing and generation library. +/// @details This library provides classes and functions for parsing JSON strings +/// and generating JSON data structures. +#include +#include +#include +#include +#include +#include + +class JsonValue; + +/// Alias for a JSON object, mapping strings to JSON values. +using JsonObject = std::map; + +/// Alias for a JSON array, containing a sequence of JSON values. +using JsonArray = std::vector; + +/// Represents different types of JSON values. +enum JsonValueType { + Null = 0, ///< Null JSON value. + Number, ///< Numeric JSON value. + String, ///< String JSON value. + Bool, ///< Boolean JSON value. + Object, ///< JSON object. + Array ///< JSON array. +}; + +/// Represents a JSON value. +class JsonValue { +public: + + /// Default constructor, initializes to Null value. + JsonValue() : type(JsonValueType::Null) { + } + + /// Constructor for numeric JSON value (i.e., integer). + JsonValue(int num) : type(JsonValueType::Number), number(num) { + } + + /// Constructor for numeric JSON value (i.e., double). + JsonValue(double num) : type(JsonValueType::Number), number(num) { + } + + /// Constructor for string JSON value. + JsonValue(const std::string& str) : type(JsonValueType::String), str(str) { + } + + /// Constructor for boolean JSON value. + JsonValue(bool b) : type(JsonValueType::Bool), boolean(b) { + } + + /// Constructor for JSON object value. + JsonValue(const JsonObject& obj) : type(JsonValueType::Object), object(obj) { + } + + /// Constructor for JSON array value. + JsonValue(const JsonArray& arr) : type(JsonValueType::Array), array(arr) { + } + + /// Get the type of the JSON value. + JsonValueType GetType() const { + return type; + } + + /// Get the numeric value as an integer. + int GetInt() const { + return static_cast (number); + } + + /// Get the numeric value as a double. + double GetDouble() const { + return number; + } + + /// Get the string value. + const std::string& GetString() const { + return str; + } + + /// Get the boolean value. + bool GetBool() const { + return boolean; + } + + /// Get the JSON object. + JsonObject& GetObject() { + return object; + } + + /// Get the JSON array. + JsonArray& GetArray() { + return array; + } + +private: + JsonValueType type; ///< Type of the JSON value. + double number; ///< Numeric value. + std::string str; ///< String value. + bool boolean; ///< Boolean value. + JsonObject object; ///< JSON object. + JsonArray array; ///< JSON array. +}; + +/// Parses JSON strings and generates JSON values. +class JsonParser { +public: + + /// Parse a JSON string and return the corresponding JSON value. + JsonValue Parse(const std::string& json); + /// Write a JSON value to a file. + void WriteToFile(const std::string& filename, JsonValue jsonValue); + /// Display a JSON value to the standard output. + void Show(JsonValue jsonValue); + +private: + /// Skip whitespace characters in the input string. + void SkipWhitespace(); + /// Parse a JSON value. + JsonValue ParseValue(); + /// Parse a numeric JSON value. + JsonValue ParseNumber(); + /// Parse a string JSON value. + JsonValue ParseString(); + /// Parse a boolean JSON value. + JsonValue ParseBool(); + /// Parse a null JSON value. + JsonValue ParseNull(); + /// Parse a JSON object. + JsonValue ParseObject(); + /// Parse a JSON array. + JsonValue ParseArray(); + /// Write a JSON value to an output file stream. + void WriteJsonValue(std::ofstream& outputFile, JsonValue jsonValue); + /// Display a JSON value to an output stream. + void PrintJsonValue(std::ostream& outputFile, JsonValue jsonValue); + /// Indentation helper for printing JSON values in an output file stream. + void Indent(std::ostream& outputFile, int level); + /// Indentation helper for printing JSON values in an output stream. + void Indent(std::ofstream& outputFile, int level); + + std::string data; ///< Input JSON data. + size_t position; ///< Current position in the data. +}; + +/// Parse a JSON string and return the corresponding JSON value. +/// @param json The JSON string to parse. +/// @return The parsed JSON value. +JsonValue JsonParser::Parse(const std::string& json) { + data = json; + position = 0; + return ParseValue(); +} + +void JsonParser::SkipWhitespace() { + while (position < data.length() && std::isspace(data[position])) { + position++; + } +} + +/// Parse a JSON value. +/// @return The parsed JSON value. +JsonValue JsonParser::ParseValue() { + /// Skip whitespace characters in the input string. + SkipWhitespace(); + char current = data[position]; + if (current == '{') { + return ParseObject(); + } else if (current == '[') { + return ParseArray(); + } else if (current == '"') { + return ParseString(); + } else if (current == 't' || current == 'f') { + return ParseBool(); + } else if (current == 'n') { + return ParseNull(); + } else { + return ParseNumber(); + } +} + +/// Parse a numeric JSON value. +/// @return The parsed JSON value. +JsonValue JsonParser::ParseNumber() { + size_t end_pos = position; + bool is_float = false; + while (end_pos < data.length() && (std::isdigit(data[end_pos]) || data[end_pos] == '.' || data[end_pos] == '-' || data[end_pos] + == 'e' || data[end_pos] == 'E')) { + if (data[end_pos] == '.' || data[end_pos] == 'e' || data[end_pos] == 'E') { + is_float = true; + } + end_pos++; + } + + std::string num_str = data.substr(position, end_pos - position); + position = end_pos; + + if (is_float) { + double num; + std::istringstream(num_str) >> num; + return JsonValue(num); + } else { + int num; + std::istringstream(num_str) >> num; + return JsonValue(num); + } +} + +/// Parse a string JSON value. +/// @return The parsed JSON value. +JsonValue JsonParser::ParseString() { + position++; // Skip the initial '"' + size_t end_pos = data.find('"', position); + std::string str = data.substr(position, end_pos - position); + position = end_pos + 1; + return JsonValue(str); +} + +/// Parse a boolean JSON value. +/// @return The parsed JSON value. +JsonValue JsonParser::ParseBool() { + if (data.compare(position, 4, "true") == 0) { + position += 4; + return JsonValue(true); + } else if (data.compare(position, 5, "false") == 0) { + position += 5; + return JsonValue(false); + } else { + // Invalid boolean value + return JsonValue(); + } +} + +/// Parse a null JSON value. +/// @return The parsed JSON value. +JsonValue JsonParser::ParseNull() { + if (data.compare(position, 4, "null") == 0) { + position += 4; + return JsonValue(); + } else { + // Invalid null value + return JsonValue(); + } +} + +/// Parse a JSON object. +/// @return The parsed JSON value representing the object. +JsonValue JsonParser::ParseObject() { + JsonObject obj; + position++; // Skip the initial '{' + + while (data[position] != '}') { + SkipWhitespace(); + std::string key = ParseString().GetString(); + + position++; // Skip the ':' + SkipWhitespace(); + JsonValue value = ParseValue(); + obj[key] = value; + + SkipWhitespace(); + if (data[position] == ',') { + position++; + } + } + + position++; // Skip the trailing '}' + return JsonValue(obj); +} + +/// Parse a JSON array. +/// @return The parsed JSON value representing the array. +JsonValue JsonParser::ParseArray() { + JsonArray arr; + position++; // Skip the initial '[' + + while (data[position] != ']') { + SkipWhitespace(); + JsonValue value = ParseValue(); + arr.push_back(value); + + SkipWhitespace(); + if (data[position] == ',') { + position++; + } + } + + position++; // Skip the trailing ']' + return JsonValue(arr); +} + +/// Write a JSON value to an output file. +/// @param filename The name of the output file. +/// @param jsonValue The JSON value to write. +void JsonParser::WriteToFile(const std::string& filename, JsonValue jsonValue) { + std::ofstream outputFile(filename); + if (!outputFile) { + std::cerr << "Error: Unable to open file " << filename << " for writing." << std::endl; + return; + } + + // Call a private helper function to write JSON values recursively + WriteJsonValue(outputFile, jsonValue); +} + +/// Write a JSON value to an output file. +// Private helper function to write JSON values recursively +/// @param outputFile The output file stream. +/// @param jsonValue The JSON value to write. +void JsonParser::WriteJsonValue(std::ofstream& outputFile, JsonValue jsonValue) { + switch (jsonValue.GetType()) { + case JsonValueType::Null: + outputFile << "null"; + break; + case JsonValueType::Number: + outputFile << jsonValue.GetDouble(); + break; + case JsonValueType::String: + outputFile << "\"" << jsonValue.GetString() << "\""; + break; + case JsonValueType::Bool: + outputFile << (jsonValue.GetBool() ? "true" : "false"); + break; + case JsonValueType::Object: + { + JsonObject& obj = jsonValue.GetObject(); + outputFile << "{"; + bool first = true; + for (const auto& pair : obj) { + if (!first) { + outputFile << ","; + } + first = false; + outputFile << "\"" << pair.first << "\":"; + WriteJsonValue(outputFile, pair.second); + } + outputFile << "}"; + } + break; + case JsonValueType::Array: + { + JsonArray& arr = jsonValue.GetArray(); + outputFile << "["; + bool first = true; + for (const auto& value : arr) { + if (!first) { + outputFile << ","; + } + first = false; + WriteJsonValue(outputFile, value); + } + outputFile << "]"; + } + break; + } +} + +/// Display a JSON value to the standard output. +/// @param jsonValue The JSON value to display. +void JsonParser::Show(JsonValue jsonValue){ + this->PrintJsonValue(std::cout, jsonValue); + std::cout< pop; // ConfigurePopulationModel, RunModelLoop, and CheckModelOutput // methods are in integration_class.hpp - good = t.ConfigurePopulationModel(pop, input, output); + good = t.ConfigurePopulationModel(pop, input_, output_); - pop.numbers_at_age = t.RunModelLoop(pop, input); - good = t.CheckModelOutput(pop, output); + pop.numbers_at_age = t.RunModelLoop(pop, input_); + good = t.CheckModelOutput(pop, output_); // declare unfished numbers at age 1, unfished spawning bimoass, // and unfished biomass @@ -68,15 +71,15 @@ namespace // Test unfished numbers at age, unfished spawning biomass, // and unfished biomass - it = input.FindMember("median_R0"); - rapidjson::Value &R_0 = (*it).value; + it = input.find("median_R0"); + JsonArray &R_0 = (*it).second.GetArray(); // When obtaining the numeric values, GetDouble() will convert internal integer representation // to a double. Note that, int and unsigned can be safely converted to double, // but int64_t and uint64_t may lose precision (since mantissa of double is only 52-bits). double log_rzero = fims::log(R_0[0].GetDouble()); - it = input.FindMember("Phi.0"); - rapidjson::Value &Phi0 = (*it).value; + it = input.find("Phi.0"); + JsonArray &Phi0 = (*it).second.GetArray();; double phi_0 = Phi0[0].GetDouble(); for (int year = 0; year < pop.nyears; year++) @@ -116,11 +119,11 @@ namespace // Test spawning biomass // find the OM json member called "SSB" - it = output.FindMember("SSB"); + it = output.find("SSB"); - if (it != output.MemberEnd()) + if (it != output.end()) { - rapidjson::Value &e = (*it).value; + JsonArray &e = (*it).second.GetArray();; for (int year = 0; year < pop.nyears; year++) { expected_spawning_biomass[year] = e[year].GetDouble(); @@ -146,11 +149,11 @@ namespace // Test biomass // find the OM json member called "Biomass" - it = output.FindMember("biomass.mt"); + it = output.find("biomass.mt"); - if (it != output.MemberEnd()) + if (it != output.end()) { - rapidjson::Value &e = (*it).value; + JsonArray &e = (*it).second.GetArray();; for (int year = 0; year < pop.nyears; year++) { expected_biomass[year] = e[year].GetDouble(); @@ -173,13 +176,13 @@ namespace << "year " << pop.nyears + 1; // Test expected catch - it = output.FindMember("L.mt"); + it = output.find("L.mt"); - if (it != output.MemberEnd()) + if (it != output.end()) { - typename rapidjson::Document::MemberIterator fleet1; - fleet1 = it->value.FindMember("fleet1"); - rapidjson::Value &fleet_catch = (*fleet1).value; + typename JsonObject::iterator fleet1; + fleet1 = it->second.GetObject().find("fleet1"); + JsonArray &fleet_catch = (*fleet1).second.GetArray(); for (int year = 0; year < pop.nyears; year++) { expected_catch[year] = fleet_catch[year].GetDouble(); @@ -203,18 +206,18 @@ namespace } // Test expected index - it = output.FindMember("survey_q"); - typename rapidjson::Document::MemberIterator fleet2_q; - fleet2_q = it->value.FindMember("survey1"); - rapidjson::Value &fleet_q = (*fleet2_q).value; + it = output.find("survey_q"); + typename JsonObject::iterator fleet2_q; + fleet2_q = it->second.GetObject().find("survey1"); + JsonArray&fleet_q = (*fleet2_q).second.GetArray(); - it = output.FindMember("survey_index_biomass"); + it = output.find("survey_index_biomass"); - if (it != output.MemberEnd()) + if (it != output.end()) { - typename rapidjson::Document::MemberIterator fleet2_index; - fleet2_index = it->value.FindMember("survey1"); - rapidjson::Value &fleet_index = (*fleet2_index).value; + typename JsonObject::iterator fleet2_index; + fleet2_index = it->second.GetObject().find("survey1"); + JsonArray &fleet_index = (*fleet2_index).second.GetArray(); EXPECT_EQ(pop.fleets[0]->q, 1.0); // Do not use EXPECT_EQ to compare floats or doubles // Use EXPECT_NEAR here @@ -250,17 +253,16 @@ namespace // Test numbers at age // find the OM json member called "N.age" - it = output.FindMember("N.age"); - - if (it != output.MemberEnd()) + it = output.find("N.age"); + if (it != output.end()) { - rapidjson::Value &e = (*it).value; + JsonArray &e = (*it).second.GetArray(); for (int year = 0; year < pop.nyears; year++) { for (int age = 0; age < pop.nages; age++) { int index_ya = year * pop.nages + age; - expected_numbers_at_age[index_ya] = e[year][age].GetDouble(); + expected_numbers_at_age[index_ya] = e[year].GetArray()[age].GetDouble(); // Expect the difference between FIMS value and the // expected value from the MCP OM // is less than 1.0% of the expected value. @@ -268,6 +270,7 @@ namespace expected_numbers_at_age[index_ya] * 100, 1.0) << "differ at index " << index_ya << "; year " << year << "; age" << age; + // Expect the difference between FIMS value and the // expected value from the MCP OM // is less than 65 fish. @@ -280,27 +283,28 @@ namespace } } } - // Test numbers at age in year pop.nyear+1 for (int age = 0; age < pop.nages; age++) { + int index_ya = pop.nyears * pop.nages + age; EXPECT_GT(pop.numbers_at_age[index_ya], 0.0) - << "differ at index " << index_ya << "; year " << pop.nyears + 1 << "; age" << age; + << "differ at index " << index_ya << "; year " << pop.nyears + 1 << "; age " << age; } - + + + // Test fishing mortality at age - it = output.FindMember("FAA"); - - if (it != output.MemberEnd()) + it = output.find("FAA"); + if (it != output.end()) { - rapidjson::Value &e = (*it).value; + JsonArray &e = (*it).second.GetArray(); for (int year = 0; year < pop.nyears; year++) { for (int age = 0; age < pop.nages; age++) { int index_ya = year * pop.nages + age; - expected_mortality_F[index_ya] = e[year][age].GetDouble(); + expected_mortality_F[index_ya] = e[year].GetArray()[age].GetDouble(); // Expect the difference between FIMS value and the // expected value from the MCP OM // is less than 0.0001. @@ -313,13 +317,12 @@ namespace } } } - - // Test total mortality at age - it = input.FindMember("M.age"); + // Test total mortality at age + it = input.find("M.age"); // integration_test_log <<"test"<ncases_m; i++) - { - for (uint32_t j = 0; j < this->ninput_files_m; j++) - { - rapidjson::Document input; - rapidjson::Document output; + std::stringstream ss; + for (uint32_t i = 0; i < this->ncases_m; i++) { + for (uint32_t j = 0; j < this->ninput_files_m; j++) { + JsonValue input; + JsonValue output; - ss.str(""); - ss << "inputs/C" << i << "/om_input" << j + 1 << ".json"; - this->ReadJson(ss.str(), input); + ss.str(""); + ss << "inputs/C" << i << "/om_input" << j + 1 << ".json"; + this->ReadJson(ss.str(), input); - ss.str(""); - ss << "inputs/C" << i << "/om_output" << j + 1 << ".json"; - this->ReadJson(ss.str(), output); + ss.str(""); + ss << "inputs/C" << i << "/om_output" << j + 1 << ".json"; + this->ReadJson(ss.str(), output); - fims::Population pop; + fims::Population pop; - if (!this->ConfigurePopulationModel(pop, input, output)) - { - good = false; - } + if (!this->ConfigurePopulationModel(pop, input, output)) { + good = false; + } - this->RunModelLoop(pop, input); + this->RunModelLoop(pop, input); - if (!this->CheckModelOutput(pop, output)) - { - good = false; + // if (!this->CheckModelOutput(pop, output)) { + // good = false; + // } + } } - } - } - - return good; - } - - bool ReadJson(const std::string &path, - rapidjson::Document &json_) - { - std::stringstream ss; - std::ifstream infile; - infile.open(path.c_str()); - - ss.str(""); - while (infile.good()) - { - std::string line; - std::getline(infile, line); - ss << line << "\n"; - } - if (print_statements) - { - std::cout << path << "\n"; - std::cout << ss.str() << "\n"; + return good; } - json_.Parse(ss.str().c_str()); - - return true; - } - bool ConfigurePopulationModel(fims::Population &pop, - rapidjson::Document &input, - rapidjson::Document &output) - { + bool ReadJson(const std::string &path, + JsonValue &result) { - typename rapidjson::Document::MemberIterator it; + std::stringstream ss; + std::ifstream infile; + infile.open(path.c_str()); - size_t nfleets, nsurveys, nages, nyears; - // get number of years - it = input.FindMember("nyr"); - if (it != input.MemberEnd()) - { - rapidjson::Value &e = (*it).value; - nyears = e[0].GetInt(); - - if (print_statements) - { - std::cout << "nyr " << nyears << std::endl; - } - } - else - { - if (print_statements) - { - std::cout << "nyr not found in input\n"; - } - } - - // get number of ages - it = input.FindMember("nages"); - if (it != input.MemberEnd()) - { - rapidjson::Value &e = (*it).value; - nages = e[0].GetInt(); - - if (print_statements) - { - std::cout << "nages " << nages << std::endl; - } - } - else - { - if (print_statements) - { - std::cout << "nages not found in input\n"; - } - } - - // get number of fleets - it = input.FindMember("fleet_num"); - if (it != input.MemberEnd()) - { - rapidjson::Value &e = (*it).value; - nfleets = e[0].GetInt(); - bool parse_alternate_name = false; - - // instantiate fleets - if (print_statements) - { - std::cout << "nfleets " << nfleets << std::endl; - } - for (int i = 0; i < nfleets; i++) - { - std::shared_ptr> f = std::make_shared>(); - f->Initialize(nyears, nages); - f->observed_index_data = std::make_shared>(nyears); - f->observed_agecomp_data = std::make_shared>(nyears, nages); - - std::stringstream strs; - strs << "fleet" << i + 1; - - // set fleet selectivity - it = input.FindMember("sel_fleet"); - typename rapidjson::Document::MemberIterator fsel; - fsel = it->value.FindMember(strs.str().c_str()); - rapidjson::Value &ss = (*fsel).value; - typename rapidjson::Document::MemberIterator pattern; - pattern = fsel->value.FindMember("pattern"); - rapidjson::Value &sel_pattern = (*pattern).value; - - if (sel_pattern[0].GetDouble() == 1) - { // logistic - std::shared_ptr> selectivity = std::make_shared>(); - typename rapidjson::Document::MemberIterator sel_a50; - sel_a50 = fsel->value.FindMember("A50.sel1"); - - rapidjson::Value &a50 = (*sel_a50).value; - selectivity->median = a50[0].GetDouble(); - - typename rapidjson::Document::MemberIterator sel_slope; - sel_slope = fsel->value.FindMember("slope.sel1"); - rapidjson::Value &slope = (*sel_slope).value; - selectivity->slope = slope[0].GetDouble(); - f->selectivity = selectivity; - } - else if (sel_pattern[0].GetDouble() == 2) - { // double logistic - std::shared_ptr> selectivity = std::make_shared>(); - - typename rapidjson::Document::MemberIterator sel_a50; - sel_a50 = fsel->value.FindMember("A50.sel1"); - rapidjson::Value &a501 = (*sel_a50).value; - selectivity->median_asc = a501[0].GetDouble(); - - typename rapidjson::Document::MemberIterator sel_slope; - sel_slope = fsel->value.FindMember("slope.sel1"); - rapidjson::Value &slope1 = (*sel_slope).value; - selectivity->slope_asc = slope1[0].GetDouble(); - - sel_a50 = fsel->value.FindMember("A50.sel2"); - rapidjson::Value &a502 = (*sel_a50).value; - selectivity->median_desc = a502[0].GetDouble(); - - sel_slope = fsel->value.FindMember("slope.sel2"); - rapidjson::Value &slope2 = (*sel_slope).value; - selectivity->slope_desc = slope2[0].GetDouble(); - f->selectivity = selectivity; - } - - // set fleet fishing mortality - if (print_statements) - { - std::cout << "f "; - } - it = input.FindMember("f"); - f->log_q = 0.0; - for (int i = 0; i < it->value.Size(); i++) - { - rapidjson::Value &e = (*it).value; - f->Fmort[i] = e[i].GetDouble(); - f->log_Fmort[i] = std::log(e[i].GetDouble()); - if (print_statements) - { - std::cout << f->log_Fmort[i] << " "; - } - } - - if (print_statements) - { - std::cout << "\n"; - } - - pop.fleets.push_back(f); - } - } - else - { - if (print_statements) - { - std::cout << "fleet_num not found in input\n"; - } - } - - // get number of surveys - it = input.FindMember("survey_num"); - if (it != input.MemberEnd()) - { - rapidjson::Value &e = (*it).value; - nsurveys = e[0].GetInt(); - for (int i = 0; i < nsurveys; i++) - { - std::shared_ptr> s = std::make_shared>(); - s->Initialize(nyears, nages); - s->observed_index_data = std::make_shared>(nyears); - s->observed_agecomp_data = std::make_shared>(nyears, nages); - std::shared_ptr> selectivity = std::make_shared>(); - std::stringstream strs; - strs << "survey" << i + 1; - - // set survey selectivity - it = input.FindMember("sel_survey"); - typename rapidjson::Document::MemberIterator fsel; - fsel = it->value.FindMember(strs.str().c_str()); - rapidjson::Value &ss = (*fsel).value; - typename rapidjson::Document::MemberIterator pattern; - pattern = fsel->value.FindMember("pattern"); - rapidjson::Value &sel_pattern = (*pattern).value; - - if (sel_pattern[0].GetDouble() == 1) - { // logistic - std::shared_ptr> selectivity = std::make_shared>(); - typename rapidjson::Document::MemberIterator sel_a50; - sel_a50 = fsel->value.FindMember("A50.sel1"); - - rapidjson::Value &a50 = (*sel_a50).value; - selectivity->median = a50[0].GetDouble(); - - typename rapidjson::Document::MemberIterator sel_slope; - sel_slope = fsel->value.FindMember("slope.sel1"); - rapidjson::Value &slope = (*sel_slope).value; - selectivity->slope = slope[0].GetDouble(); - - s->selectivity = selectivity; + ss.str(""); + while (infile.good()) { + std::string line; + std::getline(infile, line); + ss << line << "\n"; } - else if (sel_pattern[0].GetDouble() == 1) - { // double logistic - std::shared_ptr> selectivity = std::make_shared>(); - - typename rapidjson::Document::MemberIterator sel_a50; - sel_a50 = fsel->value.FindMember("A50.sel1"); - rapidjson::Value &a501 = (*sel_a50).value; - selectivity->median_asc = a501[0].GetDouble(); - - typename rapidjson::Document::MemberIterator sel_slope; - sel_slope = fsel->value.FindMember("slope.sel1"); - rapidjson::Value &slope1 = (*sel_slope).value; - selectivity->slope_asc = slope1[0].GetDouble(); - - sel_a50 = fsel->value.FindMember("A50.sel2"); - rapidjson::Value &a502 = (*sel_a50).value; - selectivity->median_desc = a502[0].GetDouble(); - - sel_slope = fsel->value.FindMember("slope.sel2"); - rapidjson::Value &slope2 = (*sel_slope).value; - selectivity->slope_desc = slope2[0].GetDouble(); - s->selectivity = selectivity; + if (print_statements) { + std::cout << path << "\n"; + // std::cout << ss.str() << "\n"; } - // set survey catchability - it = output.FindMember("survey_q"); - typename rapidjson::Document::MemberIterator fleet2_q; - fleet2_q = it->value.FindMember("survey1"); - rapidjson::Value &fleet_q = (*fleet2_q).value; - s->log_q = fims::log(fleet_q[0].GetDouble()); - - std::fill(s->log_Fmort.begin(), s->log_Fmort.end(), fims::log(0.0)); - pop.fleets.push_back(s); - } - if (print_statements) - { - std::cout << "survey_num " << nsurveys << std::endl; - } - } - else - { - if (print_statements) - { - std::cout << "survey_num not found in input\n"; - } - } - - pop.nfleets = pop.fleets.size(); - - // initialize population - pop.Initialize(nyears, 1, nages); - - // Set initial size to value from MCP C0 - it = output.FindMember("N.age"); - if (it != output.MemberEnd()) - { - rapidjson::Value &e = (*it).value; - std::vector init_naa(pop.nages, 0.0); - for (int age = 0; age < pop.nages; age++) - { - init_naa[age] = e[0][age].GetDouble(); - pop.log_init_naa[age] = std::log(init_naa[age]); - } - } + JsonParser parser; + result = parser.Parse(ss.str()); + parser.WriteToFile("out.json", result); + // json_.Parse(ss.str().c_str()); - // set ages vector - it = input.FindMember("ages"); - if (it != input.MemberEnd()) - { - rapidjson::Value &e = (*it).value; - if (print_statements) - { - std::cout << "ages "; - } - - for (int i = 0; i < e.Size(); i++) - { - pop.ages[i] = e[i].GetDouble(); - } - if (print_statements) - { - std::cout << std::endl; - } - } - else - { - if (print_statements) - { - std::cout << "ages not found in input\n"; - } + return true; } - // set years vector - it = input.FindMember("year"); - if (it != input.MemberEnd()) - { - rapidjson::Value &e = (*it).value; - if (print_statements) - { - std::cout << "years "; - } - for (int i = 0; i < e.Size(); i++) - { - pop.years[i] = e[i].GetDouble(); - if (print_statements) - { - std::cout << pop.years[i] << " "; + bool ConfigurePopulationModel(fims::Population &pop, + JsonValue &input, + JsonValue &output) { + + std::cout << input.GetType() << "\n"; + size_t nfleets, nsurveys, nages, nyears; + + std::cout << input.GetDouble() << "\n"; + if (input.GetType() == JsonValueType::Object && output.GetType() == JsonValueType::Object) { + + JsonObject& obj = input.GetObject(); + JsonObject& obj2 = output.GetObject(); + + typename JsonObject::iterator it; + + it = obj.find("nyr"); + if (it != obj.end()) { + JsonValue e = (*it).second; + if (e.GetType() == JsonValueType::Array) { + JsonArray a = e.GetArray(); + nyears = a[0].GetInt(); + } + + + if (print_statements) { + std::cout << "nyr " << nyears << std::endl; + } + } else { + if (print_statements) { + std::cout << "nyr not found in input\n"; + } + } + + // typename JsonObject::iterator it; + + it = obj.find("nages"); + if (it != obj.end()) { + JsonValue e = (*it).second; + if (e.GetType() == JsonValueType::Array) { + JsonArray a = e.GetArray(); + nages = a[0].GetInt(); + } + + + if (print_statements) { + std::cout << "nages " << nages << std::endl; + } + } else { + if (print_statements) { + std::cout << "nages not found in input\n"; + } + } + + //get number of fleets + it = obj.find("fleet_num"); + if (it != obj.end()) { + JsonValue e = (*it).second; + if (e.GetType() == JsonValueType::Array) { + JsonArray a = e.GetArray(); + nfleets = a[0].GetInt(); + } + + if (print_statements) { + std::cout << "nfleets " << nfleets << std::endl; + } + + for (size_t i = 0; i < nfleets; i++) { + std::shared_ptr > f = std::make_shared >(); + f->Initialize(nyears, nages); + f->observed_index_data = std::make_shared >(nyears); + f->observed_agecomp_data = std::make_shared >(nyears, nages); + + std::stringstream strs; + strs << "fleet" << i + 1; + + it = obj.find("sel_fleet"); + typename JsonObject::iterator fsel; + if (it != obj.end()) { + JsonValue e = (*it).second; + if (e.GetType() == JsonValueType::Object) { + JsonObject o = e.GetObject(); + fsel = o.find(strs.str().c_str()); + + if ((*fsel).second.GetType() == JsonValueType::Object) { + JsonObject fsel_o = (*fsel).second.GetObject(); + it = fsel_o.find("pattern"); + if ((*it).second.GetType() == JsonValueType::Array) { + + JsonArray sel_pattern = (*it).second.GetArray(); + if (print_statements) { + std::cout << "Selectivity:\n"; + } + if (sel_pattern[0].GetInt() == 1) {//logistic + if (print_statements) { + std::cout << "logistic\n"; + } + std::shared_ptr > selectivity = std::make_shared >(); + + it = fsel_o.find("A50.sel1"); + if ((*it).second.GetType() == JsonValueType::Array) { + JsonArray a50 = (*it).second.GetArray(); + selectivity->median = a50[0].GetDouble(); + if (print_statements) { + std::cout << "A50 " << selectivity->median << "\n"; + } + } + + it = fsel_o.find("slope.sel1"); + if ((*it).second.GetType() == JsonValueType::Array) { + JsonArray slope = (*it).second.GetArray(); + selectivity->slope = slope[0].GetDouble(); + if (print_statements) { + std::cout << "slope " << selectivity->slope << "\n"; + } + } + + f->selectivity = selectivity; + + + } else if (sel_pattern[0].GetInt() == 2) {//double logistic + if (print_statements) { + std::cout << "double logistic\n"; + } + std::shared_ptr > selectivity = std::make_shared >(); + + it = fsel_o.find("A50.sel1"); + if ((*it).second.GetType() == JsonValueType::Array) { + JsonArray a50 = (*it).second.GetArray(); + selectivity->median_asc = a50[0].GetDouble(); + if (print_statements) { + std::cout << "A50 asc " << selectivity->median_asc << "\n"; + } + } + + it = fsel_o.find("slope.sel1"); + if ((*it).second.GetType() == JsonValueType::Array) { + JsonArray slope = (*it).second.GetArray(); + selectivity->slope_asc = slope[0].GetDouble(); + if (print_statements) { + std::cout << "slope asc " << selectivity->slope_asc << "\n"; + } + } + + it = fsel_o.find("A50.sel2"); + if ((*it).second.GetType() == JsonValueType::Array) { + JsonArray a50 = (*it).second.GetArray(); + selectivity->median_desc = a50[0].GetDouble(); + if (print_statements) { + std::cout << "A50 desc " << selectivity->median_desc << "\n"; + } + } + + it = fsel_o.find("slope.sel2"); + if ((*it).second.GetType() == JsonValueType::Array) { + JsonArray slope = (*it).second.GetArray(); + selectivity->slope_desc = slope[0].GetDouble(); + if (print_statements) { + std::cout << "slope desc " << selectivity->slope_desc << "\n"; + } + } + f->selectivity = selectivity; + } + + } + + } + } + + } + + + f->log_q = 0.0; + it = obj.find("f"); + if ((*it).second.GetType() == JsonValueType::Array) { + JsonArray f_values = (*it).second.GetArray(); + for (int i = 0; i < f_values.size(); i++) { + f->Fmort[i] = f_values[i].GetDouble(); + f->log_Fmort[i] = std::log(f_values[i].GetDouble()); + if (print_statements) { + std::cout << f->Fmort[i] << " "; + } + } + + } + + if (print_statements) { + std::cout << "\n"; + } + pop.fleets.push_back(f); + } + + } else { + if (print_statements) { + std::cout << "nfleets not found in input\n"; + } + } + + it = obj.find("survey_num"); + if (it != obj.end()) { + JsonValue e = (*it).second; + if (e.GetType() == JsonValueType::Array) { + JsonArray a = e.GetArray(); + nsurveys = a[0].GetInt(); + } + + if (print_statements) { + std::cout << "nsurveys " << nsurveys << std::endl; + } + + for (size_t i = 0; i < nsurveys; i++) { + std::shared_ptr > s = std::make_shared >(); + s->is_survey = true; + s->Initialize(nyears, nages); + s->observed_index_data = std::make_shared >(nyears); + s->observed_agecomp_data = std::make_shared >(nyears, nages); + + std::stringstream strs; + strs << "survey" << i + 1; + + it = obj.find("sel_survey"); + typename JsonObject::iterator fsel; + if (it != obj.end()) { + JsonValue e = (*it).second; + if (e.GetType() == JsonValueType::Object) { + JsonObject o = e.GetObject(); + fsel = o.find(strs.str().c_str()); + + + if ((*fsel).second.GetType() == JsonValueType::Object) { + + + JsonObject fsel_o = (*fsel).second.GetObject(); + it = fsel_o.find("pattern"); + if ((*it).second.GetType() == JsonValueType::Array) { + + JsonArray sel_pattern = (*it).second.GetArray(); + + if (sel_pattern[0].GetInt() == 1) {//logistic + std::shared_ptr > selectivity = std::make_shared >(); + + it = fsel_o.find("A50.sel1"); + if ((*it).second.GetType() == JsonValueType::Array) { + JsonArray a50 = (*it).second.GetArray(); + selectivity->median = a50[0].GetDouble(); + } + + it = fsel_o.find("slope.sel1"); + if ((*it).second.GetType() == JsonValueType::Array) { + JsonArray slope = (*it).second.GetArray(); + selectivity->slope = slope[0].GetDouble(); + } + + s->selectivity = selectivity; + + + + } else if (sel_pattern[0].GetInt() == 2) {//double logistic + std::shared_ptr > selectivity = std::make_shared >(); + + it = fsel_o.find("A50.sel1"); + if ((*it).second.GetType() == JsonValueType::Array) { + JsonArray a50 = (*it).second.GetArray(); + selectivity->median_asc = a50[0].GetDouble(); + } + + it = fsel_o.find("slope.sel1"); + if ((*it).second.GetType() == JsonValueType::Array) { + JsonArray slope = (*it).second.GetArray(); + selectivity->slope_asc = slope[0].GetDouble(); + } + + it = fsel_o.find("A50.sel2"); + if ((*it).second.GetType() == JsonValueType::Array) { + JsonArray a50 = (*it).second.GetArray(); + selectivity->median_desc = a50[0].GetDouble(); + } + + it = fsel_o.find("slope.sel2"); + if ((*it).second.GetType() == JsonValueType::Array) { + JsonArray slope = (*it).second.GetArray(); + selectivity->slope_desc = slope[0].GetDouble(); + } + s->selectivity = selectivity; + } + + } + + } + } + + } + + + s->log_q = 0.0; + it = obj2.find("survey_q"); + + + if ((*it).second.GetType() == JsonValueType::Object) { + // f->log_q = fims::log((*it).second.GetDouble()); + JsonObject qobj = (*it).second.GetObject(); + + typename JsonObject::iterator qit = qobj.find("survey1"); + + if ((*qit).second.GetType() == JsonValueType::Array) { + JsonArray a = (*qit).second.GetArray(); + s->log_q = fims::log(a[0].GetDouble()); + if (this->print_statements) { + std::cout << "q = " << a[0].GetDouble() << "\nlog(q) = " << s->log_q << "\n"; + } + } + } + + + + pop.fleets.push_back(s); + + } + + } else { + if (print_statements) { + std::cout << "nsurveys not found in input\n"; + } + } + + pop.nfleets = pop.fleets.size(); + + // initialize population + pop.Initialize(nyears, 1, nages); + + // Set initial size to value from MCP C0 + it = obj2.find("N.age"); + if (it != obj2.end()) { + if ((*it).second.GetType() == JsonValueType::Array) { + JsonArray n = (*it).second.GetArray(); + if (n[0].GetType() == JsonValueType::Array) { + JsonArray init_n = n[0].GetArray(); + for (size_t i = 0; i < pop.nages; i++) { + pop.log_init_naa[i] = std::log(init_n[i].GetDouble()); + } + } + } + } + + it = obj.find("ages"); + if (it != obj.end()) { + + if ((*it).second.GetType() == JsonValueType::Array) { + if (print_statements) { + std::cout << "ages: "; + } + JsonArray ages = (*it).second.GetArray(); + for (int i = 0; i < ages.size(); i++) { + pop.ages[i] = ages[i].GetDouble(); + if (print_statements) { + std::cout << pop.ages[i] << " "; + } + } + if (print_statements) { + std::cout << "\n"; + } + } + + + } else { + if (print_statements) { + std::cout << "ages not found in input\n"; + } + } + + it = obj.find("year"); + if (it != obj.end()) { + + if ((*it).second.GetType() == JsonValueType::Array) { + if (print_statements) { + std::cout << "year: "; + } + JsonArray years = (*it).second.GetArray(); + for (int i = 0; i < years.size(); i++) { + pop.years[i] = years[i].GetDouble(); + if (print_statements) { + std::cout << pop.years[i] << " "; + } + } + if (print_statements) { + std::cout << "\n"; + } + } + + + } else { + if (print_statements) { + std::cout << "years not found in input\n"; + } + } + if (print_statements) { + std::cout << "\nMortality:\n"; + } + it = obj.find("M"); + if ((*it).second.GetType() == JsonValueType::Array) { + JsonArray m = (*it).second.GetArray(); + double log_M = std::log(m[0].GetDouble()); + std::fill(pop.log_M.begin(), pop.log_M.end(), log_M); + if (print_statements) { + std::cout << pop.log_M.size() << "\n"; + std::cout << "log_M "; + for (size_t i = 0; i < pop.log_M.size(); i++) { + std::cout << pop.log_M[i] << " "; + } + std::cout << std::endl; + } + } + + + // set recruitment + std::shared_ptr > rec = + std::make_shared >(); + if (print_statements) { + std::cout << "\nRecruitment:\n"; + } + it = obj.find("R0"); + if (it != obj.end()) { + if ((*it).second.GetType() == JsonValueType::Array) { + double r0 = (*it).second.GetArray()[0].GetDouble(); + rec->log_rzero = std::log(r0); + if (print_statements) { + std::cout << "R0 " << rec->log_rzero << " \n"; + } + } + } else { + if (print_statements) { + std::cout << "'R0' not found.\n"; + } + } + + it = obj.find("h"); + if (it != obj.end()) { + if ((*it).second.GetType() == JsonValueType::Array) { + rec->logit_steep = fims::logit(0.2, 1.0, (*it).second.GetArray()[0].GetDouble()); + if (print_statements) { + std::cout << "'h' " << rec->logit_steep << " \n"; + } + } + } else { + if (print_statements) { + std::cout << "'h' not found.\n"; + } + } + + it = obj.find("logR_sd"); + if (it != obj.end()) { + if ((*it).second.GetType() == JsonValueType::Array) { + rec->log_sigma_recruit = (*it).second.GetArray()[0].GetDouble(); + if (print_statements) { + std::cout << "'SD' " << rec->log_sigma_recruit << " \n"; + } + } + } else { + if (print_statements) { + std::cout << "'logR_sd' not found.\n"; + } + } + + + it = obj.find("logR.resid"); + rec->recruit_deviations.resize(nyears + 1); + std::fill(rec->recruit_deviations.begin(), rec->recruit_deviations.end(), 1.0); + if (it != obj.end()) { + if ((*it).second.GetType() == JsonValueType::Array) { + JsonArray rdev = (*it).second.GetArray(); + if (print_statements) { + std::cout << "recruitment deviations: "; + } + for (size_t i = 0; i < rdev.size(); i++) { + rec->recruit_deviations[i] = std::exp(rdev[i].GetDouble()); + if (print_statements) { + std::cout << rec->recruit_deviations[i] << " "; + } + } + if (print_statements) { + std::cout << "\n"; + } + } + } else { + if (print_statements) { + std::cout << "'logR.resid' not found.\n"; + } + } + rec->use_recruit_bias_adjustment = false; + pop.recruitment = rec; + + // set maturity + std::shared_ptr > mat = + std::make_shared >(); + + if (print_statements) { + std::cout << "\nMaturity:\n"; + } + it = obj.find("A50.mat"); + if (it != obj.end()) { + if ((*it).second.GetType() == JsonValueType::Array) { + mat->median = (*it).second.GetArray()[0].GetDouble(); + if (print_statements) { + std::cout << "median " << mat->median << " \n"; + } + } + } else { + if (print_statements) { + std::cout << "'A50.mat' not found.\n"; + } + } + + pop.maturity = mat; + + it = obj.find("slope.mat"); + if (it != obj.end()) { + if ((*it).second.GetType() == JsonValueType::Array) { + mat->slope = (*it).second.GetArray()[0].GetDouble(); + if (print_statements) { + std::cout << "slope " << mat->slope << " \n"; + } + } + } else { + if (print_statements) { + std::cout << "'slope.mat' not found.\n"; + } + } + + // set empirical growth + std::shared_ptr > growth = std::make_shared >(); + std::cout << "Growth:\n"; + + it = obj.find("W.kg"); + if (it != obj.end()) { + if ((*it).second.GetType() == JsonValueType::Array) { + JsonArray wt = (*it).second.GetArray(); + if (print_statements) { + std::cout << "W.kg: "; + } + for (size_t i = 0; i < pop.ages.size(); i++) { + growth->ewaa[static_cast (pop.ages[i])] = wt[i].GetDouble() / 1000.0; + if (print_statements) { + std::cout << growth->ewaa[static_cast (pop.ages[i])] << " "; + } + } + if (print_statements) { + std::cout << "\n"; + } + } + } else { + if (print_statements) { + std::cout << "'logR.resid' not found.\n"; + } + } + + pop.growth = growth; + + return true; } - } - if (print_statements) - { - std::cout << std::endl; - } - } - else - { - if (print_statements) - { - std::cout << "years not found in input\n"; - } - } - // set mortality vector - it = input.FindMember("M"); - rapidjson::Value &e = (*it).value; - double log_M = std::log(e[0].GetDouble()); - std::fill(pop.log_M.begin(), pop.log_M.end(), log_M); - if (print_statements) - { - std::cout << "mortality: " << e[0].GetDouble() << std::endl; - } - // set recruitment - std::shared_ptr> rec = - std::make_shared>(); - it = input.FindMember("R0"); - e = (*it).value; - rec->log_rzero = fims::log(e[0].GetDouble()); - - it = input.FindMember("h"); - e = (*it).value; - rec->logit_steep = fims::logit(0.2,1.0,e[0].GetDouble()); - - it = input.FindMember("logR_sd"); - e = (*it).value; - rec->log_sigma_recruit = e[0].GetDouble(); - it = input.FindMember("logR.resid"); - e = (*it).value; - rec->recruit_deviations.resize(nyears + 1); - std::fill(rec->recruit_deviations.begin(), rec->recruit_deviations.end(), 1.0); - for (int i = 0; i < e.Size(); i++) - { - rec->recruit_deviations[i] = std::exp(e[i].GetDouble()); - if (print_statements) - { - std::cout << rec->recruit_deviations[i] << " "; - } - } - rec->use_recruit_bias_adjustment = false; - pop.recruitment = rec; - - // set maturity - std::shared_ptr> mat = - std::make_shared>(); - it = input.FindMember("A50.mat"); - e = (*it).value; - mat->median = e[0].GetDouble(); - - it = input.FindMember("slope.mat"); - e = (*it).value; - mat->slope = e[0].GetDouble(); - pop.maturity = mat; - - // set empirical growth - std::shared_ptr> growth = std::make_shared>(); - it = input.FindMember("W.kg"); - e = (*it).value; - for (int i = 0; i < e.Size(); i++) - { - growth->ewaa[static_cast(pop.ages[i])] = e[i].GetDouble() / 1000.0; + return false; } - pop.growth = growth; - - return true; - } - std::vector RunModelLoop(fims::Population &pop, - rapidjson::Document &input) - { - rapidjson::StringBuffer buffer; - rapidjson::Writer writer(buffer); + std::vector RunModelLoop(fims::Population &pop, + const JsonValue & input) { - rapidjson::Document output; + JsonObject output; + JsonArray array; - // define the document as an object rather than an array - output.SetObject(); + - // create a rapidjson array type with similar syntax to std::vector - rapidjson::Value array(rapidjson::kArrayType); + pop.Evaluate(); - // must pass an allocator when the object may need to allocate memory - rapidjson::Document::AllocatorType &allocator = output.GetAllocator(); + if (print_statements) { + std::cout << "Numbers at age:\n"; + } + for (int i = 0; i < pop.nyears; i++) { + for (int j = 0; j < pop.nages; j++) { + if (print_statements) { + std::cout << pop.numbers_at_age[i * pop.nages + j] << " "; + } + array.push_back(pop.numbers_at_age[i * pop.nages + j]); + } + if (print_statements) { + std::cout << std::endl; + } + } + + output["NumbersAtAge"] = array; + + if (print_statements) { + std::cout << "\n\n" + << std::endl; + } - // create a rapidjson object type - // rapidjson::Value object(rapidjson::kObjectType); - // object.AddMember("NumbersAtAge", "50", allocator); - pop.Evaluate(); - if (print_statements) - { - std::cout << "Numbers at age:\n"; - } - for (int i = 0; i < pop.nyears; i++) - { - for (int j = 0; j < pop.nages; j++) - { - if (print_statements) - { - std::cout << pop.numbers_at_age[i * pop.nages + j] << " "; - } - array.PushBack(pop.numbers_at_age[i * pop.nages + j], allocator); - } - if (print_statements) - { - std::cout << std::endl; - } - } - if (print_statements) - { - std::cout << "\n\n" - << std::endl; + return pop.numbers_at_age; } - output.Accept(writer); - if (print_statements) - { - std::cout << buffer.GetString() << std::endl; + bool CheckModelOutput(fims::Population &pop, + JsonValue &output) { + return true; } - return pop.numbers_at_age; - } - - bool CheckModelOutput(fims::Population &pop, - rapidjson::Document &output) - { - return true; - } };