mantispy.tl.dose_response

Contents

mantispy.tl.dose_response#

mantispy.tl.dose_response(adata, compound_key='Metadata_Compound', dose_key='Metadata_Concentration', response='hits_row_distance', min_doses=4, min_r_squared=0.8, reference='negcon', cutoff=None, key_added='dose_response', copy=False)#

Test whether each compound’s response grows with concentration.

Each compound gets two results. The Spearman correlation between dose and response tests for a monotonic trend, makes no assumption about shape and works with three doses. A four-parameter logistic fit adds an EC50 and a Hill slope, and is only attempted with at least min_doses distinct doses.

fit_ok is True only when the fit succeeded, the curve explains the data (r_squared >= min_r_squared) and the EC50 lies inside the tested dose range. Four parameters converge on almost any five or six points. On pure noise the optimizer succeeds 59 times in 60, and these checks reduce that to 12 in 200 without losing real curves. Read spearman and its q-value first.

hitcall grades the curve on the scale the controls set, rather than only asking whether the optimizer converged. It is the product of the three weights of the ToxCast pipeline (Feshuk et al. 2023): the confidence that the curve beats a constant fit, that at least one concentration’s median response clears the cutoff, and that the fitted asymptote clears it. The EPA reads hitcall >= 0.9 as active. It needs controls to set a baseline and a cutoff, or an explicit cutoff, and is NaN without them.

The arithmetic is ported from tcplfit2’s hitcontinner and toplikelihood, including its Student-t error model on four degrees of freedom. The model set is where the numbers will differ: tcplfit2 picks a winner among ten models, mantispy between two, the logistic and a line in log dose anchored at the lowest dose. The line is there for the same reason tcplfit2 carries poly1: most real curves are still climbing at the top concentration, and a logistic with no plateau to find reports no EC50 at all. hitcall_model names the winner.

Parameters:
  • adata (AnnData) – Object carrying a compound, a dose and a per-row response.

  • compound_key (str (default: 'Metadata_Compound')) – obs column holding the compound identity.

  • dose_key (str (default: 'Metadata_Concentration')) – obs column holding the concentration. Doses must be positive; rows with a zero dose, such as vehicle, are dropped, since the fit is in log dose.

  • response (str (default: 'hits_row_distance')) – obs column holding the per-row response, normally hits_row_distance from hit_calling(). Its group-level sibling hits_distance is one number repeated over each group’s rows, so the controls show no spread and no cutoff can be read from them.

  • min_doses (int (default: 4)) – Distinct doses below which the curve is skipped and only the trend is reported.

  • min_r_squared (float (default: 0.8)) – Coefficient of determination a fit needs before it is marked ok.

  • reference (str | None (default: 'negcon')) – Rows that set the baseline the response is read against and the spread the cutoff comes from. None leaves the hit call out unless cutoff is given.

  • cutoff (float | None (default: None)) – Response a curve has to clear to count as active. The default takes three times the controls’ MAD, the ToxCast pipeline’s 3 * bmad, over the controls hit_calling() held out of its own fit rather than over all of them.

  • key_added (str (default: 'dose_response')) – Name for the output table.

  • copy (bool (default: False)) – Return a modified copy instead of mutating in place.

Return type:

AnnData | None

Returns:

None, or the modified copy. Writes uns["mantispy"][key_added] with compound, n_doses, spearman, pvalue, qvalue, ec50, hill_slope, bottom, top, r_squared, fit_ok, hitcall and hitcall_model. bottom and top are the fitted asymptotes, so for a decreasing response, such as an inhibitor’s, bottom is greater than top.

Raises:

KeyErrorobs has no compound_key, no dose_key, or no response column to use as the response.

Notes

Compounds with fewer than two usable doses are left out of the table.

An EC50 outside the tested doses is an extrapolation, usually from a curve that has not plateaued within the tested range, and its row has fit_ok=False. Compare ec50 against the dose range before quoting it.