void Profile::Build() { string type = ""; string label = ""; string parameter = ""; string index = ""; /** * Explode the parameter string so we can get the estimable * name (parameter) and the index */ model_->objects().ExplodeString(parameter_, type, label, parameter, index); if (type == "" || label == "" || parameter == "") { LOG_ERROR_P(PARAM_PARAMETER) << ": parameter " << parameter_ << " is not in the correct format. Correct format is object_type[label].estimable(array index)"; } model_->objects().ImplodeString(type, label, parameter, index, parameter_); string error = ""; base::Object* target = model_->objects().FindObject(parameter_, error); if (!target) { LOG_ERROR_P(PARAM_PARAMETER) << ": parameter " << parameter_ << " is not a valid estimable in the system"; return; } target_ = target->GetEstimable(parameter); if (target_ == 0) LOG_ERROR_P(PARAM_PARAMETER) << ": parameter " << parameter_ << " is not a valid estimable in the system"; original_value_ = *target_; step_size_ = (upper_bound_ - lower_bound_) / (steps_ + 1); }
/** * Validate our Mortality Constant Rate process * * - Validate the required parameters * - Assign the label from the parameters * - Assign and validate remaining parameters * - Duplicate 'm' and 'selectivities' if only 1 vale specified * - Check m is between 0.0 and 1.0 * - Check the categories are real */ void TagLoss::DoValidate() { LOG_FINEST() << "Number of categories = " << category_labels_.size() << " number of proportions given = " << tag_loss_input_.size(); if (tag_loss_input_.size() == 1) tag_loss_input_.assign(category_labels_.size(), tag_loss_input_[0]); if (selectivity_names_.size() == 1) selectivity_names_.assign(category_labels_.size(), selectivity_names_[0]); if (tag_loss_input_.size() != category_labels_.size()) { LOG_ERROR_P(PARAM_TAG_LOSS_RATE) << ": Number of tag loss values provided is not the same as the number of categories provided. Expected: " << category_labels_.size()<< " but got " << tag_loss_input_.size(); } if (selectivity_names_.size() != category_labels_.size()) { LOG_ERROR_P(PARAM_SELECTIVITIES) << ": Number of selectivities provided is not the same as the number of categories provided. Expected: " << category_labels_.size()<< " but got " << selectivity_names_.size(); } // Validate type of tag loss if (tag_loss_type_ != "single") LOG_ERROR_P(PARAM_TAG_LOSS_TYPE) << tag_loss_type_ << " Is not an expected type. Values allowed are " << PARAM_SINGLE << " and " << PARAM_DOUBLE << " is coming soon"; if (tag_loss_type_ == PARAM_DOUBLE) LOG_ERROR() << PARAM_TAG_LOSS_TYPE << " " << PARAM_DOUBLE << " is not implemented yet"; // Validate our Ms are between 1.0 and 0.0 for (Double tag_loss : tag_loss_input_) { if (tag_loss < 0.0 || tag_loss > 1.0) LOG_ERROR_P(PARAM_TAG_LOSS_RATE) << ": m value " << AS_DOUBLE(tag_loss) << " must be between 0.0 and 1.0 (inclusive)"; } for (unsigned i = 0; i < tag_loss_input_.size(); ++i) tag_loss_[category_labels_[i]] = tag_loss_input_[i]; }
/** * Validate this selectivity. This will load the * values that were passed in from the configuration * file and assign them to the local variables. * * We'll then do some basic checks on the local * variables to ensure they are within the business * rules for the model. */ void AllValuesBounded::DoValidate() { unsigned min_age = model_->min_age(); unsigned max_age = model_->max_age(); // Param: L if (low_ < min_age) { LOG_ERROR_P(PARAM_L) << ": Parameter 'l' is less than the 'min_age' for the model\n" << "Model 'min_age' is " << min_age << " and 'l' is " << low_; } // Param: H if (high_ > max_age) { LOG_ERROR_P(PARAM_H) << ": Parameter 'h' is greater than the 'max_age' for the model\n" << "Model 'max_age' is " << max_age << " and 'h' is " << high_; } if (low_ >= high_) { LOG_ERROR_P(PARAM_L) << ": Parameter 'l' is greater than or equal to parameter 'h'\n" << "'l' = " << low_ << " and 'h' = " << high_; } // Param: V if (v_.size() != (high_ - low_)+1) { LOG_ERROR_P(PARAM_V) << ": Parameter 'v' does not have the right amount of elements n = h - l\n" << "Expected " << (high_ - low_) + 1 << " but got " << v_.size(); } }
/** * Validate our Survival Constant Rate process * * - Validate the required parameters * - Assign the label from the parameters * - Assign and validate remaining parameters * - Duplicate 's' and 'selectivities' if only 1 vale specified * - Check s is between 0.0 and 1.0 * - Check the categories are real */ void SurvivalConstantRate::DoValidate() { category_labels_ = model_->categories()->ExpandLabels(category_labels_, parameters_.Get(PARAM_CATEGORIES)); if (s_input_.size() == 1) s_input_.assign(category_labels_.size(), s_input_[0]); if (selectivity_names_.size() == 1) selectivity_names_.assign(category_labels_.size(), selectivity_names_[0]); if (s_input_.size() != category_labels_.size()) { LOG_ERROR_P(PARAM_S) << ": Number of Ms provided is not the same as the number of categories provided. Expected: " << category_labels_.size()<< " but got " << s_input_.size(); } if (selectivity_names_.size() != category_labels_.size()) { LOG_ERROR_P(PARAM_SELECTIVITIES) << ": Number of selectivities provided is not the same as the number of categories provided. Expected: " << category_labels_.size()<< " but got " << selectivity_names_.size(); } // Validate our Ms are between 1.0 and 0.0 for (Double s : s_input_) { if (s < 0.0 || s > 1.0) LOG_ERROR_P(PARAM_S) << ": m value " << AS_DOUBLE(s) << " must be between 0.0 and 1.0 (inclusive)"; } for (unsigned i = 0; i < s_input_.size(); ++i) m_[category_labels_[i]] = s_input_[i]; // Check categories are real for (const string& label : category_labels_) { if (!model_->categories()->IsValid(label)) LOG_ERROR_P(PARAM_CATEGORIES) << ": category " << label << " does not exist. Have you defined it?"; } }
void MortalityEventBiomass::DoValidate() { category_labels_ = model_->categories()->ExpandLabels(category_labels_, parameters_.Get(PARAM_CATEGORIES)); if (u_max_ <= 0.0 || u_max_ >= 1.0) LOG_ERROR_P(PARAM_U_MAX) << " (" << u_max_ << ") must be between 0.0 and 1.0 exclusive"; if (category_labels_.size() != selectivity_labels_.size()) LOG_ERROR_P(PARAM_SELECTIVITIES) << " number provided (" << selectivity_labels_.size() << ") must match the number of " "categories provided (" << category_labels_.size() << ")"; if (years_.size() != catches_.size()) LOG_ERROR_P(PARAM_CATCHES) << " number provided (" << catches_.size() << ") must match the number of " "years provided (" << years_.size() << ")"; // Validate: catches_ and years_ for(unsigned i = 0; i < years_.size(); ++i) { if (catch_years_.find(years_[i]) != catch_years_.end()) { LOG_ERROR_P(PARAM_YEARS) << " year " << years_[i] << " has already been specified, please remove the duplicate"; } catch_years_[years_[i]] = catches_[i]; } // add extra years in to model for things like forward projection vector<unsigned> model_years = model_->years(); for (unsigned year : model_years) { if (catch_years_.find(year) == catch_years_.end()) catch_years_[year] = 0.0; } }
void Iterative::DoBuild() { time_steps_ = model_->managers().time_step()->ordered_time_steps(); // Set the default process labels for the time step for this phase for (auto time_step : time_steps_) time_step->SetInitialisationProcessLabels(label_, time_step->process_labels()); // handle any new processes we want to insert for (string insert : insert_processes_) { vector<string> pieces; boost::split(pieces, insert, boost::is_any_of("()="), boost::token_compress_on); string target_process = pieces.size() == 3 ? pieces[1] : ""; string new_process = pieces.size() == 3 ? pieces[2] : pieces[1]; auto time_step = model_->managers().time_step()->GetTimeStep(pieces[0]); vector<string> process_labels = time_step->initialisation_process_labels(label_); if (target_process == "") { process_labels.insert(process_labels.begin(), new_process); } else { vector<string>::iterator iter = std::find(process_labels.begin(), process_labels.end(), target_process); if (iter == process_labels.end()) LOG_ERROR_P(PARAM_INSERT_PROCESSES) << " process " << target_process << " does not exist in time step " << time_step->label(); process_labels.insert(iter, new_process); } time_step->SetInitialisationProcessLabels(label_, process_labels); } // handle the excludes we've specified for (string exclude : exclude_processes_) { unsigned count = 0; for (auto time_step : time_steps_) { vector<string> process_labels = time_step->initialisation_process_labels(label_); unsigned size_before = process_labels.size(); process_labels.erase(std::remove_if(process_labels.begin(), process_labels.end(), [exclude](string& ex) { return exclude == ex; }), process_labels.end()); unsigned diff = size_before - process_labels.size(); time_step->SetInitialisationProcessLabels(label_, process_labels); count += diff; } if (count == 0) LOG_ERROR_P(PARAM_EXCLUDE_PROCESSES) << " process " << exclude << " does not exist in any time steps to be excluded. Please check your spelling"; } if (convergence_years_.size() != 0) { std::sort(convergence_years_.begin(), convergence_years_.end()); if ((*convergence_years_.rbegin()) != years_) convergence_years_.push_back(years_); } // Build our partition vector<string> categories = model_->categories()->category_names(); partition_.Init(categories); cached_partition_.Init(categories); }
/** * Build any objects that will need to be utilised by this object. * Obtain smart_pointers to any objects that will be used by this object. */ void Data::DoBuild() { length_weight_ = model_->managers().length_weight()->GetLengthWeight(length_weight_label_); if (!length_weight_) LOG_ERROR_P(PARAM_LENGTH_WEIGHT) << "(" << length_weight_label_ << ") could not be found. Have you defined it?"; if (!data_table_) LOG_CODE_ERROR() << "!data_table_"; // basic validation const vector<string>& columns = data_table_->columns(); if (columns.size() != model_->age_spread() + 1) LOG_ERROR_P(PARAM_DATA) << "column count (" << columns.size() << ") must be <year> <ages> for a total of " << model_->age_spread() + 1 << " columns"; if (columns[0] != PARAM_YEAR) LOG_ERROR_P(PARAM_DATA) << "first column label must be 'year'. First column label was '" << columns[0] << "'"; /** * Build our data_by_year map so we can fill the gaps * and use it in the model */ vector<vector<string>>& data = data_table_->data(); vector<Double> total_length(model_->age_spread(), 0.0); Double number_of_years = 0.0; for (vector<string> row : data) { if (row.size() != columns.size()) LOG_CODE_ERROR() << "row.size() != columns.size()"; number_of_years += 1; unsigned year = utilities::ToInline<string, unsigned>(row[0]); for (unsigned i = 1; i < row.size(); ++i) { data_by_year_[year].push_back(utilities::ToInline<string, Double>(row[i])); total_length[i - 1] += utilities::ToInline<string, Double>(row[i]); } } /* * Build our average map for use in initialisation and simulation phases */ for (unsigned i = 0; i < model_->age_spread(); ++i) data_by_age_[model_->min_age() + i] = total_length[i] / number_of_years; /** * Check if we're using a mean method and build a vector of means now * before we modify the data_by_year object by filling the external * gaps */ if (external_gaps_ == PARAM_MEAN || internal_gaps_ == PARAM_MEAN) { for (unsigned i = 0; i < model_->age_spread(); ++i) { Double total = 0.0; for (auto iter = data_by_year_.begin(); iter != data_by_year_.end(); ++iter) total += iter->second[i]; means_.push_back(total / data_by_year_.size()); } } // Fill our gaps FillExternalGaps(); FillInternalGaps(); }
/** * Validate this selectivity. This will load the * values that were passed in from the configuration * file and assign them to the local variables. * * We'll then do some basic checks on the local * variables to ensure they are within the business * rules for the model. */ void DoubleNormal::DoValidate() { if (alpha_ <= 0.0) LOG_ERROR_P(PARAM_MU) << ": alpha cannot be less than or equal to 0.0"; if (sigma_l_ <= 0.0) LOG_ERROR_P(PARAM_SIGMA_L) << ": sigma_l cannot be less than or equal to 0.0"; if (sigma_r_ <= 0.0) LOG_ERROR_P(PARAM_SIGMA_R) << ": sigmal_r cannot be less than or equal to 0.0"; }
/** * Validate the parameters passed in from the configuration file */ void Cinitial::DoValidate() { LOG_TRACE(); min_age_ = model_->min_age(); max_age_ = model_->max_age(); if (max_age_ < min_age_) LOG_ERROR_P(PARAM_MIN_AGE) << "(" << min_age_ << ") cannot be less than the max age(" << max_age_ << ")"; column_count_ = (max_age_ - min_age_) + 2; /** * Convert the string values to doubles and load them in to a table. */ vector<vector<string>>& data = n_table_->data(); unsigned row_number = 1; for (auto row : data) { string row_label = row[0]; // CHeck that it is a valid category bool check_combined = model_->categories()->IsCombinedLabels(row_label); LOG_FINEST() << "Checking row with label = " << row_label; if (find(category_labels_.begin(),category_labels_.end(), row_label )== category_labels_.end()) LOG_FATAL_P(PARAM_N) << " Could not find '" << row_label << "' in the categories supplied, please make sure that categories supplied is the same as the row labels."; if (check_combined) { vector<string> split_category_labels; boost::split(split_category_labels, row_label, boost::is_any_of("+")); unsigned category_iter = 0; for (const string& split_category_label : split_category_labels) { if (!model_->categories()->IsValid(split_category_label)) { LOG_FATAL_P(PARAM_N)<< ": The category " << split_category_label << " is not a valid category."; } ++category_iter; } } else { if (!model_->categories()->IsValid(row_label)) LOG_FATAL_P(PARAM_N) << ": The category " << row_label << " is not a valid category."; } // convert to lower case row_label = utilities::ToLowercase(row_label); if (row.size() != column_count_) LOG_ERROR_P(PARAM_N) << "the " << row_number << "the row has " << row.size() << " values but " << column_count_ << " values are expected"; if (n_.find(row_label) != n_.end()) LOG_ERROR_P(PARAM_N) << "the category " << row_label << " is defined more than once. You can only define a category once"; for (unsigned i = 1; i < row.size(); ++i) { Double temp = Double(); if (!utilities::To<Double>(row[i], temp)) LOG_ERROR_P(PARAM_N) << "value (" << row[i] << ") in row " << row_number << " is not a valid numeric"; n_[row_label].push_back(temp); } row_number++; } }
/** * Validate our Mortality Event Process * * 1. Check for the required parameters * 2. Assign any remaining variables */ void MortalityInitialisationEventBiomass::DoValidate() { // Validate that the number of selectivities is the same as the number of categories if (category_labels_.size() != selectivity_names_.size()) { LOG_ERROR_P(PARAM_SELECTIVITIES) << " Number of selectivities provided does not match the number of categories provided." << " Expected " << category_labels_.size() << " but got " << selectivity_names_.size(); } // Validate u_max if (u_max_ < 0.0 || u_max_ > 1.0) LOG_ERROR_P(PARAM_U_MAX) << ": u_max must be between 0.0 and 1.0 (inclusive). Value defined was " << AS_DOUBLE(u_max_); }
void SumToOne::DoValidate() { LOG_TRACE(); if (parameters_.Get(PARAM_UPPER_BOUND)->has_been_defined() & parameters_.Get(PARAM_LOWER_BOUND)->has_been_defined()) { if (estimate_labels_.size() > 2) LOG_WARNING() << "This estimate transformation was specked for two parameters if you have more than this, be cautious using this transformation"; if (upper_bounds_.size() != lower_bounds_.size()) LOG_ERROR_P(PARAM_LOWER_BOUND) << "You must supple the same number of upper and lower bounds. We found '" << estimate_labels_.size() << "' estimate labels and '" << lower_bounds_.size() << "' bounds, please sort this out or look in the manual"; if ((estimate_labels_.size() - 1) != lower_bounds_.size()) LOG_ERROR_P(PARAM_ESTIMATE_LABELS) << "You must supple one less bound than estimate labels. We found '" << upper_bounds_.size() << "' upper bound values and '" << lower_bounds_.size() << "' lower bound values, please sort this out chairs"; } }
/** * Populate any parameters, * Validate values are within expected ranges when we cannot use bind<>() overloads * * Note: all parameters are populated from configuration files */ void MortalityPreySuitability::DoValidate() { // Check length of categories are the same as selectivities if (prey_category_labels_.size() != prey_selectivity_labels_.size()) LOG_ERROR_P(PARAM_PREY_CATEGORIES) << ": You provided (" << prey_selectivity_labels_.size() << ") prey selectivities but we have " << prey_category_labels_.size() << " prey catregories"; if (predator_category_labels_.size() != predator_selectivity_labels_.size()) LOG_ERROR_P(PARAM_PREY_CATEGORIES) << ": You provided (" << predator_selectivity_labels_.size() << ") predator selectivities but we have " << predator_category_labels_.size() << " predator categories"; if (prey_category_labels_.size() != electivities_.size()) LOG_ERROR_P(PARAM_ELECTIVITIES) << ": You provided (" << prey_category_labels_.size() << ") prey categories but we have " << electivities_.size() << " prey electivities, these must be equal"; }
void TimeStepAbundance::DoBuild() { Abundance::DoBuild(); if (time_step_proportion_ < 0.0 || time_step_proportion_ > 1.0) LOG_ERROR_P(PARAM_TIME_STEP_PROPORTION) << ": time_step_proportion (" << AS_DOUBLE(time_step_proportion_) << ") must be between 0.0 and 1.0"; proportion_of_time_ = time_step_proportion_; auto time_step = model_->managers().time_step()->GetTimeStep(time_step_label_); if (!time_step) { LOG_ERROR_P(PARAM_TIME_STEP) << time_step_label_ << " could not be found. Have you defined it?"; } else { for (unsigned year : years_) time_step->SubscribeToBlock(this, year); } }
/** * Build our relationships between this object and other objects */ void Project::DoBuild() { project_ = model_->managers().project()->GetProject(project_label_); if (!project_) { LOG_ERROR_P(PARAM_PROJECT) << "project " << project_label_ << " could not be found. Have you defined it?"; } }
/** * Build our time step */ void TimeStep::Build() { // Get the pointers to our processes processes::Manager& process_manager = *model_->managers().process(); for (string process_name : process_names_) { Process* process = process_manager.GetProcess(process_name); if (!process) { LOG_ERROR_P(PARAM_PROCESSES) << ": process " << process_name << " does not exist. Have you defined it?"; } else processes_.push_back(process); } LOG_FINE() << "Time step " << label_ << " has " << processes_.size() << " processes"; /** * Find the range of our mortality block. This block encompasses the * first continuous collection of mortality processes within the time * step. */ mortality_block_.first = processes_.size(); mortality_block_.second = processes_.size() - 1; bool finished_mortality_block = false; for (unsigned i = 0; i < processes_.size(); ++i) { if (processes_[i]->process_type() == ProcessType::kMortality && !finished_mortality_block) { mortality_block_.first = mortality_block_.first == processes_.size() ? i : mortality_block_.first; mortality_block_.second = i; } else if (processes_[i]->process_type() == ProcessType::kMortality && finished_mortality_block) { LOG_FATAL() << "Mortality processes within a time step need to be consecutive (i.e. a single mortality block)"; } else if (mortality_block_.first != processes_.size()) finished_mortality_block = true; } mortality_block_.second = mortality_block_.first == processes_.size() ? mortality_block_.first : mortality_block_.second; }
/** * Build any objects that will need to be utilised by this object. * Obtain smart_pointers to any objects that will be used by this object. */ void AgeLength::Build() { unsigned time_step_count = model_->managers().time_step()->ordered_time_steps().size(); if (time_step_proportions_.size() == 0) { time_step_proportions_.assign(time_step_count, 0.0); } else if (time_step_count != time_step_proportions_.size()) { LOG_ERROR_P(PARAM_TIME_STEP_PROPORTIONS) << "size (" << time_step_proportions_.size() << ") must match the number " "of defined time steps for this process (" << time_step_count << ")"; } for (auto iter : time_step_proportions_) { if (iter < 0.0 || iter > 1.0) LOG_ERROR_P(PARAM_TIME_STEP_PROPORTIONS) << " value (" << iter << ") must be in the range 0.0-1.0"; } DoBuild(); BuildCV(); }
/** * Build our relationships between this object and other objects */ void Process::DoBuild() { process_ = model_->managers().process()->GetProcess(process_label_); if (!process_) { LOG_ERROR_P(PARAM_PROCESS) << "process " << process_label_ << " could not be found. Have you defined it?"; } process_->flag_print_report(); }
void Iterative::DoValidate() { for (string insert : insert_processes_) { vector<string> pieces; boost::split(pieces, insert, boost::is_any_of("()="), boost::token_compress_on); if (pieces.size() != 2 && pieces.size() != 3) LOG_ERROR_P(PARAM_INSERT_PROCESSES) << " value " << insert << " does not match the format time_step(process)=new_process = " << pieces.size(); } }
/** * Build any runtime relationships we may have and ensure * the labels for other objects are valid. */ void ProcessRemovalsByLength::DoBuild() { partition_ = CombinedCategoriesPtr(new niwa::partition::accessors::CombinedCategories(model_, category_labels_)); cached_partition_ = CachedCombinedCategoriesPtr(new niwa::partition::accessors::cached::CombinedCategories(model_, category_labels_)); // if (ageing_error_label_ != "") // LOG_CODE_ERROR() << "ageing error has not been implemented for the proportions at age observation"; length_results_.resize(number_bins_ * category_labels_.size(), 0.0); auto time_step = model_->managers().time_step()->GetTimeStep(time_step_label_); if (!time_step) { LOG_FATAL_P(PARAM_TIME_STEP)<< time_step_label_ << " could not be found. Have you defined it?"; } else { auto process = time_step->SubscribeToProcess(this, years_, process_label_); mortality_instantaneous_ = dynamic_cast<MortalityInstantaneous*>(process); } if (!mortality_instantaneous_) LOG_ERROR_P(PARAM_PROCESS) << "This observation can only be used for Process of type = " << PARAM_MORTALITY_INSTANTANEOUS; // Need to split the categories if any are combined for checking vector<string> temp_split_category_labels, split_category_labels; for (const string& category_label : category_labels_) { boost::split(temp_split_category_labels, category_label, boost::is_any_of("+")); for (const string& split_category_label : temp_split_category_labels) { split_category_labels.push_back(split_category_label); } } // Need to make this a vector so its compatible with the function couldn't be bothered templating sorry vector<string> methods; methods.push_back(method_); // Do some checks so that the observation and process are compatible if (!mortality_instantaneous_->check_methods_for_removal_obs(methods)) LOG_ERROR_P(PARAM_METHOD_OF_REMOVAL) << "could not find all these methods in the instantaneous_mortality process labeled " << process_label_ << " please check that the methods are compatible with this process"; if (!mortality_instantaneous_->check_categories_in_methods_for_removal_obs(methods, split_category_labels)) LOG_ERROR_P(PARAM_CATEGORIES) << "could not find all these categories in the instantaneous_mortality process labeled " << process_label_ << " please check that the categories are compatible with this process"; if (!mortality_instantaneous_->check_years_in_methods_for_removal_obs(years_, methods)) LOG_ERROR_P(PARAM_YEARS) << "could not find catches in all years in the instantaneous_mortality process labeled " << process_label_ << " please check that the years are compatible with this process"; }
void Linear::DoBuild() { string error = ""; target_object_ = model_->objects().FindObject(parameter_, error); Estimable::Type estimable_type = model_->objects().GetEstimableType(parameter_, error); if( estimable_type != Estimable::kSingle) LOG_ERROR_P(PARAM_TYPE) << "@time_varying blocks of type " << PARAM_LINEAR << " can only be implemented in parameters that are scalars or single values"; DoReset(); }
/** * Build the runtime relationships required * - Build partition reference */ void MortalityInitialisationEventBiomass::DoBuild() { partition_.Init(category_labels_); for (string label : selectivity_names_) { Selectivity* selectivity = model_->managers().selectivity()->GetSelectivity(label); if (!selectivity) LOG_ERROR_P(PARAM_SELECTIVITIES) << ": selectivity " << label << " does not exist. Have you defined it?"; selectivities_.push_back(selectivity); } if (penalty_name_ != "") { penalty_ = model_->managers().penalty()->GetProcessPenalty(penalty_name_); if (!penalty_) { LOG_ERROR_P(PARAM_PENALTY) << ": penalty " << penalty_name_ << " does not exist. Have you defined it?"; } } }
/** * Build our parameters */ void VectorSmoothing::DoBuild() { string type = ""; string label = ""; string parameter = ""; string index = ""; /** * Explode the parameter string sive o we can get the estimable * name (parameter) and the index */ if (parameter_ == "") { parameters().Add(PARAM_PARAMETER, label_, parameters_.Get(PARAM_LABEL)->file_name(), parameters_.Get(PARAM_LABEL)->line_number()); parameter_ = label_; } model_->objects().ExplodeString(parameter_, type, label, parameter, index); if (type == "" || label == "" || parameter == "") { LOG_ERROR_P(PARAM_PARAMETER) << ": parameter " << parameter_ << " is not in the correct format. Correct format is object_type[label].estimable(array index)"; } string error = ""; base::Object* target = model_->objects().FindObject(parameter_, error); if (!target) LOG_ERROR_P(PARAM_PARAMETER) << " " << parameter_ << " is not a valid estimable in the system"; Estimable::Type estimable_type = target->GetEstimableType(parameter); switch(estimable_type) { case Estimable::kInvalid: LOG_CODE_ERROR() << "Invalid estimable type: " << parameter_; break; case Estimable::kVector: estimable_vector_ = target->GetEstimableVector(parameter); break; case Estimable::kUnsignedMap: estimable_map_ = target->GetEstimableUMap(parameter); break; default: LOG_ERROR() << "The estimable you have provided for use in a additional priors: " << parameter_ << " is not a type that is supported for this class of additional prior"; break; } }
/** * Populate any parameters, * Validate values are within expected ranges when we cannot use bind<>() overloads * * Note: all parameters are populated from configuration files */ void DerivedQuantity::Validate() { parameters_.Populate(); category_labels_ = model_->categories()->ExpandLabels(category_labels_, parameters_.Get(PARAM_CATEGORIES)); // Validate Categories auto categories = model_->categories(); for (const string& label : category_labels_) { if (!categories->IsValid(label)) LOG_ERROR_P(PARAM_CATEGORIES) << ": category " << label << " does not exist. Have you defined it?"; } if (proportion_method_ == PARAM_WEIGHTED_PRODUCT) mean_proportion_method_ = false; if (category_labels_.size() != selectivity_labels_.size()) LOG_ERROR_P(PARAM_SELECTIVITIES) << " count (" << selectivity_labels_.size() << ") " << " is not the same as the categories count (" << category_labels_.size() << ")"; }
/** * Build any objects that will need to be utilised by this object. * Validate any parameters that require information from other objects * in the system */ void MortalityPreySuitability::DoBuild() { prey_partition_ = CombinedCategoriesPtr(new niwa::partition::accessors::CombinedCategories(model_, prey_category_labels_)); predator_partition_ = CombinedCategoriesPtr(new niwa::partition::accessors::CombinedCategories(model_, predator_category_labels_)); /** * Assign the selectivity, penalty and time step index to each fisher data object */ unsigned category_offset = 0; for (string selectivity : prey_selectivity_labels_) { prey_selectivities_.push_back(model_->managers().selectivity()->GetSelectivity(selectivity)); if (!prey_selectivities_[category_offset]) LOG_ERROR_P(PARAM_PREY_SELECTIVITIES) << "selectivity " << selectivity << " does not exist. Have you defined it?"; ++category_offset; } category_offset = 0; for (string selectivity : predator_selectivity_labels_) { predator_selectivities_.push_back(model_->managers().selectivity()->GetSelectivity(selectivity)); if (!predator_selectivities_[category_offset]) LOG_ERROR_P(PARAM_PREDATOR_SELECTIVITIES) << "selectivity " << selectivity << " does not exist. Have you defined it?"; ++category_offset; } if (penalty_label_ != "none") { penalty_ = model_->managers().penalty()->GetProcessPenalty(penalty_label_); if (!penalty_) LOG_ERROR_P(PARAM_PENALTY) << ": penalty " << penalty_label_ << " does not exist. Have you defined it?"; } /* * * Check All the categories are valid for (const string& label : prey_category_labels_) { if (!model_->categories()->IsValid(label)) LOG_ERROR_P(PARAM_PREY_CATEGORIES) << ": category " << label << " does not exist. Have you defined it?"; } for (const string& label : predator_category_labels_) { if (!model_->categories()->IsValid(label)) LOG_ERROR_P(PARAM_PREDATOR_CATEGORIES) << ": category " << label << " does not exist. Have you defined it?"; }*/ }
/** * Build any runtime relationships * - Build the partition accessor * - Build our list of selectivities * - Build our ratios for the number of time steps */ void TagLoss::DoBuild() { partition_.Init(category_labels_); for (string label : selectivity_names_) { Selectivity* selectivity = model_->managers().selectivity()->GetSelectivity(label); if (!selectivity) LOG_ERROR_P(PARAM_SELECTIVITIES) << ": selectivity " << label << " does not exist. Have you defined it?"; selectivities_.push_back(selectivity); } /** * Organise our time step ratios. Each time step can * apply a different ratio of M so here we want to verify * we have enough and re-scale them to 1.0 */ vector<TimeStep*> time_steps = model_->managers().time_step()->ordered_time_steps(); LOG_FINEST() << "time_steps.size(): " << time_steps.size(); vector<unsigned> active_time_steps; for (unsigned i = 0; i < time_steps.size(); ++i) { if (time_steps[i]->HasProcess(label_)) active_time_steps.push_back(i); } if (ratios_.size() == 0) { for (unsigned i : active_time_steps) time_step_ratios_[i] = 1.0; } else { if (ratios_.size() != active_time_steps.size()) LOG_FATAL_P(PARAM_TIME_STEP_RATIO) << " length (" << ratios_.size() << ") does not match the number of time steps this process has been assigned to (" << active_time_steps.size() << ")"; for (Double value : ratios_) { if (value < 0.0 || value > 1.0) LOG_ERROR_P(PARAM_TIME_STEP_RATIO) << " value (" << value << ") must be between 0.0 (inclusive) and 1.0 (inclusive)"; } for (unsigned i = 0; i < ratios_.size(); ++i) time_step_ratios_[active_time_steps[i]] = ratios_[i]; } }
/** * Validate */ void Constant::DoValidate() { if (values_.size() != 1 && values_.size() != years_.size()) { LOG_ERROR_P(PARAM_VALUES) << "length (" << values_.size() << ") must match the number of years provided (" << years_.size() << ")"; return; } if (values_.size() == 1) values_.assign(years_.size(), values_[0]); for (unsigned i = 0; i < years_.size(); ++i) { parameter_by_year_[years_[i]] = values_[i]; } }
/** * Build any runtime relationships this class needs. * - Build the partition accessors * - Verify the selectivities are valid * - Get pointers to the selectivities */ void TransitionCategory::DoBuild() { LOG_TRACE(); from_partition_.Init(from_category_names_); to_partition_.Init(to_category_names_); for(string label : selectivity_names_) { Selectivity* selectivity = model_->managers().selectivity()->GetSelectivity(label); if (!selectivity) LOG_ERROR_P(PARAM_SELECTIVITIES) << ": Selectivity " << label << " does not exist. Have you defined it?"; selectivities_.push_back(selectivity); } }
/** * Populate any parameters, * Validate values are within expected ranges when we cannot use bind<>() overloads * * Note: all parameters are populated from configuration files */ void MortalityPreySuitability::DoValidate() { /** * Now go through each category and split it if required, then check each piece to ensure * it's a valid category */ Categories* categories = model_->categories(); vector<string> split_prey_category_labels; for (const string& category_label : prey_category_labels_) { boost::split(split_prey_category_labels, category_label, boost::is_any_of("+")); for (const string& split_category_label : split_prey_category_labels) { if (!categories->IsValid(split_category_label)) { if (split_category_label == category_label) { LOG_ERROR_P(PARAM_PREY_CATEGORIES) << ": The category " << split_category_label << " is not a valid category."; } else { LOG_ERROR_P(PARAM_PREY_CATEGORIES) << ": The category " << split_category_label << " is not a valid category." << " It was defined in the category collection " << category_label; } } } } vector<string> split_predator_category_labels; for (const string& category_label : predator_category_labels_) { boost::split(split_predator_category_labels, category_label, boost::is_any_of("+")); for (const string& split_category_label : split_predator_category_labels) { if (!categories->IsValid(split_category_label)) { if (split_category_label == category_label) { LOG_ERROR_P(PARAM_PREDATOR_CATEGORIES) << ": The category " << split_category_label << " is not a valid category."; } else { LOG_ERROR_P(PARAM_PREDATOR_CATEGORIES) << ": The category " << split_category_label << " is not a valid category." << " It was defined in the category collection " << category_label; } } } } // Check length of categories are the same as selectivities if (prey_category_labels_.size() != prey_selectivity_labels_.size()) LOG_ERROR_P(PARAM_PREY_CATEGORIES) << ": You provided (" << prey_selectivity_labels_.size() << ") prey selectivities but we have " << prey_category_labels_.size() << " prey catregories"; if (predator_category_labels_.size() != predator_selectivity_labels_.size()) LOG_ERROR_P(PARAM_PREY_CATEGORIES) << ": You provided (" << predator_selectivity_labels_.size() << ") predator selectivities but we have " << predator_category_labels_.size() << " predator categories"; if (prey_category_labels_.size() != electivities_.size()) LOG_ERROR_P(PARAM_ELECTIVITIES) << ": You provided (" << prey_category_labels_.size() << ") prey categories but we have " << electivities_.size() << " prey electivities, these must be equal"; }
/** * Build any objects that will need to be utilised by this object. * Obtain smart_pointers to any objects that will be used by this object. */ void DerivedQuantity::Build() { LOG_TRACE(); partition_.Init(category_labels_); selectivities::Manager& selectivity_manager = *model_->managers().selectivity(); for (string label : selectivity_labels_) { Selectivity* selectivity = selectivity_manager.GetSelectivity(label); if (!selectivity) LOG_ERROR_P(PARAM_SELECTIVITIES) << " (" << label << ") could not be found. Have you defined it?"; selectivities_.push_back(selectivity); } /** * ensure the time steps we have are valid */ TimeStep* time_step = model_->managers().time_step()->GetTimeStep(time_step_label_); if (!time_step) LOG_ERROR_P(PARAM_TIME_STEP) << " (" << time_step_label_ << ") could not be found. Have you defined it?"; time_step->SubscribeToBlock(this); time_step->SubscribeToInitialisationBlock(this); }
/** * Build our process proportions by category */ void ProcessProportionsByCategory::DoBuild() { ProportionsByCategory::DoBuild(); if (process_proportion_ < 0.0 || process_proportion_ > 1.0) LOG_ERROR_P(PARAM_PROCESS_PROPORTION) << ": process_proportion (" << AS_DOUBLE(process_proportion_) << ") must be between 0.0 and 1.0"; proportion_of_time_ = process_proportion_; auto time_step = model_->managers().time_step()->GetTimeStep(time_step_label_); if (!time_step) { LOG_FATAL_P(PARAM_TIME_STEP) << time_step_label_ << " could not be found. Have you defined it?"; } else { for (unsigned year : years_) time_step->SubscribeToProcess(this, year, process_label_); } }