Version context: engine label patcaniq-loader-0.8.1b (as returned by the calculation API). This
document describes how the web UI is meant to be used and how the backend evaluates autosomal STR data, based on
the current FastAPI implementation.
PaternIQ is a browser-based application for autosomal STR workflows in paternity and kinship analysis. The frontend collects case data and sends it to a FastAPI backend, which computes locus-wise contributions and combined likelihoods using population frequencies (STRidER-based data when available).
The public entry point is normally HTTPS on your configured host, for example
https://paterniq.medgene.at. The frontend is served as static files from
frontend/dist via nginx; API routes on the same host are reverse-proxied to the
backend on port 8000.
From inside the same LAN, reaching the public URL may fail on some routers (NAT hairpin). In that case use a hosts file entry mapping the hostname to the server’s LAN IP, or test from mobile data to confirm external access.
Access is restricted. After successful login, the application stores a session token in the
browser’s localStorage (key pattern used in the app: patcan-auth-session) and
sends it as Authorization: Bearer … to protected API routes. The backend validates the session via
GET /auth/session.
Use Logout on shared workstations. If the session expires or is rejected, you must sign in again.
Paternity mode is oriented toward mother–child–alleged father trios (or duo if configured), with paternity-specific verbal conclusions when applicable.
Kinship mode compares two hypotheses using two persons’ genotypes per locus (plus expert tooling in the UI). The backend computes kinship locus likelihood ratios using either a parent–child Mendelian model or an IBD-based model with fixed k0, k1, k2 coefficients for the selected relationship degree.
POST /calculate/trio-autosomal with a structured payload).
A ? help control on the main application shell opens this document in a new browser tab (when
the control is present in the deployed index.html).
The calculation endpoint expects a JSON body with at least:
case — object with analysis settings, including:
population — population key as used by STRidER / backend normalization (e.g. AUSTRIA).analysis_mode — paternity or kinship.analysis_type — trio or duo (duo: motherless workflow).kinship_degree — relationship key for kinship LR (see §8.4).coancestry_coefficient — numeric θ as string or number; combined with kinship_mode for θ presets.kinship_mode — influences θ presets (e.g. manual vs named presets in backend).mutation_mode — standard, include, or strict.genotypes — map of locus name → genotype object. Depending on mode, each locus may contain:
alleged_father, mother, child (two alleles each as strings).person_1, person_2 (fallback: some flows still accept father/child-shaped keys; backend normalizes).Standard autosomal loci are evaluated per marker row. Alleles are normalized (decimal comma, basic cleanup). The backend recognizes off-ladder style entries (e.g. OL, <,> variants) and applies a conservative frequency floor when no reliable regular frequency is available, as described in the methodology text returned with results.
Amelogenin is treated with sex-marker specific logic in kinship evaluation paths.
Core endpoint: POST /calculate/trio-autosomal. For each locus, the backend produces a
paternity index (PI) or kinship LR factor, then multiplies informative loci to form a
combined paternity index (CPI) / combined LR (implementation multiplies informative
contributions; see code for exact status filters).
For paternity mode, the backend also derives a posterior probability (percent) from the
combined LR (CPI) as P = 100 × LR / (LR + 1) when LR ≥ 0, rounded for display.
CPI accumulation: only loci with status informativ or mutation
multiply into CPI (cpi *= pi per locus). Statuses such as kompatibel,
frequenz_fehlt, leer, unvollständig, or ausschluss do not
contribute to the product in that loop (see implementation).
The UI exposes mutation_mode as standard, include, or
strict. Before trio/duo evaluation, the backend maps this to an
effective mode: strict stays strict; both
standard and include become include for the locus routines. In other
words, standard and include behave the same in the current trio/duo pipeline; only
strict changes behaviour (e.g. single-step mutation candidates are not evaluated the same way,
and fallback PI after failed detailed mutation math may use 1.0 instead of 1/μ).
For incompatible trios where a single-step mutation is plausible, the engine may compute a
structured Trio-Mutationsheuristik or motherless (duo) mutation PI using
locus mutation rates and θ-adjusted denominators. If that detailed path fails, a
fallback may assign PI = 1/μ (when effective mode is include) or
PI = 1.0 (when strict), with comments in German in the JSON response.
Several loci carry locus-specific mutation rates in code; where rates are missing, mutation branches may not activate or may use conservative defaults.
Allele frequencies are taken from the configured STRidER CSV when present. Frequencies are adjusted with NRC II-style θ correction as implemented:
p′ = min(1, p + θ(1 − p)) for θ > 0.
The UI may offer θ either as a manual numeric value or via kinship_mode presets
that map to default θ (see backend map KINSHIP_MODE_TO_THETA: e.g. none → 0, father–child → 0.25,
brother–brother → 0.125, etc.). manual uses the entered coefficient directly.
For non-parent–child degrees, the kinship LR at a locus uses the generic form (IBD model):
LR = (k2·P|IBD2 + k1·P|IBD1 + k0·P|IBD0) / P|IBD0
Implemented coefficient sets include:
| Degree key | k0 | k1 | k2 |
|---|---|---|---|
| parent-child | 0 | 1 | 0 |
| full-siblings | 0.25 | 0.50 | 0.25 |
| half-siblings | 0.50 | 0.50 | 0 |
| grandparent-grandchild | 0.50 | 0.50 | 0 |
| avuncular | 0.50 | 0.50 | 0 |
| first-cousins | 0.75 | 0.25 | 0 |
| unrelated | 1 | 0 | 0 |
For parent–child, the backend uses a dedicated Mendelian transmission LR instead of the generic IBD formula (see kinship locus metadata: algorithm label distinguishes parent–child vs IBD kinship LR).
Independently of the selected kinship degree, the backend can compute multi-hypothesis relationship scores by multiplying per-locus contributions across a fixed list (same-person, parent-child, siblings, avuncular, cousins, unrelated, etc.). This supports comparison views in the expert UI layer.
Loci with status ausschluss are listed in summary.exclusion_markers. Loci evaluated
as mutation (single-step mutation explanation) are listed in
summary.mutation_markers.
For hard exclusion in paternity mode, the backend forms
incompatibility_markers = exclusion_markers + mutation_markers (one combined list). If
len(incompatibility_markers) ≥ 3, then hard_exclusion is true:
likelihood_ratio and CPI are forced to 0, probability to 0,
and conclusion_text becomes the German exclusion phrase. A technical note records how many
incompatibility/mutation markers triggered this.
Therefore mutation-interpreted loci count toward the same threshold as exclusions for this rule — not only strict Mendelian exclusions.
The backend can store case snapshots as JSON files under backend/data/saved_cases/. This is a
prototype persistence layer (not a full SQL product). Saved data includes UI-related state as
well as case content—treat backups accordingly.
Print preview uses a separate browser snapshot path for layout. Printing does not replace saving a case to the server store; use Save / Update case when you need the JSON snapshot retained.
frontend/dist; ensure execute bit on home path components for www-data.paterniq-backend service) and authentication.