void ProportionsMigrating::Execute() { LOG_TRACE(); /** * Verify our cached partition and partition sizes are correct */ auto cached_partition_iter = cached_partition_->Begin(); auto partition_iter = partition_->Begin(); // vector<vector<partition::Category> > /** * Loop through the provided categories. Each provided category (combination) will have a list of observations * with it. We need to build a vector of proportions for each age using that combination and then * compare it to the observations. */ LOG_FINEST() << "Number of categories " << category_labels_.size(); for (unsigned category_offset = 0; category_offset < category_labels_.size(); ++category_offset, ++partition_iter, ++cached_partition_iter) { Double start_value = 0.0; Double end_value = 0.0; vector<Double> expected_values(age_spread_, 0.0); vector<Double> numbers_age_before((model_->age_spread() + 1), 0.0); vector<Double> numbers_age_after((model_->age_spread() + 1), 0.0); /** * Loop through the 2 combined categories building up the * expected proportions values. */ auto category_iter = partition_iter->begin(); auto cached_category_iter = cached_partition_iter->begin(); for (; category_iter != partition_iter->end(); ++cached_category_iter, ++category_iter) { for (unsigned data_offset = 0; data_offset < (*category_iter)->data_.size(); ++data_offset) { // We now need to loop through all ages to apply ageing misclassification matrix to account // for ages older than max_age_ that could be classified as an individual within the observation range unsigned age = ( (*category_iter)->min_age_ + data_offset); start_value = (*cached_category_iter).data_[data_offset]; end_value = (*category_iter)->data_[data_offset]; numbers_age_before[data_offset] += start_value; numbers_age_after[data_offset] += end_value; LOG_FINE() << "----------"; LOG_FINE() << "Category: " << (*category_iter)->name_ << " at age " << age; LOG_FINE() << "start_value: " << start_value << "; end_value: " << end_value; } } /* * Apply Ageing error on numbers at age before and after */ if (ageing_error_label_ != "") { vector<vector<Double>>& mis_matrix = ageing_error_->mis_matrix(); vector<Double> temp_before(numbers_age_before.size(), 0.0); vector<Double> temp_after(numbers_age_after.size(), 0.0); for (unsigned i = 0; i < mis_matrix.size(); ++i) { for (unsigned j = 0; j < mis_matrix[i].size(); ++j) { temp_before[j] += numbers_age_before[i] * mis_matrix[i][j]; temp_after[j] += numbers_age_after[i] * mis_matrix[i][j]; } } numbers_age_before = temp_before; numbers_age_after = temp_after; } /* * Now collapse the number_age into out expected values */ Double plus_before = 0, plus_after = 0; for (unsigned k = 0; k < numbers_age_before.size(); ++k) { // this is the difference between the unsigned age_offset = min_age_ - model_->min_age(); if (numbers_age_before[k] > 0) { if (k >= age_offset && (k - age_offset + min_age_) <= max_age_) { expected_values[k - age_offset] = (numbers_age_before[k] - numbers_age_after[k]) / numbers_age_before[k]; LOG_FINEST() << "Numbers before migration = " << numbers_age_before[k] << " numbers after migration = " << numbers_age_after[k] << " proportion migrated = " << expected_values[k - age_offset]; } if (((k - age_offset + min_age_) > max_age_) && age_plus_) { plus_before += numbers_age_before[k]; plus_after += numbers_age_after[k]; } } else { if (k >= age_offset && (k - age_offset + min_age_) <= max_age_) expected_values[k] = 0; if (((k - age_offset + min_age_) > max_age_) && age_plus_) { plus_before += 0; plus_after += 0; } } } LOG_FINEST() << "Plus group before migration = " << plus_before << " Plus group after migration = " << plus_after; if (age_plus_) expected_values[age_spread_ - 1] = (plus_before - plus_after) / plus_before; if (expected_values.size() != proportions_[model_->current_year()][category_labels_[category_offset]].size()) LOG_CODE_ERROR() << "expected_values.size(" << expected_values.size() << ") != proportions_[category_offset].size(" << proportions_[model_->current_year()][category_labels_[category_offset]].size() << ")"; /** * save our comparisons so we can use them to generate the score from the likelihoods later */ for (unsigned i = 0; i < expected_values.size(); ++i) { LOG_FINEST() << " Numbers at age " << min_age_ + i << " = " << expected_values[i]; SaveComparison(category_labels_[category_offset], min_age_ + i ,0.0 ,expected_values[i], proportions_[model_->current_year()][category_labels_[category_offset]][i], process_errors_by_year_[model_->current_year()], error_values_[model_->current_year()][category_labels_[category_offset]][i], delta_, 0.0); } } }
void ProcessRemovalsByLength::Execute() { LOG_TRACE(); /** * Verify our cached partition and partition sizes are correct */ // auto categories = model_->categories(); unsigned year = model_->current_year(); unsigned year_index = year - model_->start_year(); unsigned time_step = model_->managers().time_step()->current_time_step(); auto cached_partition_iter = cached_partition_->Begin(); auto partition_iter = partition_->Begin(); // vector<vector<partition::Category> > map<unsigned, map<string, map<string, vector<Double>>>> &Removals_at_age = mortality_instantaneous_->catch_at(); /** * Loop through the provided categories. Each provided category (combination) will have a list of observations * with it. We need to build a vector of proportions for each length using that combination and then * compare it to the observations. */ for (unsigned category_offset = 0; category_offset < category_labels_.size(); ++category_offset, ++partition_iter, ++cached_partition_iter) { LOG_FINEST() << "category: " << category_labels_[category_offset]; Double start_value = 0.0; Double end_value = 0.0; Double number_at_age = 0.0; // LOG_WARNING() << "This is bad code because it allocates memory in the middle of an execute"; vector<Double> expected_values(number_bins_, 0.0); vector<Double> numbers_at_length; vector<vector<Double>> age_length_matrix; /** * Loop through the 2 combined categories building up the * expected proportions values. */ auto category_iter = partition_iter->begin(); auto cached_category_iter = cached_partition_iter->begin(); for (; category_iter != partition_iter->end(); ++cached_category_iter, ++category_iter) { // AgeLength* age_length = categories->age_length((*category_iter)->name_); // LOG_WARNING() << "This is bad code because it allocates memory in the middle of an execute"; age_length_matrix.resize((*category_iter)->data_.size()); vector<Double> age_frequencies(length_bins_.size(), 0.0); const auto& age_length_proportions = model_->partition().age_length_proportions((*category_iter)->name_)[year_index][time_step]; for (unsigned data_offset = 0; data_offset < (*category_iter)->data_.size(); ++data_offset) { unsigned age = ((*category_iter)->min_age_ + data_offset); // Calculate the age structure removed from the fishing process number_at_age = Removals_at_age[year][method_][(*category_iter)->name_][data_offset]; LOG_FINEST() << "Numbers at age = " << age << " = " << number_at_age << " start value : " << start_value << " end value : " << end_value; // Implement an algorithm similar to DoAgeLengthConversion() to convert numbers at age to numbers at length // This is different to DoAgeLengthConversion as this number is now not related to the partition // Double mu= (*category_iter)->mean_length_by_time_step_age_[time_step][age]; // LOG_FINEST() << "mean = " << mu << " cv = " << age_length->cv(year, time_step, age) << " distribution = " << age_length->distribution_label() << " and length plus group = " << length_plus_; // age_length->CummulativeNormal(mu, age_length->cv(year, time_step, age), age_frequencies, length_bins_, length_plus_); // LOG_WARNING() << "This is bad code because it allocates memory in the middle of an execute"; age_length_matrix[data_offset].resize(number_bins_); // Loop through the length bins and multiple the partition of the current age to go from // length frequencies to age length numbers for (unsigned j = 0; j < number_bins_; ++j) { age_length_matrix[data_offset][j] = number_at_age * age_length_proportions[data_offset][j]; LOG_FINEST() << "The proportion of fish in length bin : " << length_bins_[j] << " = " << age_frequencies[j]; } } if (age_length_matrix.size() == 0) LOG_CODE_ERROR()<< "if (age_length_matrix_.size() == 0)"; numbers_at_length.assign(age_length_matrix[0].size(), 0.0); for (unsigned i = 0; i < age_length_matrix.size(); ++i) { for (unsigned j = 0; j < age_length_matrix[i].size(); ++j) { numbers_at_length[j] += age_length_matrix[i][j]; } } for (unsigned length_offset = 0; length_offset < number_bins_; ++length_offset) { LOG_FINEST() << " numbers for length bin : " << length_bins_[length_offset] << " = " << numbers_at_length[length_offset]; expected_values[length_offset] += numbers_at_length[length_offset]; LOG_FINE() << "----------"; LOG_FINE() << "Category: " << (*category_iter)->name_ << " at length " << length_bins_[length_offset]; LOG_FINE() << "start_value: " << start_value << "; end_value: " << end_value << "; final_value: " << numbers_at_length[length_offset]; LOG_FINE() << "expected_value becomes: " << expected_values[length_offset]; } } if (expected_values.size() != proportions_[model_->current_year()][category_labels_[category_offset]].size()) LOG_CODE_ERROR()<< "expected_values.size(" << expected_values.size() << ") != proportions_[category_offset].size(" << proportions_[model_->current_year()][category_labels_[category_offset]].size() << ")"; /** * save our comparisons so we can use them to generate the score from the likelihoods later */ for (unsigned i = 0; i < expected_values.size(); ++i) { SaveComparison(category_labels_[category_offset], 0, length_bins_[i], expected_values[i], proportions_[model_->current_year()][category_labels_[category_offset]][i], process_errors_by_year_[model_->current_year()], error_values_[model_->current_year()][category_labels_[category_offset]][i], 0.0, delta_, 0.0); } } }
/** * Save the comparison that was done during an observation to the list of comparisons. Each comparison contributes part to a score * and we will need to know what those parts are when reporting. * * @param category The name of the comparison * @param age The age of the population being compared * @param expected The value generated by the model * @param observed The value passed in from the configuration file * @param error_value The error value for this comparison * @param score The amount of score for this comparison */ void Observation::SaveComparison(string category, Double expected, Double observed, Double process_error, Double error_value, Double adjusted_error, Double delta, Double score) { SaveComparison(category, 0, 0, expected, observed, process_error, error_value,adjusted_error, delta, score); }