Examples

Example 1: Basic Usage

In the first example we will correct a measured response vector of the M-57 alanine fragment. First the chemical formula of the fragment and the response vector have to be defined, after which the uncorrected mass isotopomer distribution (MID) can be calculated.

Labeled Carbon

The number after "LabC" in the chemical formula represents the number of possibly labeled carbon atoms in the fragment while the number behind "C" is the total number of carbon atoms, both from the alanine and from any derivative groups.

using IsotopeCorrection

ala_m57 = "C11H26N1O2Si2LabC3"
response_vec = [2500000, 2000000, 2500000, 800000]
MID = response_vec ./ sum(response_vec)
4-element Vector{Float64}:
 0.32051282051282054
 0.2564102564102564
 0.32051282051282054
 0.10256410256410256

The function isotope_correction()` can be directly used on a single measurement vector. Here we are assuming that the tracer used for this experiment had an 80% purity.

corr_resp, corr_MID, mean_enrich, residuum = isotope_correction(response_vec,
                                                                ala_m57;
                                                                tracer_purity = 0.8)
([3.0266026323459675e6, 819243.5134320183, 3.666924789018221e6, 587930.8175325774], [0.37362227679544946, 0.10113241278096713, 0.4526675467300171, 0.07257776369356636], 0.5560501993304251, [-2.022641591536693e-13, -2.999336291582156e-13, 3.788572473403735e-13, 2.28532231771029e-13])

corr_resp` is the corrected measurement vector,

corr_resp
4-element Vector{Float64}:
      3.0266026323459675e6
 819243.5134320183
      3.666924789018221e6
 587930.8175325774

corr_MID is the MID of the corrected measurement vector,

corr_MID
4-element Vector{Float64}:
 0.37362227679544946
 0.10113241278096713
 0.4526675467300171
 0.07257776369356636

mean_enrich is the mean enrichment of the corrected measurement vector,

mean_enrich
0.5560501993304251

and residuum is the residals of the optimization.

residuum
4-element Vector{Float64}:
 -2.022641591536693e-13
 -2.999336291582156e-13
  3.788572473403735e-13
  2.28532231771029e-13

The optimization can also be turned off, using the optimization = false keyword argument, though this isn't recommended as the optimization prevents negative values in the corrected response.

To visualize the effects of isotope_correction(), the MID can be plotted before and after correction.

using ColorSchemes, CairoMakie

colors = colorschemes[:bamako][1:64:end];
group_color = [PolyElement(color = color, strokecolor = :transparent)
    for color in colors]
labels = ["m+0", "m+1", "m+2", "m+3"]
Mplus = [0, 1, 2, 3]

fig = Figure();
ax = Axis(fig[1,1],
    xticks = (1:2, ["uncorrected", "corrected"]),
    title = "Alanine (M-57) MID")
barplot!(ax, repeat([1, 2], inner = length(corr_MID)),
    cat(MID, corr_MID, dims = 1),
    stack = repeat(Mplus, 2),
    colormap = colors,
    color = repeat(Mplus .+ 1, 2))

Legend(fig[1,2], group_color, labels, framevisible = false)
fig
Example block output

Example 2: Usage with a DataFrame

For this example we will make a very simple DataFrame with 2 samples for each of which 2 methionine fragments were measured, specifically M-159 and M-57. We need the chemical formulas of both fragments, as shown in the code below, as well as measured response vectors. For this example the measured response for sample 1 is all possible m+ being recorded with equal frequency while the measured response for sample 2 is simply a random vector.

Labeled Carbon

The number after "LabC" in the chemical formula represents the number of possibly labeled carbon atoms in the fragment while the number behind "C" is the total number of carbon atoms, both from the methionine and from any derivative groups.

using IsotopeCorrection
using DataFrames, DataFramesMeta

df = DataFrame(
    Sample = repeat([1, 2], inner = 11),
    AminoAcidFragment = repeat(cat(repeat(["Met_(M-159)"], 5), repeat(["Met_(M-57)"], 6), dims = 1), 2),
    Molecule = repeat(cat(repeat(["C10H24N1S1Si1LabC4"], 5), repeat(["C13H30N1O2S1Si2LabC5"], 6), dims = 1), 2),
    MZ0 = repeat(cat(repeat([218], 5), repeat([320], 6), dims = 1), 2),
    Mplus = repeat(cat(repeat(0:4, 1), repeat(0:5, 1), dims = 1), 2),
    Response = cat(repeat([3e6/5], 5), repeat([3e6/6], 6), rand(0:3e6, 11), dims = 1))

# Of course normally the first step would be to read in (and prepare) real data,
# using CSV.jl or XLSX.jl, for example.

# using CSV
# df = CSV.read("DATA.csv", DataFrame)
22×6 DataFrame
RowSampleAminoAcidFragmentMoleculeMZ0MplusResponse
Int64StringStringInt64Int64Float64
11Met_(M-159)C10H24N1S1Si1LabC42180600000.0
21Met_(M-159)C10H24N1S1Si1LabC42181600000.0
31Met_(M-159)C10H24N1S1Si1LabC42182600000.0
41Met_(M-159)C10H24N1S1Si1LabC42183600000.0
51Met_(M-159)C10H24N1S1Si1LabC42184600000.0
61Met_(M-57)C13H30N1O2S1Si2LabC53200500000.0
71Met_(M-57)C13H30N1O2S1Si2LabC53201500000.0
81Met_(M-57)C13H30N1O2S1Si2LabC53202500000.0
91Met_(M-57)C13H30N1O2S1Si2LabC53203500000.0
101Met_(M-57)C13H30N1O2S1Si2LabC53204500000.0
111Met_(M-57)C13H30N1O2S1Si2LabC53205500000.0
122Met_(M-159)C10H24N1S1Si1LabC42180818334.0
132Met_(M-159)C10H24N1S1Si1LabC42181261575.0
142Met_(M-159)C10H24N1S1Si1LabC421822.5839e6
152Met_(M-159)C10H24N1S1Si1LabC421831.14897e6
162Met_(M-159)C10H24N1S1Si1LabC42184231407.0
172Met_(M-57)C13H30N1O2S1Si2LabC532001.17069e6
182Met_(M-57)C13H30N1O2S1Si2LabC53201678027.0
192Met_(M-57)C13H30N1O2S1Si2LabC532022.97735e6
202Met_(M-57)C13H30N1O2S1Si2LabC53203541298.0
212Met_(M-57)C13H30N1O2S1Si2LabC532041.82826e6
222Met_(M-57)C13H30N1O2S1Si2LabC532051.65989e6

Using DataFramesMeta the DataFrame can be grouped based on the sample ID and amino acid fragment and each group corrected using the main function of this package: isotope_correction()

Since this function outputs the corrected response, MID, mean enrichment and residuum, we index into element 1 to recieve only the corrected response. Additionally we are assuming that the tracer used for this experiment had a 99% purity.

gdfs = groupby(df, [:Sample, :AminoAcidFragment])
df_corrected = @transform(gdfs,
    :CorrectedResponse = isotope_correction(Vector(:Response), :Molecule[1]; tracer_purity = 0.99)[1])
22×7 DataFrame
RowSampleAminoAcidFragmentMoleculeMZ0MplusResponseCorrectedResponse
Int64StringStringInt64Int64Float64Float64
11Met_(M-159)C10H24N1S1Si1LabC42180600000.07.61252e5
21Met_(M-159)C10H24N1S1Si1LabC42181600000.06.22406e5
31Met_(M-159)C10H24N1S1Si1LabC42182600000.05.75541e5
41Met_(M-159)C10H24N1S1Si1LabC42183600000.05.8521e5
51Met_(M-159)C10H24N1S1Si1LabC42184600000.06.18862e5
61Met_(M-57)C13H30N1O2S1Si2LabC53200500000.07.15001e5
71Met_(M-57)C13H30N1O2S1Si2LabC53201500000.0524602.0
81Met_(M-57)C13H30N1O2S1Si2LabC53202500000.04.67532e5
91Met_(M-57)C13H30N1O2S1Si2LabC53203500000.04.88044e5
101Met_(M-57)C13H30N1O2S1Si2LabC53204500000.04.90389e5
111Met_(M-57)C13H30N1O2S1Si2LabC53205500000.05.20477e5
122Met_(M-159)C10H24N1S1Si1LabC42180818334.01.04608e6
132Met_(M-159)C10H24N1S1Si1LabC42181261575.090713.2
142Met_(M-159)C10H24N1S1Si1LabC421822.5839e63.14444e6
152Met_(M-159)C10H24N1S1Si1LabC421831.14897e69.42992e5
162Met_(M-159)C10H24N1S1Si1LabC42184231407.00.0
172Met_(M-57)C13H30N1O2S1Si2LabC532001.17069e61.69095e6
182Met_(M-57)C13H30N1O2S1Si2LabC53201678027.04.33579e5
192Met_(M-57)C13H30N1O2S1Si2LabC532022.97735e63.83412e6
202Met_(M-57)C13H30N1O2S1Si2LabC53203541298.00.0
212Met_(M-57)C13H30N1O2S1Si2LabC532041.82826e61.93887e6
222Met_(M-57)C13H30N1O2S1Si2LabC532051.65989e61.83581e6

Now, again using DataFramesMeta, both the corrected and uncorrected MIDs can be calculated.

gdfs_corrected = groupby(df_corrected, [:Sample, :AminoAcidFragment])
df_corrected_MIDs = @transform(gdfs_corrected,
    :MID = :Response ./ sum(:Response),
    :CorrectedMID = :CorrectedResponse ./ sum(:CorrectedResponse))
select(df_corrected_MIDs, :Sample, :AminoAcidFragment, :Response, :CorrectedResponse, :MID, :CorrectedMID)
# And of course the finished DataFrame can then be saved.
# CSV.write("Corrected_MIDs.csv", df_corrected_MIDs)
22×6 DataFrame
RowSampleAminoAcidFragmentResponseCorrectedResponseMIDCorrectedMID
Int64StringFloat64Float64Float64Float64
11Met_(M-159)600000.07.61252e50.20.240653
21Met_(M-159)600000.06.22406e50.20.19676
31Met_(M-159)600000.05.75541e50.20.181945
41Met_(M-159)600000.05.8521e50.20.185002
51Met_(M-159)600000.06.18862e50.20.19564
61Met_(M-57)500000.07.15001e50.1666670.223017
71Met_(M-57)500000.0524602.00.1666670.163629
81Met_(M-57)500000.04.67532e50.1666670.145828
91Met_(M-57)500000.04.88044e50.1666670.152226
101Met_(M-57)500000.04.90389e50.1666670.152958
111Met_(M-57)500000.05.20477e50.1666670.162342
122Met_(M-159)818334.01.04608e60.1622330.200237
132Met_(M-159)261575.090713.20.05185670.017364
142Met_(M-159)2.5839e63.14444e60.5122540.601896
152Met_(M-159)1.14897e69.42992e50.2277810.180504
162Met_(M-159)231407.00.00.0458760.0
172Met_(M-57)1.17069e61.69095e60.1321990.173728
182Met_(M-57)678027.04.33579e50.07656550.0445459
192Met_(M-57)2.97735e63.83412e60.3362140.393917
202Met_(M-57)541298.00.00.06112550.0
212Met_(M-57)1.82826e61.93887e60.2064540.199199
222Met_(M-57)1.65989e61.83581e60.1874410.188611

To visualize what isotope_correction() does we can plot the MIDs before and after correction.

using ColorSchemes, CairoMakie

gdfs = @groupby(df_corrected_MIDs, :Sample, :AminoAcidFragment)

colors = colorschemes[:bamako][1:43:256];
group_color = [PolyElement(color = color, strokecolor = :transparent)
    for color in colors]
labels = ["m+0", "m+1", "m+2", "m+3", "m+4", "m+5"]

fig = Figure();

function myplot(group, fig, colors)
    name = group.AminoAcidFragment[1]
    sample = group.Sample[1]
    ax = Axis(fig,
        xticks = (1:2, ["uncorrected", "corrected"]),
        title = "Sample $sample $name MID")
    barplot!(ax, repeat([1, 2], inner = length(group.MID)),
        cat(group.MID, group.CorrectedMID, dims = 1),
        stack = repeat(group.Mplus, 2),
        colormap = colors,
        color = repeat(group.Mplus .+ 1, 2))
end
myplot(gdfs[1], fig[1,1], colors[1:5])
myplot(gdfs[2], fig[1,2], colors)
myplot(gdfs[3], fig[2,1], colors[1:5])
myplot(gdfs[4], fig[2,2], colors)

Legend(fig[1:2,3], group_color, labels, framevisible = false)

fig
# save("Methionine_MIDs.png", fig)
Example block output

This page was generated using Literate.jl.