Rceattle C++ template
The CEATTLE likelihood: src/TMB/ceattle.cpp and its headers
Loading...
Searching...
No Matches
diet_data.hpp
Go to the documentation of this file.
1#ifndef DIET_CONTENT_HPP
2#define DIET_CONTENT_HPP
3
4/**
5 * @brief Parses empirical diet observations and maps them into a 5D proportion array.
6 *
7 * @details Maps `diet_obs` proportions onto the 5D `diet_prop` array used for MSVPA based
8 * suitability, handling 1-sex and 2-sex indexing. A row with `flt_yr == 0` is written to
9 * every modeled year. Rows aggregated over predator or prey ages are skipped: only
10 * diet-data type 1 (a prey age in a predator age) can be used for MSVPA suitability.
11 *
12 * @param nspp Number of species.
13 * @param nyrs Years, hindcast plus projection.
14 * @param nyrs_hind Years in the hindcast.
15 * @param styr First year of the model.
16 * @param minage Minimum modeled age per species.
17 * @param nsex Sexes modelled per species: 1 = combined, 2 = both.
18 * @param diet_obs Diet observations; column 0 sample size, column 1 the proportion.
19 * @param diet_ctl Maps each observation row to predator, prey, sexes, ages, and year.
20 * @param diet_prop [Output] Observed diet proportions
21 * (pred_idx, prey_idx, pred_age, prey_age, yr). Modified by reference.
22 */
23template <class Type>
25 const int& nspp,
26 const int& nyrs,
27 const int& nyrs_hind,
28 const int& styr,
29 const vector<int>& minage,
30 const vector<int>& nsex,
31 matrix<Type>& diet_obs,
32 matrix<int>& diet_ctl,
33 array<Type>& diet_prop // Modified by reference
34) {
35 for(int stom_ind = 0; stom_ind < diet_obs.rows(); stom_ind++) {
36 int rsp = diet_ctl(stom_ind, 0) - 1; // Index of pred
37 int ksp = diet_ctl(stom_ind, 1) - 1; // Index of prey
38 int r_sex = diet_ctl(stom_ind, 2); // Pred: 0 combined, 1 female, 2 male
39 int k_sex = diet_ctl(stom_ind, 3); // Prey sex, same convention
40 int r_age = diet_ctl(stom_ind, 4) - minage(rsp); // Index of pred age
41 int k_age = diet_ctl(stom_ind, 5) - minage(ksp); // Index of prey age
42 int flt_yr = diet_ctl(stom_ind, 6); // Year of the row, 0 for all years
43 // A negative age marks a row aggregated over prey ages (k_age) or predator ages
44 // (r_age). Those are not diet-data type 1, so they carry no MSVPA suitability;
45 // predict_stomach_content() still predicts them for the likelihood.
46 if((k_age < 0) || (r_age < 0)) continue;
47
48 // Sex looping bounds, predator and prey; a combined-sex row is written to both sexes.
49 int r_start = 0;
50 int r_end = 0;
51 if(nsex(rsp) == 2) {
52 if(r_sex == 0) { r_end = 1; }
53 else { r_start = r_sex - 1; r_end = r_sex - 1; }
54 }
55
56 int k_start = 0;
57 int k_end = 0;
58 if(nsex(ksp) == 2) {
59 if(k_sex == 0) { k_end = 1; }
60 else { k_start = k_sex - 1; k_end = k_sex - 1; }
61 }
62
63 Type obs_val = diet_obs(stom_ind, 1);
64
65 for(int j = r_start; j <= r_end; j++) {
66 int r_idx = rsp + (nspp * j);
67
68 for(int k = k_start; k <= k_end; k++) {
69 int k_idx = ksp + (nspp * k);
70
71 // Only flt_yr >= 0 is loaded here: one year, dropped if outside the hindcast, or
72 // year 0 for every year. A negative flt_yr loads nothing.
73 if(flt_yr > 0) {
74 int yr = flt_yr - styr;
75 if(yr >= 0 && yr < nyrs_hind) {
76 diet_prop(r_idx, k_idx, r_age, k_age, yr) = obs_val;
77 }
78 }
79 else if(flt_yr == 0) {
80 for(int yr = 0; yr < nyrs; yr++) {
81 diet_prop(r_idx, k_idx, r_age, k_age, yr) = obs_val;
82 }
83 }
84 }
85 }
86 }
87}
88
89
90/**
91 * @brief Residual stomach content: the "other food" not explicitly modeled.
92 *
93 * The unattributed diet share divided by other_food (mt) is on the same per-biomass scale
94 * as stom_div_bio, which calculate_msvpa_suitability() sums over prey and adds it to.
95 */
96template <class Type>
98 const int& nspp,
99 const int& nyrs,
100 const vector<int>& nsex,
101 const vector<int>& nages,
102 const vector<Type>& other_food,
103 array<Type>& diet_prop,
104 array<Type>& other_food_diet_prop // Modified by reference
105) {
106 other_food_diet_prop.setZero();
107 for(int yr = 0; yr < nyrs; yr++) {
108 for(int rsp = 0; rsp < nspp; rsp++) {
109 for(int r_sex = 0; r_sex < nsex(rsp); r_sex++) {
110 int r_idx = rsp + (nspp * r_sex);
111 for(int r_age = 0; r_age < nages(rsp); r_age++) {
112
113 other_food_diet_prop(rsp, r_sex, r_age, yr) = Type(1.0);
114
115 for(int ksp = 0; ksp < nspp; ksp++) {
116 for(int k_sex = 0; k_sex < nsex(ksp); k_sex++) {
117 int k_idx = ksp + (nspp * k_sex);
118 for(int k_age = 0; k_age < nages(ksp); k_age++) {
119 other_food_diet_prop(rsp, r_sex, r_age, yr) -= diet_prop(r_idx, k_idx, r_age, k_age, yr);
120 }
121 }
122 }
123
124 if(other_food(rsp) > 0) {
125 other_food_diet_prop(rsp, r_sex, r_age, yr) /= other_food(rsp);
126 } else {
127 other_food_diet_prop(rsp, r_sex, r_age, yr) = 0.0;
128 }
129 }
130 }
131 }
132 }
133}
134
135
136/**
137 * @brief Expected stomach content proportions given the modeled population state.
138 *
139 * @details Maps `diet_prop_hat` back onto the rows of the empirical `diet_obs`, which are
140 * often aggregated over ages or sexes. The four diet-data types, as the ages encode them:
141 * - **Type 1:** Specific predator age and prey age (weighted across sexes if combined).
142 * - **Type 2:** Specific predator age, summed across all prey ages.
143 * - **Type 3:** Unweighted mean over predator ages, summed over prey ages (r_age > -500).
144 * - **Type 4:** As Type 3, but weighted by predator numbers-at-age (r_age < -500).
145 *
146 * @param nspp Number of species.
147 * @param nyrs_hind Years in the hindcast.
148 * @param styr First year of the model.
149 * @param suit_styr Start year index of the suitability window, per predator.
150 * @param suit_endyr End year index of the suitability window, per predator.
151 * @param minage Minimum modeled age per species.
152 * @param nsex Sexes modelled per species: 1 = combined, 2 = both.
153 * @param nages Age bins per species.
154 * @param diet_obs Empirical diet observations, used here for row-matching.
155 * @param diet_ctl Maps each observation row to its aggregation levels.
156 * @param avgN_at_age Average numbers-at-age (thousands of fish), used for weighting.
157 * @param diet_prop_hat Predicted diet proportions for specific ages/sexes.
158 * @param diet_hat [Output] Predicted diet proportions matching `diet_obs`.
159 */
160template <class Type>
162 const int& nspp,
163 const int& nyrs_hind,
164 const int& styr,
165 const vector<int>& suit_styr,
166 const vector<int>& suit_endyr,
167 const vector<int>& minage,
168 const vector<int>& nsex,
169 const vector<int>& nages,
170 matrix<Type>& diet_obs,
171 matrix<int>& diet_ctl,
172 array<Type>& avgN_at_age,
173 array<Type>& diet_prop_hat,
174 matrix<Type>& diet_hat // Modified by reference
175) {
176 for(int stom_ind = 0; stom_ind < diet_obs.rows(); stom_ind++) {
177 int rsp = diet_ctl(stom_ind, 0) - 1;
178 int ksp = diet_ctl(stom_ind, 1) - 1;
179 int r_sex = diet_ctl(stom_ind, 2);
180 int k_sex = diet_ctl(stom_ind, 3);
181 int r_age = diet_ctl(stom_ind, 4) - minage(rsp);
182 int k_age = diet_ctl(stom_ind, 5) - minage(ksp);
183 int flt_yr = diet_ctl(stom_ind, 6);
184
185 // Sex looping bounds (0 = combined, 1 = female, 2 = male), predator then prey.
186 int r_start = 0;
187 int r_end = 0;
188 if(nsex(rsp) == 2) {
189 if(r_sex == 0) { r_end = 1; }
190 else { r_start = r_sex - 1; r_end = r_sex - 1; }
191 }
192 int num_r_sexes = r_end - r_start + 1; // Used for averaging in TYPE 3
193
194 int k_start = 0;
195 int k_end = 0;
196 if(nsex(ksp) == 2) {
197 if(k_sex == 0) { k_end = 1; }
198 else { k_start = k_sex - 1; k_end = k_sex - 1; }
199 }
200
201 // flt_yr > 0 is that year, 0 the suitability window, negative the year |flt_yr|.
202 int yr_start = 0, yr_end = 0;
203 if(flt_yr > 0) {
204 yr_start = flt_yr - styr;
205 yr_end = flt_yr - styr;
206 } else if (flt_yr == 0) {
207 yr_start = suit_styr(rsp);
208 yr_end = suit_endyr(rsp);
209 } else {
210 yr_start = -flt_yr - styr;
211 yr_end = -flt_yr - styr;
212 }
213
214 // Only evaluate if within hindcast limits
215 if(yr_start < nyrs_hind && yr_end < nyrs_hind) {
216 Type yr_accum = 0;
217 int n_yrs_evaluated = yr_end - yr_start + 1;
218
219 for(int yr = yr_start; yr <= yr_end; yr++) {
220 Type type_accum = 0;
221
222 // TYPE 1: Specific pred age, specific prey age
223 if((k_age >= 0) & (r_age >= 0)) {
224 Type weighted_sum = 0;
225 Type total_numbers = 0;
226 for(int r_s = r_start; r_s <= r_end; r_s++) {
227 Type pred_numbers = avgN_at_age(rsp, r_s, r_age, yr);
228 total_numbers += pred_numbers;
229 for(int k_s = k_start; k_s <= k_end; k_s++) {
230 weighted_sum += diet_prop_hat(rsp + (nspp * r_s), ksp + (nspp * k_s), r_age, k_age, yr) * pred_numbers;
231 }
232 }
233 if(total_numbers > 0) type_accum += weighted_sum / total_numbers;
234 }
235
236 // TYPE 2: Specific pred age, sum across prey ages
237 else if((k_age < 0) & (r_age >= 0)) {
238 Type weighted_sum = 0;
239 Type total_numbers = 0;
240 for(int r_s = r_start; r_s <= r_end; r_s++) {
241 Type pred_numbers = avgN_at_age(rsp, r_s, r_age, yr);
242 total_numbers += pred_numbers;
243 for(int k_s = k_start; k_s <= k_end; k_s++) {
244 for(int k_age_tmp = 0; k_age_tmp < nages(ksp); k_age_tmp++) {
245 weighted_sum += diet_prop_hat(rsp + (nspp * r_s), ksp + (nspp * k_s), r_age, k_age_tmp, yr) * pred_numbers;
246 }
247 }
248 }
249 if(total_numbers > 0) type_accum += weighted_sum / total_numbers;
250 }
251
252 // TYPE 3: Mean across pred ages, sum across prey ages (Unweighted)
253 else if((k_age < 0) & (r_age < 0) & (r_age > -500)) {
254 Type unweighted_sum = 0;
255 for(int r_s = r_start; r_s <= r_end; r_s++) {
256 for(int r_age_tmp = 0; r_age_tmp < nages(rsp); r_age_tmp++) {
257 for(int k_s = k_start; k_s <= k_end; k_s++) {
258 for(int k_age_tmp = 0; k_age_tmp < nages(ksp); k_age_tmp++) {
259 unweighted_sum += diet_prop_hat(rsp + (nspp * r_s), ksp + (nspp * k_s), r_age_tmp, k_age_tmp, yr);
260 }
261 }
262 }
263 }
264 type_accum += unweighted_sum / (num_r_sexes * nages(rsp));
265 }
266
267 // TYPE 4: Weighted mean across pred ages, sum across prey ages
268 else if((k_age < 0) & (r_age < -500)) {
269 Type weighted_sum = 0;
270 Type total_numbers = 0;
271 for(int r_s = r_start; r_s <= r_end; r_s++) {
272 for(int r_age_tmp = 0; r_age_tmp < nages(rsp); r_age_tmp++) {
273 Type pred_numbers = avgN_at_age(rsp, r_s, r_age_tmp, yr);
274 total_numbers += pred_numbers;
275 for(int k_s = k_start; k_s <= k_end; k_s++) {
276 for(int k_age_tmp = 0; k_age_tmp < nages(ksp); k_age_tmp++) {
277 weighted_sum += diet_prop_hat(rsp + (nspp * r_s), ksp + (nspp * k_s), r_age_tmp, k_age_tmp, yr) * pred_numbers;
278 }
279 }
280 }
281 }
282 if(total_numbers > 0) type_accum += weighted_sum / total_numbers;
283 }
284 yr_accum += type_accum;
285 }
286 diet_hat(stom_ind, 1) = yr_accum / n_yrs_evaluated;
287 }
288 }
289}
290
291#endif
void organize_diet_obs(const int &nspp, const int &nyrs, const int &nyrs_hind, const int &styr, const vector< int > &minage, const vector< int > &nsex, matrix< Type > &diet_obs, matrix< int > &diet_ctl, array< Type > &diet_prop)
Parses empirical diet observations and maps them into a 5D proportion array.
Definition diet_data.hpp:24
void predict_stomach_content(const int &nspp, const int &nyrs_hind, const int &styr, const vector< int > &suit_styr, const vector< int > &suit_endyr, const vector< int > &minage, const vector< int > &nsex, const vector< int > &nages, matrix< Type > &diet_obs, matrix< int > &diet_ctl, array< Type > &avgN_at_age, array< Type > &diet_prop_hat, matrix< Type > &diet_hat)
Expected stomach content proportions given the modeled population state.
void calculate_other_food_diet_prop(const int &nspp, const int &nyrs, const vector< int > &nsex, const vector< int > &nages, const vector< Type > &other_food, array< Type > &diet_prop, array< Type > &other_food_diet_prop)
Residual stomach content: the "other food" not explicitly modeled.
Definition diet_data.hpp:97