A language for clinical knowledge
Clinical phenotypes,
thoughtfully modelled.
Turn patient observations into meaningful clinical descriptions. Picorules gives you a small, expressive language to define, compose, and reuse clinical knowledge.
Open source. Built from clinical practice.
Small definitions. Shared understanding.
01 — The approach
Clinical knowledge,
made explicit.
A phenotype is more than a label. It is a description of a patient, built from evidence and the definitions that give it meaning.
Picorules makes those definitions visible: the observations they use, the history they consider, and the smaller constructs they bring together.
See how a ruleblock works- 01
Start with the evidence.
Work with dated observations: measurements, diagnoses, and medications. Make explicit which facts matter, and when.
- 02
Give each construct a definition.
Express a measurement summary, a temporal pattern, or a classification as a named, reusable piece of clinical knowledge.
- 03
Compose a richer picture.
Bring those constructs together into a phenotype definition. Reuse its characteristics in registries, research, and clinical applications.
02 — The language
A small definition.
A clearer intention.
Picorules began by making clinical calculations easier to maintain in a database. Its compact definitions now also run in JavaScript, while keeping the clinical question in view.
WITH egfr_history AS (
SELECT eid, val,
MIN(val::numeric) OVER (
PARTITION BY eid
) AS egfr_lowest,
ROW_NUMBER() OVER (
PARTITION BY eid ORDER BY dt DESC
) AS observation_order
FROM eadv
WHERE att = 'lab_bld_egfr'
)
SELECT eid,
val AS egfr_latest,
egfr_lowest
FROM egfr_history
WHERE observation_order = 1;// Summarise a patient's recorded measurements
egfr_latest => eadv.lab_bld_egfr.val.last();
egfr_lowest => eadv.lab_bld_egfr.val.min();Two questions, made explicit.
What is the latest recorded eGFR? What is the lowest? These summaries are reusable constructs that can contribute to a larger phenotype definition.
Get the complete ruleblockAn observation-summary example, with no disease classification. The SQL shows the retrieval operation; the compiler also supplies the surrounding ruleblock and output structure.
Inspect the actual compiler output PostgreSQL
--================================================
-- SQL Dialect: PostgreSQL
-- Ruleblock: renal_measurements
--================================================
CREATE TABLE ROUT_RENAL_MEASUREMENTS AS
WITH
UEADV AS (
SELECT DISTINCT eid FROM eadv
),
SQ_EGFR_LATEST AS (
SELECT eid, val AS egfr_latest
FROM (
SELECT eid, val,
ROW_NUMBER() OVER (PARTITION BY eid ORDER BY dt DESC) AS rn
FROM eadv
WHERE att = 'lab_bld_egfr'
) ranked
WHERE rn = 1
),
SQ_EGFR_LOWEST AS (
SELECT eid, MIN(val::numeric) AS egfr_lowest
FROM eadv
WHERE att = 'lab_bld_egfr'
GROUP BY eid
),
SQ_RENAL_MEASUREMENTS AS (
SELECT eid,
CASE
WHEN egfr_latest IS NOT NULL THEN 1
ELSE 0
END AS renal_measurements
FROM UEADV
LEFT JOIN SQ_EGFR_LATEST USING (eid)
LEFT JOIN SQ_EGFR_LOWEST USING (eid)
)
SELECT eid,
egfr_latest,
egfr_lowest,
renal_measurements
FROM UEADV
LEFT JOIN SQ_EGFR_LATEST USING (eid)
LEFT JOIN SQ_EGFR_LOWEST USING (eid)
LEFT JOIN SQ_RENAL_MEASUREMENTS USING (eid)
-- ---
Download the SQL History, made usable.
Select the latest result, summarise an interval, or follow change over time. Work with dated observations through the EADV model.
Explore the functions →Definitions that compose.
Reuse named outputs from other ruleblocks. Build richer clinical descriptions from smaller, explicit constructs.
Explore composition →Reasoning beside the rule.
Keep descriptions, citation keys, and output labels alongside the definition with documentation and attribute directives.
Explore documentation →03 — Across platforms
One definition.
Many settings.
Keep your clinical definitions together while adapters handle the data source. Bring shared knowledge to a population registry or an individual patient application.
FHIR
R4 resources
Evaluate definitions against clinical records supplied by a FHIR adapter.
openEHR
Clinical repositories
Access observations in an openEHR repository through an AQL-based adapter.
SQL
Population-scale analysis
Compile definitions for PostgreSQL, SQL Server, and Oracle databases.
How the definitions connect to your data
Fetch what the rule needs.
The FHIR adapter inspects ruleblocks to identify their data requirements and build targeted queries. Terminology mappings connect attributes to the source's codes.
Read about smart fetching →Fit into the clinical workflow.
The same requirements can generate CDS Hooks prefetch templates. SMART on FHIR applications can use the JavaScript evaluator after retrieving their records.
Explore FHIR integration →Keep the mappings explicit.
The openEHR adapter uses AQL to retrieve observations. Each deployment supplies the coding, units, and dated values its definitions expect.
Explore openEHR integration →04 — The npm packages
Build it into
your application.
Bring your clinical definitions into the software you already build. Start with the compiler, then add adapters and tools as you need them.
Explore the SDKThe compiler & runtime
picorules-compiler-js-coreA JavaScript and TypeScript package for parsing ruleblocks, generating SQL, and evaluating definitions directly in your application.
npm install picorules-compiler-js-coreAdapters & tools, also on npm
Try the JavaScript runtime In your browser
The same ruleblock can run against records in JavaScript. This example uses two synthetic observations, with no database connection.
import { parse, evaluate, EadvDataAdapter }
from 'picorules-compiler-js-core';
// Serve the example ruleblock with your application.
const source = await fetch('/examples/renal_measurements.prb')
.then((response) => response.text());
const [rule] = parse([
{ name: 'renal_measurements', text: source, isActive: true }
]);
// Synthetic records for one patient.
const adapter = new EadvDataAdapter([
{ eid: 1, att: 'lab_bld_egfr', dt: '2025-01-15', val: 44 },
{ eid: 1, att: 'lab_bld_egfr', dt: '2025-06-01', val: 52 }
]);
console.log(evaluate(rule, adapter));
// { egfr_latest: 52, egfr_lowest: 44, renal_measurements: 1 }Latest: 52 · Lowest: 44
05 — Picorules Studio
Room to write.
Space to explore.
A browser-based workspace for developing ruleblocks. Write a definition, inspect its compiled SQL, and explore the results with synthetic data.
- Syntax highlighting and a Monaco editor
- SQL compilation for three database dialects
- Synthetic data generation and PostgreSQL execution
renal_measurements.prb
egfr_latest => eadv.lab_bld_egfr.val.last();
egfr_lowest => eadv.lab_bld_egfr.val.min();| Characteristic | Value |
|---|---|
| Latest recorded eGFR | 52 |
| Lowest recorded eGFR | 44 |
From clinical practice
An idea with
roots in care.
Picorules began in 2019 within Territory Kidney Care, where clinical calculations needed to run inside an Oracle database. The TypeScript compiler extends that foundation to other SQL databases and direct evaluation in JavaScript.
Origins, evidence, and open development
Published TKC studies evaluate specific clinical algorithms. Compiler tests and adapter comparisons examine software behaviour and selected outputs. These are different kinds of evidence, which the project describes separately.
Begin with a definition
Give clinical knowledge
a language.
Learn the ideas behind Picorules, or open the Studio and start exploring.
From an observation
to a construct.
From a construct
to a clearer picture.