@@ -251,7 +251,7 @@ class OperatorDecayFunction : public DecayFunction {
251251 DecayFunction (elt.getIncreasing(), elt.getInitialEfficacy(), elt.getCV()) {
252252 const scnXml::DecayFunction::DecaySequence &decaySequence = elt.getDecay ();
253253 if (decaySequence.size () != 2 )
254- throw util::xml_scenario_error (" Operator decay function expects two decay functions, " + to_string (decaySequence.size ()) +" were given." );
254+ throw util::xml_scenario_error (" The operator decay function expects two decay functions, but " + to_string (decaySequence.size ()) +" were given." );
255255
256256 f1 = makeObject (decaySequence[0 ], " Operator::f1" );
257257 f2 = makeObject (decaySequence[1 ], " Operator::f2" );
@@ -281,6 +281,67 @@ class OperatorDecayFunction : public DecayFunction {
281281 T op;
282282};
283283
284+ class EmaxFunction : public DecayFunction {
285+ public:
286+ EmaxFunction ( const scnXml::DecayFunction& elt ) :
287+ DecayFunction (elt.getIncreasing(), elt.getInitialEfficacy(), elt.getCV()) {
288+ const scnXml::DecayFunction::DecaySequence &decaySequence = elt.getDecay ();
289+ if (decaySequence.size () != 1 )
290+ throw util::xml_scenario_error (" The Emax function expects exactly one user function, but " + to_string (decaySequence.size ()) +" were given." );
291+ if (!elt.getEmax ().present ())
292+ throw util::xml_scenario_error (" Emax function: the Emax parameter is not declared" );
293+ if (!elt.getIC50 ().present ())
294+ throw util::xml_scenario_error (" Emax function: the IC50 parameter is not declared" );
295+ if (!elt.getSlope ().present ())
296+ throw util::xml_scenario_error (" Emax function: the Slope parameter is not declared" );
297+ if (!elt.getInitialConcentration ().present ())
298+ throw util::xml_scenario_error (" Emax function: the InitialConcentration parameter is not declared" );
299+
300+ f = makeObject (decaySequence[0 ], " Emax::f" );
301+
302+ Emax = elt.getEmax ().get ();
303+ IC50 = elt.getIC50 ().get ();
304+ slope = elt.getSlope ().get ();
305+ initialConcentration = elt.getInitialConcentration ().get ();
306+
307+ IC50 = pow (IC50, slope); // compute once
308+ }
309+
310+ EmaxFunction (const EmaxFunction ©, unique_ptr<DecayFunction> f) :
311+ DecayFunction (copy),
312+ f (move(f)),
313+ Emax (copy.Emax),
314+ IC50 (copy.IC50),
315+ slope (copy.slope),
316+ initialConcentration (copy.initialConcentration) {}
317+
318+ double compute (double effectiveAge) const {
319+ double fcomp = pow (initialConcentration * f->eval (effectiveAge), slope);
320+ cout << " t: " << effectiveAge << endl;
321+ cout << " AB(t): " << f->eval (effectiveAge) << endl;
322+ cout << " rho: " << initialConcentration << endl;
323+ cout << " slope: " << slope << endl;
324+ cout << " IC50^slope: " << IC50 << endl;
325+ cout << " rho * AB(t)^slope: " << fcomp << endl;
326+ cout << " Emax(t) = " << Emax * fcomp / (fcomp + IC50) << endl;
327+ return max (min (Emax * fcomp / (fcomp + IC50), 1.0 ), 0.0 );
328+ }
329+
330+ SimTime sampleAgeOfDecay (LocalRng& rng) const {
331+ return sim::roundToTSFromDays ( f->sampleAgeOfDecay (rng) );
332+ }
333+
334+ unique_ptr<DecayFunction> hetSample (double hetFactor) const {
335+ unique_ptr<DecayFunction> fhetSample = f->hetSample (hetFactor);
336+ unique_ptr<EmaxFunction> copy = make_unique<EmaxFunction>(*this , move (fhetSample));
337+ return move (copy);
338+ }
339+
340+ private:
341+ unique_ptr<DecayFunction> f;
342+ double Emax, IC50, slope, initialConcentration;
343+ };
344+
284345// ----- interface / static functions -----
285346
286347unique_ptr<DecayFunction> DecayFunction::makeObject (
@@ -310,6 +371,8 @@ unique_ptr<DecayFunction> DecayFunction::makeObject(
310371 return unique_ptr<DecayFunction>(new OperatorDecayFunction<std::divides<double >>( elt ));
311372 }else if ( func == " multiplies" ){
312373 return unique_ptr<DecayFunction>(new OperatorDecayFunction<std::multiplies<double >>( elt ));
374+ }else if ( func == " Emax" ){
375+ return unique_ptr<DecayFunction>(new EmaxFunction ( elt ));
313376 }else {
314377 throw util::xml_scenario_error (" decay function type " + string (func) + " of " + string (eltName) + " unrecognized" );
315378 }
0 commit comments