Overview
DashboardIntelligenceHerd profitAsk GenemapTake a tour
Animals
SearchUpload herdPedigree & relationshipsPedigree builderAnimal reference
Records
PhenotypesUpload CSV dataWeighingsReproductionCarcaseCarcase importMSA feedbackFeed efficiencyNutritionMicrobiomeTranscriptsExpression profileG×E reaction normsSampling planUltrasound scansUltrasound scan dayUltrasound measurementsUltrasound calibrationUltrasound validationPhones (calving app)Records complete? (calving seasons)
Rankings
Live bull indexLive cow rankDynamic indexFamily rankHow the indexes are calculatedGenotypes & ssGBLUPCalibrationProperty rollupGenetic gainGenetic gain forecast
Decisions
Bid advisorMarket data
Sales
Prospective buyersListings & marketplaceSire carcase reportTell your bull breeder
Land & climate
Forage & drought plannerMethane & carbon
Settings
Farm profileEconomics profileBioeconomic profilePropertiesTeam & permissionsOrganisationActivity logExportStatusTechnical reference

Genemap Beef technical reference

Every method, every flag, every audit-row column. Producer-language with the math kept honest.

Genemap is a multi-trait single-step BLUP genetic evaluation platform built for cattle (Bos taurus, Bos indicus, composites). It is Genemap's own implementation of single-step BLUP. It does not use, and has not been validated against, BREEDPLAN, Zoetis, IGS or BLUPF90 software. Cattle parameters are published Angus estimates, used as a default for other breeds. Phenotype, genotype and carcase data are imported by file, then re-run.

This document is the complete technical reference. Methods are organised by what they do (variance estimation, SNP priors, etc.) with each section linking to the code and request flags that activate them.

Quick start

The simplest possible solve uses default ssGBLUP with no advanced options:

POST /functions/v1/ssgblup-solve
Content-Type: application/json
Authorization: Bearer <jwt>

{}

This pulls every animal in your org, builds A from pedigree, blends in G from any genotypes, and returns posterior breeding values for the default 15-trait set. It writes nothing back: auto_apply defaults to false and only an explicit auto_apply: true records the run's EBVs in ebv_genemap_values (never on the animal record).

To turn on the advanced methods individually, see the API reference below. Or use the Calibration page for a UI that ticks them on for you.

The ssGBLUP solver

Multi-trait Henderson MME

The core of every BLUP system. For multi-trait, the mixed-model equation is:

[ X'X   X'Z   ] [ β̂ ] [ X'y ]
[ Z'X   Z'Z + λG⁻¹ ] [ û ] = [ Z'y ]

where X holds fixed effects (contemporary group, breed, etc.), Z links observations to animals, β̂ is the fixed-effect estimate, û is the breeding value vector, λ = σ²ₑ / σ²ₐ, and G is the relationship matrix. We solve this iteratively via preconditioned conjugate gradient (PCG); the diagonal of (Z'Z + λG⁻¹) is the preconditioner.

Traits are solved one at a time in an outer Gauss-Seidel loop and coupled through G₀⁻¹, the inverse of the genetic (co)variance matrix: each pass carries the other traits' current breeding values into a trait's equations with the weights G₀⁻¹ implies, which is the coupling a joint multi-trait solve uses. There is no damping factor; the 0.3 damping that an earlier version applied was removed as mathematically wrong. The loop stops when the normalised change between passes falls below outer_tol (default 1e-4, reads as the distance in σₐ; up to max_outer 250 passes), and the run reports every pass, the coupling it used and a solution-free model_identity check that the assembled coefficient matrix is the one the declared variance components imply. It remains an outer loop rather than one joint solve of every trait, and it is not described as one.

References: Henderson 1975, 1976. Schaeffer 1984 multi-trait extension.

Single-step H matrix (Aguilar 2010)

When some animals are genotyped and some aren't, the H matrix replaces A:

H⁻¹ = A⁻¹ + [ 0   0 ; 0   G* − A₂₂⁻¹ ]

where the genomic correction is non-zero only on the genotyped block. G* is the blended G matrix:

G* = α · G + (1 − α) · A₂₂

α defaults to 0.95. G itself is built via VanRaden 2008: G = Z·Z' / 2Σpᵢqᵢ after centring genotypes by allele frequency. The blend with A₂₂ regularises G against monomorphic-SNP issues.

References: Aguilar et al. 2010, VanRaden 2008, Christensen-Lund 2010.

APY G⁻¹ for scale

Cholesky-direct G⁻¹ is O(n²³). Past ~3000 genotyped animals it becomes infeasible. The Algorithm for Proven and Young (Misztal 2014) decomposes G⁻¹:

G_APY⁻¹ = [ G_cc⁻¹ + G_cc⁻¹·G_cn·M⁻¹·G_nc·G_cc⁻¹   −G_cc⁻¹·G_cn·M⁻¹ ]
        [ −M⁻¹·G_nc·G_cc⁻¹                       M⁻¹ ]

where M is a diagonal matrix, c indexes "core" animals (~10% of genotyped) and n indexes non-core. Only G_cc requires inversion. With proper core selection the result is statistically equivalent to full G⁻¹ at a fraction of the compute.

On a runtime that can hold that many animals (the deployed one stops at about 1,190), Genemap auto-fires APY when n_geno ≥ 1500 (use_apy forces it either way). Core membership: 60% birth-year rank + 40% A-relationship-sum rank, repaired so every breed keeps at least one animal outside the core. Core size comes from the spectrum of G: the number of leading eigenvalues needed to capture apy_core_variance (default 0.98) of its variance, computed on the full G up to 1,200 genotyped animals and on a seeded random subset above that with the count scaled back, clamped to a floor of 200 and a ceiling of 5,000. An explicit apy_core_size overrides the rule and is recorded as such. The response's apy.core_rule carries the rule, the target, the captured proportion, whether the spectrum was sampled and on how many animals, and the chosen core.

Operator path and its gate. Above the dense ceiling the same APY G⁻¹ can be applied as an operator inside the H matrix without forming the dense inverse (use_operator_path, default false). It is gated: it delivers only when the manifest shows the agreement gate (corr ≥ 0.999 and max |ΔEBV| ≤ 0.10 σₐ against the dense path) was met for the population's size class and core rule. Measured at 1,000 animals with 600 genotyped: the default rule (0.98, core 231) gives corr 0.9946 and 0.45 σₐ and is not admitted; a variance target of 0.998 (core 481: corr 0.999997, 0.022 σₐ) or a core of at least two thirds of the genotyped animals meets it and is admitted. Larger size classes have no dense reference and are unmet. operator_gate_override: true runs the operator anyway as a labelled measurement with auto_apply forced off, so an ungated value never reaches an animal record. The Edge runtime's measured dense ceiling is ~1,190 animals on its 2-second CPU budget; the container runtime would reach ~5,600 once deployed (not running); a 20,000 × 8,000 operator run did not finish within three hours and is recorded as such.

Reference: Misztal 2014, Pocrnic et al. 2016. Phase E.1 gate record: docs/phase-E1/01-core-rule-gate.md.

Sparse Henderson A⁻¹

For pedigree-only solves at scale, A⁻¹ is built directly via Quaas 1976 rules without ever forming dense A:

For animal i with parents (s, d) and inbreeding F_s, F_d:
  α = 1 / (0.5 − 0.25(F_s + F_d)) (both parents known)
  α = 1 / (0.75 − 0.25 F_known) (one parent known)
  α = 1 (both unknown)
Contributions:
  A⁻¹[i,i] += α
  A⁻¹[s,s], A⁻¹[d,d] += α/4
  A⁻¹[i,s], A⁻¹[i,d] −= α/2 (and symmetric)
  A⁻¹[s,d] += α/4 (and symmetric)

F_i (inbreeding) is computed via Meuwissen-Luo 1992: depth-limited recursion through shared ancestors. Result: A⁻¹ stored as CSR with ~5 non-zeros per row regardless of N.

Activated automatically when N ≥ 3000 and no genotypes are loaded; force with sparse_solver: true.

Variance component estimation

The dictionary-default σ² values shipped with the engine are industry averages. Re-fitting them against your data is what turns a generic evaluation into a calibrated one.

EM-REML

Restricted maximum likelihood by expectation-maximisation. At each iteration, with C = D + λA⁻¹:

  1. Solve for û and form C⁻¹
  2. σ²₉' = [ û'A⁻¹û + σ²ₑ·tr(A⁻¹C⁻¹) ] / N
  3. σ²ₑ' = [ Σ(y−û)² + σ²ₑ·tr(D C⁻¹) ] / n
  4. Stop when the relative change falls below the tolerance

The trace terms are the expectation step. They are what makes this an estimator rather than a plug-in of the conditional mean, which is biased downward.

Activate with vce_method: "reml". Returns posterior σ²₉, σ²ₑ, λ. No asymptotic standard error is returned, because EM does not yield one.

Status: not validated. Every EM-REML estimate is rejected by the known-heritability recovery gate and the supplied prior is kept instead; the rejection is recorded on the run. Use vce_method: "ai_reml" below for the estimator that passes.

Reference: Dempster, Laird & Rubin 1977; Searle, Casella & McCulloch 1992.

AI-REML — the gated estimator

Average-information REML (Gilmour, Thompson & Cullis 1995; Johnson & Thompson 1995), kernel core/js/vce-reml.js (VCE.AI.1), fitted per trait or trait pair on y = Xb + Zu + Wp + e with u ~ N(0, G₀ ⊗ A), a permanent-environment effect where records repeat, sparse Henderson A⁻¹ with Meuwissen–Luo inbreeding, the coefficient matrix applied as an operator under preconditioned conjugate gradients, traces by Hutchinson probes, a Newton step with step-halving and Marquardt damping, and standard errors from the inverse average-information matrix by the delta method.

Gate. Before any estimate is shown or used it has to recover known parameters on simulated populations (20 replicates per cell, criteria and tolerances fixed before the numbers were seen). It passes 8 of 9 cells. The failing cell sets the floors: heritability and repeatability are usable from 500 animals with records; a genetic correlation from 2,000 animals recorded on both traits, and not before. Below the floor the run says so per parameter and keeps the supplied value. Activate with vce_method: "ai_reml" (aireml_max_iter 25, aireml_tol 1e-4); every run reports per trait whether its variance components were estimated by this gated estimator or supplied from the literature, and which (variance_component_provenance).

History: an earlier average-information path was withdrawn in August 2026 because its information matrix carried no C⁻¹ term and it returned 0.000 or 1.000 depending on the start. The current kernel is a new derivation; its fixed point is checked against a direct likelihood evaluation independently of the gate.

Gibbs VCE

Bayesian alternative with conjugate scaled-inverse-chi-square priors. Per trait:

σ²ₐ | u ~ scaled-inv-χ²(νₐ + N, (νₐ·Sₐ + u'A⁻¹u) / (νₐ + N))
σ²ₑ | y, u ~ scaled-inv-χ²(νₑ + n_obs, (νₑ·Sₑ + e'e) / (νₑ + n_obs))

Defaults: ν = 4 degrees of freedom, S = dictionary value. After burn-in (200 iter), sample 400 to compute posterior mean. Geweke z-statistic on the σ²ₐ chain reports convergence — |z| < 1.96 declares convergence.

Activate with vce_method: "gibbs". Not gated: the Gibbs posterior is reported on the run but its estimates are rejected for delivery ("has not passed the known-h2 recovery gate") and the supplied values are kept. Only AI-REML above has passed the gate.

SNP variable-selection priors

Standard GBLUP assumes every SNP contributes equally (prior is N(0, σ²ᵤ) for all). Variable-selection priors allow some SNPs to have zero effect and others to have large effects — better for traits with major-effect loci on a polygenic background.

BayesC

Spike-and-slab. Each SNP has probability π of being "out" (zero effect) or (1 − π) of being "in" (effect ~ N(0, σ²ᵤ)). Per SNP, full-conditional sampler:

log_BF = 0.5·log(σ²ₑ / (σ²ₑ + σ²ᵤ·z_j'z_j))
        + 0.5 · (z_j'r/σ²ₑ)² / (z_j'z_j/σ²ₑ + 1/σ²ᵤ)
        + log((1−π) / π)
P(in) = σ(log_BF)

Output: per-SNP posterior inclusion probability (PIP) — the fraction of post-burn iterations the SNP was sampled "in". GBLUP cannot produce a PIP, this is the BayesC differentiator. Top-50 PIP SNPs are returned in the API response.

Activate with snp_prior: "bayesC". Defaults: 500 burn, 1000 sample.

Reference: Habier et al. 2011, Garrick & Fernando 2013.

BayesR

4-class mixture prior generalising BayesC. Each SNP belongs to one of (zero, ×1e-4, ×1e-3, ×1e-2) effect-variance scales. The class proportions π_classes are themselves Dirichlet-sampled. Used by Australian dairy MGBSI.

Status: fails the recovery gate. On simulated data with a known architecture BayesC recovers it and BayesR does not, so a BayesR posterior is reported but is never allowed to overwrite breeding values (applied: false, reason recorded on the run row). The four-class structure is in principle better suited to a few large-effect loci over many small ones; on this implementation that has not been shown.

Activate with snp_prior: "bayesR". Returns per-SNP class probabilities for the top-50 PIP SNPs.

Reference: Erbe et al. 2012, Moser et al. 2015.

SS-BayesC (Single-step propagation)

BayesC and BayesR run on genotyped animals only. SS-BayesC propagates the marker-derived BVs to non-genotyped animals via pedigree:

u_n_imputed = A_n,2 · A₂₂⁻¹ · û_2

where û_2 is the BayesC posterior mean for genotyped animals. Now every animal in the pedigree benefits from variable selection, not just the genotyped subset. Result is blended with the polygenic GBLUP estimate (default 50/50).

Activate with snp_prior_single_step: true (also requires snp_prior: "bayesC" or "bayesR").

Reference: Fernando et al. 2014.

Trait-specific models

Threshold / probit model for binary traits

Fertility, calf survival, dystocia are binary. Treating them as Gaussian gives the wrong BVs. Threshold model assumes a continuous liability θ underlies the binary observation:

y_i = 1 ⟺ θ_i > 0,    θ_i = μ + u_i + e_i,    e_i ~ N(0, σ²ₑ ≡ 1)

Gibbs sampler alternates: (1) sample θ_i from truncated normal given y_i, (2) sample u given θ via the standard PCG solver. Posterior mean of u is the threshold-model BV. σ²ₐ on the liability scale is h²ₗ / (1 − h²ₗ).

Activate with threshold_traits: ["LSURV", "CALVING_EASE"]. Defaults: 300 burn, 700 sample.

Reference: Gianola 1982, Sorensen et al. 1995.

Random regression (Legendre)

For longitudinal traits (growth curves, milk yield curves). Replaces "weight at age N" as separate traits with per-animal polynomial coefficients describing the trajectory:

y(t) = Σₖ αₖ · φₖ(t̃)

where φ are orthonormal Legendre polynomials on [-1, 1] and t̃ is standardised age. Each animal gets (k+1) BV coefficients per trait. Default order = 2 (intercept, slope, curvature).

Activate with random_regression_traits: ["WGT"]. Source observations come from cattle_weighings; ages computed from animal.dob. Per-animal trajectory predictions returned at 5 standard ages (10%, 30%, 50%, 70%, 90% of population age range).

Reference: Schaeffer 2004, Meyer 2007.

Functional longevity (FLC)

What it is. FLC is the cumulative number of calvings a cow has had, recorded at each age from 2 to 10. A cow that is in the herd and joined but does not calve keeps last year's count, so a missed year costs her. Every cow in the evaluation calved at two, so the trait starts at 1. The breeding value is reported at age 6 as extra calves by age 6: a bull with FLC6 +0.20 is expected to leave daughters with 0.10 more calves by six than a bull at 0.

The model. A random regression on Legendre polynomials (three coefficients): additive genetic and permanent-environment effects are random regressions on age, the cow's contemporary group (property × birth year × season of first calving) is a fixed regression on age, and each age record also sits in a calf contemporary group (property × year × season). The residual is homogeneous across ages. The system is solved sparsely — A⁻¹ by Henderson's rules, the genetic covariance applied as a Kronecker operator — and switches to H⁻¹ automatically when the herd has genotypes.

FLC(t) = fixed(t) + Σₖ aₖ φₖ(t̃) + Σₖ pₖ φₖ(t̃) + e,   t = 2…10

Two departures from the published method, and the evidence for them.

The (co)variances are supplied, not estimated. Genemap does not estimate variance components for FLC. They come from Ramos et al. (2026), Table 4 (heritability and additive, permanent-environment and residual variances at each age) and Table 5 (genetic correlations between ages), converted to Legendre coefficient matrices by least squares. The published genetic (co)variances are reproduced to within 0.3%. The paper does not publish permanent-environment correlations; Genemap assumes they equal the genetic correlations, and every run records that assumption.

What to expect. Heritability is low — 0.04 to 0.12 across ages in Ramos et al. (2026) — so a cow's own record moves her breeding value only a little, and accuracy within one herd will be modest. Accuracies are not computed on the current runtime. Sheep FLC is not available. Accuracy rises as more herds record disposals with their reasons, and joinings and pregnancy tests. An evaluation with too little data refuses and lists, cow by cow, what is missing, rather than producing rankings.

Economic value. One extra calf by age 6 is priced through the herd model: the genetic covariance function spreads it across ages, the herd's steady state turns it into more calvings, and the herd's feed costs and prices value them. It is shown as a range, because the herd model cannot represent the cow that is kept rather than culled empty.

References: Ramos P, Tsuruta S, Garcia A, Retallick K, Miller SP, Lourenco D (2026) National genomic evaluation for a novel functional longevity trait. Genet Sel Evol 58:68, doi:10.1186/s12711-026-01087-0 (CC BY 4.0). Oliveira HR, Brito LF, Miller SP, Schenkel FS (2020) Using random regression models to genetically evaluate functional longevity traits in North American Angus cattle. Animals 10:2410, doi:10.3390/ani10122410. Oliveira HR, Miller SP, Brito LF, Schenkel FS (2021) Impact of censored or penalized data in the genetic evaluation of two longevity indicator traits using random regression models in North American Angus cattle. Animals 11:800, doi:10.3390/ani11030800.

Maternal effects

For traits where the dam's milk + maternal behaviour drives a meaningful share of pre-weaning performance (WWT). Genemap auto-derives MWWT phenotypes: each calf's WWT record contributes a paired maternal-effect record against the dam, in a shifted contemporary group.

The bivariate MME with rg(WWT, MWWT) ≈ -0.20 handles the partition naturally. Active by default; toggle off with maternal_effects: false.

Reference: Henderson 1976 (Method R), Willham 1972.

Major-gene fixed effects

FecB, FecX, FecG, FecL, Callipyge, Texel-MSTN, FABP4 — major-effect loci where a single allele substantially shifts the trait mean. The platform pulls per-animal genotype calls from cattle_animals.major_genes and fits per-allele effect β as a fixed effect, then subtracts the dosage × β fit from yCentred BEFORE the BLUP step.

If 20+ animals carry the gene, β is fitted empirically from the data; otherwise the literature default is used. Default literature values:

GeneTarget traitβ / alleleSource
CallipygeYEMD+8 mm—
Texel-MSTNYEMD+6 mm—
FABP4CIMF+0.45 %—

Active by default; toggle off with major_gene_effects: false.

Genotype quality control

Genomic parentage verification

Counts loci where animal and parent are homozygous for opposite alleles. Expected rate for true parent-offspring: < 1% (genotyping error only). Anything ≥ 5% indicates the recorded parent is wrong.

For each mismatch, the platform automatically scans all genotyped same-sex animals and suggests candidate replacement parents that DO pass the test. Surfaced in posterior_state.parentage.

Activate with verify_parentage: true. Tunable thresholds via parentage_threshold_fail (default 0.05) and parentage_threshold_pass (default 0.01).

SNP imputation

Two-stage filler for missing SNP calls:

  1. Parent-averaging. When both parents are genotyped, missing offspring G[i,j] ≈ round((G[s,j] + G[d,j])/2). When only one parent typed, propagate with population-frequency adjustment.
  2. LD-based local. For residual missing, scan ±20 flanking SNPs, pick the most-correlated flanker (|r| ≥ 0.3), impute via E(G_j | G_k = obs) = mean(G_j) + cov_jk/var_k · (obs − mean(G_k)).

Fill rate has not been measured on real herds. Mutates the genotype set in place before G is built. For high-density-from-low-density imputation (50k → 600k), use a HMM-based tool like Beagle or AlphaImpute upstream — Genemap's built-in is for the missing-call class of imputation.

Activate with snp_imputation: true.

Advanced corrections

Metafounders

Single-γ (Legarra 2015): unknown parents are treated as draws from a single base population with self-relationship γ. Estimated as γ = 1 − mean(2pq) from genotyped allele frequencies, bounded [0, 0.5]. Plugs into buildAMatrix(γ) with diagonal contribution 1 + 0.5γ for both-parents-unknown animals.

Multi-breed (Garcia-Baccino 2017): per-breed γ_b plus cross-breed γ_{b,b'} via allele-frequency correlation. Crucial for crossbred / composite herds where different breed components have different effective allele-frequency variances.

Activate with metafounders: true. Per-breed via metafounders_per_breed: true.

Heterosis covariate (Pollak-Quaas)

For each animal, compute pedigree heterosis H = 1 − Σpᵢ² where pᵢ is the proportion of breed i. If observed SNP heterozygosity is recorded (snp_het_rate), use that instead. Per trait, OLS regress yCentred on H within contemporary groups; subtract the fit before BLUP.

γ_t coefficient and variance-explained percentage are reported in heterosis_coefficients per trait.

Reference: Pollak & Quaas 1981.

Tuning is not breed adjustment

BLUPF90's OPTION tunedG rescales G so its summary statistics hit a target — tunedG 1 gives mean(diag(G)) = 1 and mean(offdiag(G)) = 0; tunedG 2 (the preGSf90 default) matches those moments to A₂₂. This is a scaling, applied to the whole matrix.

Those are the same two numbers a correct multi-breed adjustment produces, so they cannot be used as evidence that breed structure has been handled. A tuned but unadjusted G reports a mean diagonal of 1.0 while its between-breed block is still systematically negative — every between-breed pair, not half of them — because the animals are still centred on a pooled base population that no real animal was drawn from. Rescaling moves the average; it does not move the structure.

Ask instead for the two statistics a rescale cannot fake, both algebraic consequences of centring each breed on its own allele frequencies:

Both are reported by the relationship-matrix diagnostics as blocks.between_breed.mean_relationship and blocks.within_breed_identity_error. Note that being scale invariant, they prove the centring and say nothing about the denominators — the scaling sums are checked separately against the geometric mean √Sb · √Sc.

Genemap does not use BLUPF90. The tunedG argument semantics are drawn from a community mirror of the BLUPF90 documentation and are flagged for confirmation against the official manual.

Selection-bias correction

Aggressive selection biases BLUP because the data-generating process is no longer random sampling. Practical approximation (Sorensen-Kennedy 1984): subtract per-trait per-birth-year mean of yCentred BEFORE the solve. Removes systematic between-year drift; leaves within-year additive variance for the random-animal effect.

Requires ≥3 birth-year cohorts. Activate with selection_bias_correction: true. Reports cohort drift range per trait.

Diagnostics

k-fold cross-validation

Holds out a random fraction of phenotype records (default 20%, k=5 implied), retrains BVs on the remaining 80%, computes Pearson correlation between predicted BV and held-out residuals (within contemporary group). Reports per-trait predictive correlation AND predictive accuracy = corr / √h² (Legarra 2008).

Activate with cross_validate: true. Park-Miller LCG seed makes runs deterministic.

VCE drift monitoring

Queries up to 20 historical solver runs from cattle_solver_runs for the org. Per trait: mean and SD of σ²ₐ history, Z-score of current run vs history. |z| ≥ 2 raises an alert — sign that population genetic variance is shifting.

Activate with monitor_vce_drift: true (also requires a VCE method).

Expression scoring (Phase A)

Blood-transcript deliveries are recorded, gated and scored as physiological state readings. Three plain statements govern everything on this layer:

  1. A score is a state reading. It says where an animal's sample sits, on the day it was taken, against a reference distribution of sampled animals. It is labelled Physiological score — not a breeding value everywhere it appears, and Illustrative — not validated while its definition is unvalidated (every definition, in this phase).
  2. No genetic parameter has been estimated for any expression trait. No heritability, no genetic correlation, no accuracy. The bridge table that registers a score as a trait refuses a genetic-parameter source by check constraint.
  3. Expression is not used in breeding values. Nothing in mgt_scores or the tables behind it is read by the solver, an EBV or an index.

How it works: Transcript upload takes three CSVs (run identity, one row per sample, the expression matrix), matches every sample to an animal through a worksheet, and runs the QC gate (mapping rate, read depth, RIN where supplied, a sex check against the registry) with thresholds that each name their source. Counts are normalised (CPM, TMM, log2) and a per-run batch shift is removed where the design allows it; a run fully confounded with its sampling sessions is refused adjustment with the reason. A score is a weighted signature or a rank enrichment over an Ensembl-116 gene set, placed on a stored reference snapshot, and written only with a complete provenance manifest (species, reference genome, annotation, quantification tool, normalisation and batch-model versions, QC status, definition, reference snapshot, engine commit, run, session, provider). External scorers receive opaque result ids and normalised values — no animal or organisation identifier — and their scores come back through Genemap's callback, placed and labelled by Genemap.

Where to look: the State and Samples & scores panels on an animal's page, and the Expression profile for a cohort. Tables: mgt_providers, mgt_gene_annotations, mgt_expression_matrices, mgt_score_definitions, mgt_reference_distributions, mgt_scores, mgt_score_traits, mgt_qc_thresholds, mgt_sex_markers, mgt_scorer_requests, extending the mgt_sampling_sessions / mgt_biosamples / mgt_assay_runs / mgt_transcript_results layer. Code: core/js/expression-ingest.js, expression-normalise.js, expression-score.js, expression-scorer.js, animal-state-panel.js. Edge function: expression-scorer-callback.

Since Phase E.0 a score is placed against a reference stratum: the breed group of the sampled animal where that group has at least 10 reference animals, otherwise the whole reference, and placement.stratum says which. Reprocess all deliveries, in order (Deliveries panel; expression-process-run with reprocess_all) re-runs every delivery in date order under the current definitions and stamps one batch id on every log row it writes.

Environment (season) channel

Every phenotype, weighing, carcase record and biosample is linked at commit to the environment snapshot for its property and date (mgt_environment_snapshots: 90-day rainfall decile against the 1991–2020 climatology, temperature-humidity index, feed-gap state and pasture quality band, sourced daily from SeasonRisk by environment-snapshot-sync; the property resolves to the organisation's primary property when the record names none; a day without a snapshot stays unlinked and is never given a neighbouring day). mgt_backfill_environment_links() links waiting rows when a snapshot arrives later. The solver reports the linked snapshots with emit_environment_covariates; it does not fit them.

Trait registry

One registry, mgt_trait_registry with mgt_trait_stages and mgt_trait_scales, is the source of every trait definition the platform uses: the cattle trait definitions and carcase registry sync into it by trigger, and the client-side trait-config.js is generated from a snapshot of it (scripts/export-trait-registry.ts → scripts/generate-trait-config.js) and pinned by a test, so a page and the solver cannot disagree about a trait's scale, direction or stage. Threshold routing for ordinal traits reads the registry. Uploads commit through mgt_commit_write_plan in one transaction from a staged plan.

API: ssgblup-solve

Endpoint

POST /functions/v1/ssgblup-solve
Headers:
  Content-Type: application/json
  Authorization: Bearer <jwt>
  apikey: <supabase_anon_key>
Body: { "species": "cattle", ... see flags below ... }

Request flags

FlagTypeDefaultDescription
speciesstringrequired — no default"sheep" or "cattle". Selects every table the run touches. A missing species is an error: it previously defaulted to sheep, which meant a cattle page solved the sheep herd. Both species are supported and cattle runs live (the Clear Creek reference herd is evaluated on the deployed solver). The packed cattle genotype store exists and is empty of SNP rows today, which is a data fact, not a support fact: a cattle run without genotypes is a pedigree BLUP.
traitsstring[]15-trait defaultSubset of traits to solve.
g_blend_alphanumber0.95Weight on G in H matrix.
auto_applyboolfalseRecord the run's EBVs and accuracies in ebv_genemap_values, each row tied to the run (since 2026-10-16 the solver never writes the animals table, and never touches breed association EBVs). Opt-in: omitting it writes nothing. It previously defaulted to TRUE, and this row previously named cattle_animals — neither was correct.
Reference population
use_reference_populationbooltrueAuto-match producer animals to silent reference + walk pedigree closure.
ref_pedigree_depthint5Closure depth.
Pedigree module, relationship matrix, environment
use_pedigree_modulebooltrueAncestors from the pedigree module enter the relationship matrix as ghost animals (no records) so descendants stay related; pedigree_module_depth (default 5) generations above the organisation's linked animals.
grm_methodstring"unadjusted""unadjusted" (VanRaden) | "adjusted" (breed-adjusted GRM_a, centred within breed, regularised (1−w)G + wI at w = 0.01) | "composition". The run records which it used.
emit_environment_covariatesboolfalseCarry each record's linked environment snapshot (rainfall decile, heat load, feed-gap state) on the response. No model change: the covariates are reported, not fitted.
outer_tol / max_outernumber / int1e-4 / 250Outer-loop stop on the normalised change between passes, and the pass cap.
APY and the operator path
apy_core_variancenumber0.98Share of the variance of G the core must capture (the spectrum rule). apy_core_size overrides it explicitly.
use_operator_pathboolfalseApply APY G⁻¹ as an operator inside H. Delivers only where the gate record shows the agreement gate met for the size class and core rule; otherwise not applied, with the reason.
operator_gate_overrideboolfalseRun the operator where its gate is unmet, as a labelled measurement. Forces auto_apply off.
Variance components
vce_methodstringnull"ai_reml" (gated, passes) | "reml" (EM, rejected) | "gibbs" (ungated, rejected) | null. Only "ai_reml" estimates are used, and only above the floors (500 for h² and repeatability; 2,000 for rg).
SNP priors
snp_priorstringnull"bayesC" | "bayesR" | null.
snp_prior_single_stepboolfalsePropagate marker BVs to non-genotyped via pedigree.
Trait-specific
threshold_traitsstring[][]Trait codes to fit with probit Gibbs.
random_regression_traitsstring[][]Trait codes for Legendre RR.
maternal_effectsbooltrueAuto-derive maternal phenotypes.
major_gene_effectsbooltrueFit known major-gene loci as fixed effects.
Genotype QC
verify_parentageboolfalseOpposing-homozygosity test.
snp_imputationboolfalseParent-avg + LD imputation.
Advanced
metafoundersboolfalseγ-corrected A matrix.
metafounders_per_breedboolfalsePer-breed γ estimation.
use_apybool/nullautoAuto-fires past 1500 genotyped; core sized by the spectrum rule above.
sparse_solverbool/nullautoHenderson sparse A⁻¹ at scale.
selection_bias_correctionboolfalsePer-cohort mean correction.
Diagnostics
cross_validateboolfalsek-fold CV with predictive correlation.
monitor_vce_driftboolfalseTrack posterior σ²ₐ across runs.

Response shape

{
  "version": "SSG.M.S.7",
  "solver_run_id": "...",
  "n_animals": 1234,
  "iterations": 18,
  "compute_ms": 2840,
  "convergence": "converged",
  "traits": [ ... ],
  "accuracy_summary": { trait: { mean_acc_post, max, min } },
  "heterosis_coefficients": { trait: { gamma, n_obs, var_explained_pct } },
  "reference_population": { n_seed, n_total, max_depth, n_ghosts_added },
  "pedigree_module":   { used, depth, n_linked, n_ghosts, ... },
  "environment_covariates": { emitted, n_records_linked, by_record: [ ... ] } | null,
  "operator_path":     { requested, applied, reason, core_rule, gate: { met, met_by, override, ungated_delivery } },
  "outer_loop":        { passes, coupling: "G0_inverse", outer_tol, converged, model_identity: { ... } },
  "variance_component_provenance": { trait: { source: "ai_reml" | "supplied", floor_met, ... } },
  "verifications_guide": { gate: { establishes, does_not, invariant_to } },
  "grm":               { method, breeds, diagnostics, ... },
  "vce_posterior":     { trait: { method, sigA2_post, sigE2_post, lambda_post, ... } },
  "bayesC_posterior":  { trait: { pi_post, sigU2_post, top_pip_snps, ... } },
  "bayesR_posterior":  { trait: { pi_classes_post, top_class_probs, ... } },
  "threshold_models":  { trait: { n1, n0, mu_post, h2_liability, ... } },
  "random_regression": { trait: { basis_order, age_range_days, ... } },
  "metafounders":      { gamma, gamma_estimated },
  "metafounders_breed":{ gammaByBreed, gammaCross, n_per_breed },
  "apy":               { core_size, non_core_size, auto, core_rule: { rule, variance_target, captured, sampled, chosen } },
  "sparse_solver":     { N, nnz, nnz_per_row },
  "major_genes":       { trait: [ { gene, beta, n_genotyped } ] },
  "selection_bias":    { trait: { n_cohorts, cohort_drift_range, year_means } },
  "imputation":        { imputed_count, parent_avg_count, ld_count, ... },
  "parentage":         { total_animals_with_genotypes, summary, verifications },
  "vce_drift":         { trait: { history_mean, current, z_score, alert } },
  "cross_validation":  { trait: { n_held_out, predictive_corr, predictive_accuracy } },
  "animal_results":    [ { animal_id, tag, name, sex, breed, asbvs, accuracies } ]
}

API: enrich-from-reference

Service-role-only edge function called by upload pages. Hashes producer identifiers and looks up matched reference records, returning anonymous enrichment metadata (pedigree depth, contemporary-group size, cross-references). Never exposes plaintext identities.

POST /functions/v1/enrich-from-reference
Body: { animals: [ { herd, tag, rfid, name, dob } ] }

SQL RPCs

Database functions exposed via Supabase RPC:

Database schema

The major tables:

TablePurpose
cattle_animalsPer-animal records: tag, name, sex, dob, sire/dam, breed, indexes, major_genes, snp_het_rate. (asbvs / accuracies are a frozen legacy field since 2026-10-16.)
ebv_external_valuesAppend-only EBV history from outside Genemap — breed association (LAMBPLAN, BREEDPLAN), commercial genomic (Zoetis Inherit Select) or not confirmed — each value with its provider, evaluation date and import batch.
ebv_genemap_valuesGenemap's own EBVs, one set per solver run. ebv_current gives each animal's latest evaluation from each source with a plain-English source label.
cattle_phenotypesPer-trait observations.
cattle_weighingsTime-stamped weight records (auto-classified BWT/WWT/PWT/YWT by age).
cattle_carcase_recordsAbattoir kill sheets (CWT, CFAT, CEMD, CIMF, LMY).
cattle_genotypesPacked SNP arrays (base64 uint8). Per-animal one row.
cattle_solver_runsAudit log per solve. Posterior states, heterosis coefficients, accuracy summary, advanced-method outputs.
cattle_farm_profilesPer-org farm profile.
genemap_reference_recordsSilent reference. RLS deny-all; service-role read only.
genemap_platform_configHolds the platform salt.
mgt_organizationsMulti-tenant org tree.
mgt_membershipsUser ↔ org links.
mgt_consentsCross-business consent grants.
mgt_trait_registry, mgt_trait_stages, mgt_trait_scalesThe single trait registry that generates trait-config.js.
mgt_environment_snapshots, mgt_environment_sync_runsDaily season snapshot per property and the sync log; records link to a snapshot by environment_snapshot_id.
mgt_write_plan_stagingStaged upload plans committed in one transaction by mgt_commit_write_plan.
mgt_scores, mgt_score_definitions, mgt_reference_distributions, mgt_expression_matricesExpression layer (state readings, never breeding values).
mgt_vce_estimatesResearch variance-component estimates with floor, SE and verdict per parameter.
farm_economic_weights, market_dataPer-account economic weights anchored to a market snapshot id (see the economic engine notes on the rank page).

Two consent surfaces:

  1. Reference-population contribution. Opt-in, default off (migration 20260920). Sheep accounts only: cattle_farm_profiles has no consent column and there is no auto-seed trigger on cattle_animals, so no cattle record is contributed. For a sheep account the switch is on the sheep farm profile; when on, an auto-seed trigger on sheep_animals hashes the animal's identifiers using the platform salt and inserts an anonymous record into genemap_reference_records. Plaintext identifiers never leave the database — the salt is held by a security-definer function readable only by service_role. Revoke via genemap_revoke_my_reference_records().
  2. Cross-business genotype pooling. Stored in mgt_consents with consent_type='gebv_pooling'. Source organisation grants target organisation read access to its genotypes for solver pooling. Audited per solve in cattle_solver_runs.notes.

Bibliography