SproutlySquad.dev

Plant protein and DIAAS

Grams of protein is the number on the label and the weakest number in the dataset. Two foods can both declare 20 g per 100 g and deliver different amounts of the amino acids a body cannot make for itself, because the declared figure is nitrogen times a factor, and nitrogen does not care whether the protein was digestible or whether it was short of lysine.

DIAAS, the Digestible Indispensable Amino Acid Score, is the measure that does care. It is the score this platform will publish for protein quality, so it is worth understanding before you integrate one.

What the score actually is

For each indispensable amino acid, DIAAS takes the digestible amount in one gram of the test protein, divides it by the amount in one gram of a reference pattern for the target age group, and keeps the lowest of those ratios. The score is not an average over the profile. It is the ratio of the single amino acid that runs out first, which is why that one is called the limiting amino acid.

That has a consequence worth stating plainly: a food can be generous in eight of the nine indispensable amino acids and still score poorly, and the score alone will not tell you which one held it back. The limiting amino acid is a separate fact, and a protein quality API that returns the score without it is returning half an answer.

Two properties separate DIAAS from PDCAAS, the older score it was proposed to replace:

  • Digestibility is measured per amino acid, at the end of the small intestine (true ileal digestibility), rather than as one crude figure for the whole protein derived from faecal nitrogen. Faecal measurement credits the protein with amino acids the gut microbiota consumed or produced further down, which is an accounting error that flatters poorly digested proteins.
  • The score is not truncated at 1.0. PDCAAS capped everything at the reference, which erased the difference between a protein that just meets the pattern and one that comfortably exceeds it. Uncapped scores are what make blending arithmetic work at all.

Which reference pattern

There is no single DIAAS for a food. The reference pattern differs by age group, with separate patterns for infants, for young children, and for older children through adults, and the same food scores differently against each. A score quoted with no pattern attached is not reproducible, so treat the pattern as part of the value rather than as documentation around it.

Where plant proteins usually land

Approximate values from the published literature, scored against the young child pattern, and rounded hard because the spread between studies is larger than the last digit. They are written here as ratios, where 1.0 is the reference pattern: FAO states DIAAS as a percentage of that pattern, so a source quoting 85 and the table below quoting 0.85 are the same number.

Protein sourceDIAAS (roughly)Usually limited by
Milk proteinabove 1.0none in short supply
Soy protein isolate0.85 to 1.0sulphur amino acids
Chickpeas, cooked0.75 to 0.85sulphur amino acids
Pea protein0.6 to 0.8sulphur amino acids
Oatsaround 0.55lysine
Wheat, cooked0.4 to 0.5lysine

Every protein has a limiting amino acid, including the ones at the top: milk has a lowest ratio like everything else, and it simply sits above the pattern rather than below it. The right-hand column is the useful part where the score is under 1.0. Cereals run short of lysine. Legumes run short of methionine and cysteine. That is a fact about plant families, and it is the reason the numbers in the middle column move when you combine two foods.

Blending is not averaging

A rice and pea blend scores higher than either source because the cereal covers the legume’s sulphur amino acids and the legume covers the cereal’s lysine. What it does not do is score at the mean of the two. The correct calculation sums the digestible amino acids contributed by every component, then rescores that combined profile against the pattern, and the limiting amino acid of the blend may be neither of the two you started with.

An API that lets a caller compute the score of a recipe therefore has to hold the per amino acid digestible content, not just the finished score. A score is a lossy summary, and it is the wrong thing to store if anyone downstream wants to reformulate.

Processing moves the number

DIAAS is a property of a food as prepared, not of a crop. Heat treatment drives the Maillard reaction, which binds lysine into forms the small intestine cannot absorb while leaving it perfectly visible to a laboratory assay that measures total rather than reactive lysine. Cooking, on the other hand, deactivates the trypsin inhibitors and reduces the phytate and tannins in raw legumes, which raises digestibility. Both effects are real, they run in opposite directions, and neither is captured by naming the ingredient.

So “pea protein” is not a value. “Pea protein isolate, this process, this sample” is.

What that means for the data model

Everything above turns into one requirement: a protein quality value is not a number, it is a number plus the conditions that make it readable. The shared types the platform is built on already carry the provenance half of that, and they are defined once in the conventions RFC rather than restated here. AminoAcid is the one type below that the RFC does not hold yet, so the fence defines it rather than pointing at a section that does not exist.

This is a draft contract, a shape published as a proposal. No endpoint serves it today.

/** The nine indispensable amino acids, as an enum rather than free text.
 *  Not yet in the RFC: protein quality is the first thing on the platform
 *  that needs it, so it is proposed here and belongs there. */
type AminoAcid =
  | 'histidine'
  | 'isoleucine'
  | 'leucine'
  | 'lysine'
  | 'methionine'
  | 'phenylalanine'
  | 'threonine'
  | 'tryptophan'
  | 'valine';

/** A protein quality assessment for one food, as prepared. */
interface ProteinQuality {
  /** Part of the value, not metadata: the same food scores differently
   *  against each age group's pattern. */
  referencePattern: 'infant' | 'youngChild' | 'olderChildToAdult';
  /** A ratio against the reference pattern, not a percentage, and not
   *  capped at 1.0: above 1.0 means the protein exceeds the pattern. */
  diaasRatio: Measured<number>;
  /** The amino acid that set the score. Returned always, because the score
   *  on its own does not say which one ran out. */
  limitingAminoAcid: AminoAcid;
  /** True ileal digestibility per indispensable amino acid, 0 to 1. The
   *  input a caller needs to rescore a blend rather than average scores. */
  digestibility: Partial<Record<AminoAcid, Measured<number>>>;
}

Measured<T> is doing real work here. A DIAAS taken from a reference table for a similar sample and a DIAAS measured on the batch in front of you are both legitimate answers to the same question, and a caller building a label claim needs to be able to tell them apart. That is what the confidence levels in the RFC are for, and protein quality is the clearest case for them on the platform: the numbers are defensible, they are widely misquoted, and the difference between the two is provenance.

What to take away

Three things, if you are evaluating whether this data is worth building on:

  1. A protein score is the score of one amino acid, and you want to know which.
  2. A score without its reference pattern and its preparation is not reproducible, so it should never be stored as a bare number.
  3. Blends have to be rescored from the amino acids up, which means the underlying profile is the asset and the score is a convenience.

If the shape above is wrong for what you are building, that is the useful thing to tell us while it is still a draft.