choderalab / bayesian-itc

Python tools for the analysis and modeling of isothermal titration calorimetry (ITC) experiments.
GNU General Public License v3.0
5 stars 10 forks source link

Calibration models #57

Closed bas-rustenburg closed 6 years ago

jchodera commented 9 years ago

Looks good!

bas-rustenburg commented 9 years ago

I'm working on implementing some other basic models (because it will be useful later in the complex model).

I was thinking about the titrant to buffer titrations. I think in our discussion we talked about a delta H of dilution, but I'm curious whether it is just an enthalpy, or actually the effect of a free energy that we are observing, so there would be a temperature dependence.

Something in the form of: codecogseqn 2

bas-rustenburg commented 9 years ago

I suppose can directly subtract the suggested heats in our model that includes dilution. Can we model the single heats of dilution like this?

            q_n[n] = (DeltaH_dil * V0 * (Ln[n] - d * Ln[n - 1])) * 1000 + DeltaH_0

And for the total model, something like this?

b = q_blank
t = q_titrant_dilution
d = q_titrand_dilution
x = q_titrant_titrand

and q_bind = q_x - q_t - q_d + q_b

jchodera commented 9 years ago

The measured heat should reflect the change in the enthalpy of the system, not the change in free energy.

jchodera commented 9 years ago

The dilution heats model will depend on what model we assume the injection follows:

Which model are we using for the titrant-titrand mixing right now?

jchodera commented 9 years ago

I generally find it helpful to construct something like a "heat function" or "enthalpy function" that quantifies the total heat content as a function of thermodynamic parameters, in this case composition and volume: Q(x,V). Depending on the mixing model, we can differentiate and integrate, or subtract, the heat function to model the injection process and the heat released.

For a very simple dilution model, we might have

Q(x,V) = DeltaH0 * x * V

but we may need to get more sophisticated and have something that allows us to describe why the dilution heats are not uniform across all injections, such as

Q(x,V) = DeltaH0 * x * V + chi * x * (1-x) * V

bas-rustenburg commented 9 years ago

Thanks John! That cleared up things.

bas-rustenburg commented 9 years ago

Added 3 more models.

Two models for titrant into buffer titrations. A simple one and a model based on this paper: Calibration in isothermal titration calorimetry: heat and cell volume from heat of dilution of NaCl(aq),

though I think there might still be a bug or two, looking at some trial experiment that I did.

And one model for buffer into titrand titrations.

jchodera commented 9 years ago

Cool!

Are you able to jointly analyze buffer-buffer, titrant-buffer, buffer-titrand, and titrant-titrand together at this stage?

bas-rustenburg commented 9 years ago

Not yet. Step 1 was to figure out how to model each of them independently. Now that I've got that figured out, hopefully it won't prove too difficult to combine them.

bas-rustenburg commented 9 years ago

I've begun implementing the multiexperiment model. Not functional yet. Also still a number of bugs in parts of the code. Making progress though.

bas-rustenburg commented 9 years ago

Still got some bugs... dilution png_deltag dilution dilution png_deltah dilution dilution png_deltah_titrand dilution dilution png_deltah_titrant dilution dilution png_h_mech dilution dilution png_mc dilution dilution png_xs dilution dilution png_log_sigma dilution

bas-rustenburg commented 9 years ago

Order of magnitude mismatch between old and new models deltaH titrand and titrant.

bas-rustenburg commented 9 years ago

This looks better, not there just yet. H_mech looks off.

dilution png_deltag dilution dilution png_deltah dilution dilution png_deltah_titrand dilution dilution png_deltah_titrant dilution dilution png_h_mech dilution dilution png_mc dilution dilution png_xs dilution dilution png_log_sigma dilution

jchodera commented 9 years ago

Mechanical heat of mixing should always be exothermic, but there could be an experiment dependent heat effect that is due to mismatch between syringe and cell temperatures. This effect causes the heat of water water titrations to depend on temperature in some cases, I think.

jchodera commented 9 years ago
  1. Can you show the fits to the injection heats?
  2. Maybe it's best to unlink the DeltaH_mech for each experiment for now, since small temperature mismatches may cause these to be a bit different for each experiment?
bas-rustenburg commented 9 years ago

Can you show the fits to the injection heats?

@jchodera, you mean these figures: buffer_into_buffer buffer_into_titrand titrant_into_buffer titrant_into_titrand

Plots aren't perfect yet.

bas-rustenburg commented 9 years ago

Will post the distributions in a second. They look a little funky now that I've split things up, might be an indicator of some errors in the model..

bas-rustenburg commented 9 years ago

Here are the distributions.

deltag_bind_plot deltah_bind_plot deltah_titrand_plot deltah_titrant_plot h_mech_buffer_into_buffer_plot h_mech_buffer_into_titrand_plot h_mech_titrant_into_buffer_plot h_mech_titrant_into_titrand_plot mc_plot xs_plot

jchodera commented 9 years ago

Cool!

By "fits to the data" I mean the model derived predictions of the integrated heats and the observed integrated heats.

bas-rustenburg commented 9 years ago

Posterior predictive distribution of the injection heats, versus the observed heats (black line)

buffer_into_buffer_predictive_posterior_predictive buffer_into_titrand_predictive_posterior_predictive titrant_into_buffer_predictive_posterior_predictive titrant_into_titrand_predictive_posterior_predictive

jchodera commented 9 years ago

Very cool!

In a separate plot, can you also plot the family of models sampled from the posterior superimposed over the observed integrated heats, like this? I still find this very helpful.

For example, see In[13] here: http://nbviewer.ipython.org/github/choderalab/assaytools/blob/master/examples/fluorescence-binding-assay/Src-bosutinib%20with%20absorbance%20measurements%20in%20ScreenStar%20plate.ipynb

jchodera commented 9 years ago

Seems to be a problem with titrant_into_buffer_predictive...

bas-rustenburg commented 9 years ago

Traces added. Looks a little hairy. titrant_into_buffer_predictive_posterior_predictive

jchodera commented 9 years ago

Whoa, looks like something is majorly wrong. Why would they be so bumpy?

bas-rustenburg commented 9 years ago

I think that the trace got scrambled somehow.. now to find a way to unscramble it. Here is an unscrambled buffer buffer one, but this is manually recalculating the heats for every parameter in the trace. Looks much better

buffer_into_buffer_predictive_posterior_predictive

jchodera commented 9 years ago

Still a little confused. Can you draw solid (non-dashed) lines?

bas-rustenburg commented 9 years ago

They're all essentially flat lines, since all heats should be the same according to the current model. (neglecting the smaller initial heat here, still thinking of a solution for that.)

This is only the buffer buffer model, getting the trace for the other models and putting the parameters in the right order is a harder problem that I am tackling right now.

bas-rustenburg commented 9 years ago

Here is the trace of the heats (e.g. the deterministic variable determined by the model).

buffer_into_buffer_posterior_predictive buffer_into_titrand_posterior_predictive titrant_into_buffer_posterior_predictive titrant_into_titrand_posterior_predictive

bas-rustenburg commented 9 years ago

I'm getting a little confused... I thought that this would just give me the model, with the value of the parameters filled in as that point in the trace of those parameters.. yet, the buffer buffer looks different from the picture I showed before, where I just threw the trace values of H_mech into the model and recalculated...

jchodera commented 9 years ago

This looks like there is still a bug in either your plotting or your deterministics.

Let's resume debugging tomorrow.

bas-rustenburg commented 9 years ago

Bug was in the plotting, I think I've got it:

buffer_into_buffer_posterior_predictive buffer_into_titrand_posterior_predictive titrant_into_buffer_posterior_predictive titrant_into_titrand_posterior_predictive

Now I can move on to fixing the models...

jchodera commented 9 years ago

Bug was in the plotting, I think I've got it:

Plots look much more reasonable now, thanks!

It does look like you might either not have enough burn-in steps or you are plotting all models, including the very early ones before the sampler has settled into the populated region of parameter space. Perhaps you could increase the number of burn-in iterations, or discard the first half of the data?

jchodera commented 9 years ago

Plotting the experimental data as white circles connected by white lines isn't working, though. Can you go back to black or red circles, with no lines connecting them? The model should still be thin lines (dotted? blue? transparent?).

jchodera commented 9 years ago

Also, if you can manage to plot the cumulative heat vs titrant concentration in the cell for the titrant-into-buffer, I think that would go along way toward establishing what complexity of model we need for the dilution heats. If it is pretty linear, we can probably use a simple model.

bas-rustenburg commented 9 years ago

Yeah, this was just a short run. Not a lot of burn in. On Mar 28, 2015 4:06 PM, "John Chodera" notifications@github.com wrote:

Bug was in the plotting, I think I've got it:

Plots look much more reasonable now, thanks!

It does look like you might either not have enough burn-in steps or you are plotting all models, including the very early ones before the sampler has settled into the populated region of parameter space. Perhaps you could increase the number of burn-in iterations, or discard the first half of the data?

— Reply to this email directly or view it on GitHub https://github.com/choderalab/bayesian-itc/pull/57#issuecomment-87294205 .

bas-rustenburg commented 9 years ago

Using a model that follows this equation for the cumulative heat: codecogseqn 3 (plus the mechanical heat)

xs chi_titrant h_mech_titrant_into_buffer titrant_into_buffer titrant_into_buffer_cum

jchodera commented 9 years ago

Interesting!

Any chance you can export the data pairs of ([X]_n, Q_n) to a text file for us to play with to see what works?

bas-rustenburg commented 9 years ago

Here is the raw text. I can also email if that is more convenient.

stated_concentration     cumulative_observed_heats model_concentrations     model_cumulative_heats
2.029768194369673193e-06 -8.013264912622650726e-01 2.026287756756328881e-06 -3.909351073552982836e+00
3.223730114383260468e-05 -6.260916570597019337e+00 3.218202393741813300e-05 -3.459717945343822265e+00
6.200126601478397664e-05 -4.487019767046151131e+00 6.189495262446116750e-05 -3.434407410412215533e+00
9.132817617064910396e-05 -3.545048132875482150e+00 9.117157601286548249e-05 -2.991748860775755414e+00
1.202244493324809650e-04 -2.947011418838135555e+00 1.200183008192363981e-04 -2.973310475109562034e+00
1.486964089833757040e-04 -2.491901888383623920e+00 1.484414396838120613e-04 -2.537423149926453014e+00
1.767502857522647731e-04 -2.214510986798849945e+00 1.764472125518825750e-04 -2.525656546292495364e+00
2.043922187773864157e-04 -1.967691702135538900e+00 2.040417480349237915e-04 -2.096343021332084611e+00
2.316282570497387523e-04 -1.737558880542648954e+00 2.312310847517465100e-04 -2.091053675263612632e+00
2.584643607368026499e-04 -1.587787365490973102e+00 2.580211726499498262e-04 -1.668122283220037749e+00
2.849064024868286143e-04 -1.432699317604888112e+00 2.844178743079713695e-04 -1.669121342595316193e+00
bas-rustenburg commented 9 years ago

Units are molar and microcalories respectively for [X] and Q.

jchodera commented 9 years ago

Hm. Is cumulative_observed_heats really the cumulative observed heat? It doesn't seem to be monotonic. stated_concentration vs observed_cumulative_heats

bas-rustenburg commented 9 years ago

Might have saved the wrong array! Checking... On Mar 30, 2015 10:05 PM, "John Chodera" notifications@github.com wrote:

Hm. Is cumulative_observed_heats really the cumulative observed heat? It doesn't seem to be monotonic. [image: stated_concentration vs observed_cumulative_heats] https://cloud.githubusercontent.com/assets/3656088/6911005/ee619732-d728-11e4-8d2f-5b90b759c81b.png

— Reply to this email directly or view it on GitHub https://github.com/choderalab/bayesian-itc/pull/57#issuecomment-87899006 .

bas-rustenburg commented 9 years ago

Yeah, my bad.. this should be correct.

stated_concentration     cumulative_observed_heats model_concentrations     model_cumulative_heats
2.029768194369673193e-06 -8.013264912622650726e-01 2.012237405903344579e-06 -3.949380125291007460e+00
3.223730114383260468e-05 -7.062243061859284410e+00 3.195887264709809775e-05 -7.443596481892620353e+00
6.200126601478397664e-05 -1.154926282890543554e+01 6.146577083747025176e-05 -1.091219097295017626e+01
9.132817617064910396e-05 -1.509431096178091813e+01 9.053938908555023190e-05 -1.393268206117227237e+01
1.202244493324809650e-04 -1.804132238061905369e+01 1.191860896835442624e-04 -1.693450796058824182e+01
1.486964089833757040e-04 -2.053322426900267672e+01 1.474121414996201306e-04 -1.949508496778808819e+01
1.767502857522647731e-04 -2.274773525580152622e+01 1.752237213497476881e-04 -2.204375063130386536e+01
2.043922187773864157e-04 -2.471542695793706557e+01 2.026269153493943931e-04 -2.415782206080246652e+01
2.316282570497387523e-04 -2.645298583847971585e+01 2.296277202453750484e-04 -2.626653907474391048e+01
2.584643607368026499e-04 -2.804077320397068718e+01 2.562320447281419352e-04 -2.794712248817040035e+01
2.849064024868286143e-04 -2.947347252157557662e+01 2.824457107248068443e-04 -2.962871723927549894e+01
jchodera commented 9 years ago

Awesome, thanks! stated_concentration vs observed_cumulative_heats

jchodera commented 9 years ago

Not sure if your implementation of the model above is correct. In the plot you give, the largest heat effect is for the first (tiny) injection. Perhaps you are computing the mole fraction x incorrectly? The mole fraction of titrant should be really tiny for the first injection.

jchodera commented 9 years ago

A simple model where I use $Q = DeltaH0 * x + \chi * x * (1-x)$ seems to work decently well: cumulative_heat_fit Here, I used ~55M for the concentration of water, and computed the mole fraction of titrant in the cell $x = [X]_n / (55 + [X]_n)$, where [X]_n is the molar concentration of titrant in the cell after injection $n$.

I'm still not sure this is the best form---I think we actually want to adopt a reasonable form for the partial molar enthalpy $L(\phi)$ and then work out how this causes heat to be released on dilution.

bas-rustenburg commented 9 years ago

Not sure if your implementation of the model above is correct.

I will doublecheck. It's quite possible that I made a mistake somewhere.

Glad to see that the model fits reasonably well.

jchodera commented 9 years ago

Glad to see that the model fits reasonably well.

It may fit the injection heats $q_n$ less well. And it definitely needs the linear $x*DeltaH0$ term---doesn't seem to do well without it.

bas-rustenburg commented 9 years ago

Copy pasting the model:


# Xn[n] is the ligand concentration in sample cell after n+1 injections
    Xn = numpy.zeros([N])
    # X_frac is the mole fraction of X * (1 - mole fraction of x) in the sample cell
    X_frac = numpy.zeros([N])
    kt = 1/beta
    buffer_mass = 18.01528 # g / mol
    buffer_density = 999.97 # g / liter
    buffer_concentration = buffer_density / buffer_mass # mol /liter

    # Equation 8 of Tellinghuisen Calibration in isothermal titration calorimetry:
    # heat and cell volume from heat of dilution of NaCl(aq).
    # http://dx.doi.org/10.1016/j.ab.2006.10.015
    vcum = 0.0  # cumulative injected volume (liter)
    for n in range(N):
        # Instantaneous injection model (perfusion)
        # dilution factor for this injection (dimensionless)
        vcum += DeltaVn[n]
        vfactor = vcum / V0  # relative volume factor
        # total concentration of ligand in sample cell after n injections (converted from mM to M)
        Xn[n] = 1.e-3 * Xs * (1 - numpy.exp(-vfactor))
        X_frac[n] = x_times_onemx(mole_fraction(Xn[n], buffer_concentration)) # (x * (1-x))

    # Compute expected injection heats.
    # q_n_model[n] is the expected heat from injection n
    q_n = numpy.zeros([N])
    # Instantaneous injection model (perfusion)
    # first injection
    # From units of cal/mole to ucal
    # page 149 of Atkins physical chemistry, 8th edition, eq. 5.30 H^E = n* chi *RT * x_a * x_b
    q_n[0] = 1.e9 * V0 * (buffer_concentration + Xn[0]) * chi * kt * (X_frac[0]) + H_0
    for n in range(1, N):
        # subsequent injections
        # From units of cal/mole to ucal
        q_n[n] = 1.e9 * V0 * (buffer_concentration + Xn[n]) * chi * kt * (X_frac[n]) + (2 * H_0) - q_n[n-1]
    return q_n

Convenience functions used:

def mole_fraction(*concentrations, **options):
    """Returns the molefraction of a component.
    concentrations - positional arguments are concentrations for solution components
    options supported:
        index - zero-based index of component for which to calculate molefraction, 0 if not given
        volumes - if given, list of volumes per component, otherwise, same volume is assumed for each component
                    Needs to be of the same length as components!
    """
    for key in options:
        if key not in ['index', 'volumes']:
            raise NameError('Unexpected keyword argument: %s' % key)

    if 'volumes' in options:
        volumes = options['volumes']
        assert(len(concentrations) == len(volumes))
        moles = numpy.array(concentrations) * numpy.array(volumes)
    else:
        moles = concentrations

    if 'index' in options:
        index = options['index']
    else:
        index = 0

    return moles[index] / sum(moles)

def x_times_onemx(x):
    """
    x - number
    Returns x * (1 - x)
    """
    return x * (1 - x)
bas-rustenburg commented 9 years ago

I actually don't have the H_0 * x term you used. Will try and add that, though I was curious about the physical interpretation.