Skip to content

Commit 3253580

Browse files
committed
add Emax decay function
1 parent d9edc88 commit 3253580

File tree

2 files changed

+78
-10
lines changed

2 files changed

+78
-10
lines changed

model/util/DecayFunction.cpp

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -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 &copy, 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

286347
unique_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
}

schema/util.xsd

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ Licence: GNU General Public Licence version 2 or later (see COPYING) -->
152152
<xs:enumeration value="minus"/>
153153
<xs:enumeration value="divides"/>
154154
<xs:enumeration value="multiplies"/>
155+
<xs:enumeration value="Emax"/>
155156
</xs:restriction>
156157
</xs:simpleType>
157158
</xs:attribute>
@@ -213,26 +214,30 @@ Licence: GNU General Public Licence version 2 or later (see COPYING) -->
213214
</xs:documentation>
214215
</xs:annotation>
215216
</xs:attribute>
216-
<xs:attribute name="rho" type="xs:double" use="optional">
217+
<xs:attribute name="initialConcentration" type="xs:double" use="optional">
217218
<xs:annotation>
218219
<xs:documentation>
219220
biphasic: Proportion between 0 and 1, proportion of the response that is short-lived.</xs:documentation>
220221
</xs:annotation>
221222
</xs:attribute>
222-
<xs:attribute name="halflife_short" type="xs:string" use="optional">
223+
<xs:attribute name="Emax" type="xs:double" use="optional">
223224
<xs:annotation>
224225
<xs:documentation>
225-
biphasic: halflife of short lived component (default to years).
226-
227-
</xs:documentation>
226+
maximum efficacy (between 0 and 1)</xs:documentation>
228227
</xs:annotation>
229228
</xs:attribute>
230-
<xs:attribute name="halflife_long" type="xs:string" use="optional">
229+
<xs:attribute name="slope" type="xs:double" use="optional">
231230
<xs:annotation>
232231
<xs:documentation>
233-
biphasic: halflife of long lived component (default to years).
234-
235-
</xs:documentation>
232+
steepness of the sigmoidal curve
233+
</xs:documentation>
234+
</xs:annotation>
235+
</xs:attribute>
236+
<xs:attribute name="IC50" type="xs:double" use="optional">
237+
<xs:annotation>
238+
<xs:documentation>
239+
IC 50
240+
</xs:documentation>
236241
</xs:annotation>
237242
</xs:attribute>
238243
</xs:complexType>

0 commit comments

Comments
 (0)