Skip to content

Commit 7247bfa

Browse files
committed
add support for Gamma CV=0 and LogNormal sigma=0
1 parent 871aefc commit 7247bfa

File tree

4 files changed

+53
-41
lines changed

4 files changed

+53
-41
lines changed

model/Transmission/PerHost.cpp

+3-1
Original file line numberDiff line numberDiff line change
@@ -72,13 +72,15 @@ PerHost::PerHost () :
7272

7373
void PerHost::initialise (LocalRng& rng, double availabilityFactor) {
7474
relativeAvailabilityHet = availabilityFactor;
75+
anophEntoAvailabilityRaw.resize(PerHostAnophParams::numSpecies());
7576
anophEntoAvailability.resize(PerHostAnophParams::numSpecies());
7677
anophProbMosqBiting.resize(PerHostAnophParams::numSpecies());
7778
anophProbMosqResting.resize(PerHostAnophParams::numSpecies());
7879

7980
for(size_t i = 0; i < PerHostAnophParams::numSpecies(); ++i) {
8081
const PerHostAnophParams& base = PerHostAnophParams::get(i);
81-
anophEntoAvailability[i] = base.entoAvailabilityFactor * std::min(base.entoAvailability->sample(rng), 25.0) * availabilityFactor;
82+
anophEntoAvailabilityRaw[i] = std::min(base.entoAvailability->sample(rng), 25.0);
83+
anophEntoAvailability[i] = base.entoAvailabilityFactor * anophEntoAvailabilityRaw[i] * availabilityFactor;
8284
anophProbMosqBiting[i] = base.probMosqBiting.sample(rng);
8385
auto pRest1 = base.probMosqFindRestSite.sample(rng);
8486
auto pRest2 = base.probMosqSurvivalResting.sample(rng);

model/Transmission/PerHost.h

+5-1
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,7 @@ class PerHost
337337
/// Checkpointing
338338
template<class S>
339339
void operator& (S& stream) {
340+
anophEntoAvailabilityRaw & stream;
340341
anophEntoAvailability & stream;
341342
anophProbMosqBiting & stream;
342343
anophProbMosqResting & stream;
@@ -354,7 +355,10 @@ class PerHost
354355
// entoAvailability param stored in HostMosquitoInteraction.
355356
double relativeAvailabilityHet;
356357

357-
/** Species availability rate of human to mosquitoes, including hetergeneity factor
358+
/** Species availability rate of human to mosquitoes */
359+
vector<double> anophEntoAvailabilityRaw;
360+
361+
/** Species availability rate of human to mosquitoes, including heterogeneity factor
358362
* and base rate, but excluding age and intervention factors. */
359363
vector<double> anophEntoAvailability;
360364

model/interventions/Deployments.hpp

+35-35
Original file line numberDiff line numberDiff line change
@@ -253,50 +253,50 @@ class TimedHumanDeployment : public TimedDeployment, protected HumanDeploymentBa
253253

254254
if(copula)
255255
{
256-
if(Transmission::PerHostAnophParams::numSpecies() > 1)
257-
throw std::runtime_error("Gaussian copula: (deployment with availability correlation) only supports one mosquito species");
258-
259-
// Use avail that is already weighted?? or Need raw value?
260-
double scaling_factor = (Transmission::PerHostAnophParams::get(0).entoAvailabilityFactor * human.perHostTransmission.relativeAvailabilityHet);
261-
double ux = Transmission::PerHostAnophParams::get(0).entoAvailability->cdf(availability / scaling_factor);
262-
double xx = gsl_cdf_ugaussian_Pinv(ux); // Unit interval to Normal
263-
264-
// Apply the Gaussian copula transformation for correlation
265-
ComponentId cid = subPop;
266-
267-
/** human.rng.gauss(0.0, 1.0) is calculated once per component and per human. Re-deployment of
268-
* the same component on the same human must use the same gaussian sample. Therefore we store
269-
* this value in the human the first time it is calculated. */
270-
double g = 0.0;
271-
auto it = human.perHostTransmission.copulaGaussianSamples.find(cid);
272-
if (it != human.perHostTransmission.copulaGaussianSamples.end())
273-
g = it->second;
274-
else
275-
{
276-
g = human.rng.gauss(0.0, 1.0);
277-
human.perHostTransmission.copulaGaussianSamples[cid] = g;
278-
}
279-
280-
double yy = coverageCorr * xx + g * sqrt(1 - coverageCorr * coverageCorr);
281-
282-
// Transform back to unit interval
283-
double uy = gsl_cdf_ugaussian_P(yy);
284-
285256
// Beta distribution for intervention (Beta distributed)
286257
double beta_mean = coverage; // Assuming this value is given
287258
double beta_var = coverageVar; // Given as well
288259
double alpha = ((1.0 - beta_mean) / beta_var - 1.0 / beta_mean) * (beta_mean * beta_mean);
289260
double beta = alpha * (1.0 / beta_mean - 1.0);
290261

291-
if (alpha < 0 || beta < 0)
292-
throw std::runtime_error("Gaussian copula: resulting alpha and beta parameters must be positive");
262+
if(Transmission::PerHostAnophParams::numSpecies() > 1)
263+
throw std::runtime_error("Gaussian copula: (deployment with availability correlation) only supports one mosquito species");
293264

294-
265+
double ux = Transmission::PerHostAnophParams::get(0).entoAvailability->cdf(human.perHostTransmission.anophEntoAvailabilityRaw[0]);
266+
if(ux < 1)
267+
{
268+
double xx = gsl_cdf_ugaussian_Pinv(ux); // Unit interval to Normal
269+
270+
// Apply the Gaussian copula transformation for correlation
271+
ComponentId cid = subPop;
272+
273+
/** human.rng.gauss(0.0, 1.0) is calculated once per component and per human. Re-deployment of
274+
* the same component on the same human must use the same gaussian sample. Therefore we store
275+
* this value in the human the first time it is calculated. */
276+
double g = 0.0;
277+
auto it = human.perHostTransmission.copulaGaussianSamples.find(cid);
278+
if (it != human.perHostTransmission.copulaGaussianSamples.end())
279+
g = it->second;
280+
else
281+
{
282+
g = human.rng.gauss(0.0, 1.0);
283+
human.perHostTransmission.copulaGaussianSamples[cid] = g;
284+
}
285+
double yy = coverageCorr * xx + g * sqrt(1 - coverageCorr * coverageCorr);
295286

296-
// Get the final probability from Beta distribution
297-
probability = gsl_cdf_beta_Pinv(uy, alpha, beta);
287+
// Transform back to unit interval
288+
double uy = gsl_cdf_ugaussian_P(yy);
289+
290+
if (alpha < 0 || beta < 0)
291+
throw std::runtime_error("Gaussian copula: resulting alpha and beta parameters must be positive");
292+
293+
// Get the final probability from Beta distribution
294+
probability = gsl_cdf_beta_Pinv(uy, alpha, beta);
295+
}
296+
else // Gamma with CV=0
297+
probability = human.rng.beta(alpha, beta);
298298

299-
//cout << availability << " " << ux << " " << xx << " " << yy << " " << uy << " " << coverageCorr << " " << g << endl;;
299+
// cout << availability << " " << probability << " " << alpha << " " << beta << endl;
300300

301301
file << availability << " " << probability << endl;
302302
}

model/util/sampler.cpp

+10-4
Original file line numberDiff line numberDiff line change
@@ -171,10 +171,11 @@ double LognormalSampler::sample(LocalRng& rng) const{
171171
}
172172

173173
double LognormalSampler::cdf(double x) const {
174-
// Check if sigma is zero, and handle the degenerate log-normal case
175174
if (sigma == 0.0)
176-
throw std::runtime_error("LognormalSampler::cdf() does not support sigma = 0 (default const distirbution)");
177-
175+
{
176+
if(x >= mu) return 1.0;
177+
else return 0.0;
178+
}
178179
return gsl_cdf_lognormal_P(x, mu, sigma);
179180
}
180181

@@ -266,12 +267,17 @@ double GammaSampler::mean() const {
266267
}
267268

268269
double GammaSampler::sample(LocalRng& rng) const{
269-
if(isnan(theta))
270+
if(isnan(theta)) // CV=0
270271
return mu;
271272
return rng.gamma(k, theta);
272273
}
273274

274275
double GammaSampler::cdf(double x) const {
276+
if(isnan(theta)) // CV=0
277+
{
278+
if(x >= mu) return 1.0;
279+
else return 0.0;
280+
}
275281
return gsl_cdf_gamma_P(x, k, theta);
276282
}
277283

0 commit comments

Comments
 (0)