Use insights and reports from Python¶
Insight and report authoring is available through the server JSON API. Python
applications can use httpx with ordinary dictionaries.
For typed construction and local validation, import the canonical executable
and portable-document contracts from goodomics.schemas.insights:
from goodomics.schemas.insights import (
InsightDocument,
InsightSpec,
ReportDocument,
ReportSpec,
)
InsightSpec and ReportSpec contain executable configuration.
InsightDocument and ReportDocument add the names and identifiers needed for
portable YAML or JSON files. The server's saved-resource request and response
models reuse the same contracts.
import httpx
client = httpx.Client(base_url="http://127.0.0.1:8000/api/v1")
project_id = "rnaseq-core"
Discover selectable values¶
Use /insights/capabilities for approved metadata fields and view constraints,
and /contracts plus /contracts/{contract} for contract fields. Do not guess
field IDs or send table and column names.
capabilities = client.get("/insights/capabilities").raise_for_status().json()
run_fields = [
item for item in capabilities["metadata_fields"]
if item["entity"] == "run"
]
# Each item["field"] is ready to use, such as "metadata/run/status".
salmon = client.get(
"/contracts/salmon:results",
params={"project_id": project_id},
).raise_for_status().json()
Validate and execute an ad hoc insight¶
definition = {
"version": 1,
"analysis": {
"grain": "sample",
"values": [
{"field": "metadata/sample/sample_name"},
{
"field": "salmon:results/general_stats.salmon_percent_mapped",
},
],
},
"view": {"kind": "table"},
}
validation = client.post(
"/insights/validate",
json={**definition, "project_id": project_id},
).raise_for_status().json()
if not validation["valid"]:
raise ValueError(validation["messages"])
result = client.post(
"/insights/execute",
json={**definition, "project_id": project_id, "refresh": True},
).raise_for_status().json()["result"]
print(result["columns"], result["rows"][:5])
The order of analysis.values is the table-column and chart-series order. A
value's field is its default result and view reference. To hide a value
without removing it from the analysis, add that reference to the shared view
setting, for example {"kind": "table", "hidden_values":
["metadata/sample/sample_name"]}.
Add optional "as": "percent_mapped" when a field needs a shorter reference
or when the same field appears more than once. View bindings use as when it is
present and field otherwise.
For a scatter chart, keep the same values and replace the view with explicit field or alias bindings. Matching charts use an inner join for independently resolved values by default.
Save and execute¶
saved = client.post(
"/insights",
json={
**definition,
"insight_id": "sample-qc-overview",
"project_id": project_id,
"name": "Sample QC overview",
},
).raise_for_status().json()
result = client.post(
f"/insights/{saved['insight_id']}/execute",
json={
"project_id": project_id,
"limit": 5000,
"random": True,
},
).raise_for_status().json()["result"]
Saved execution accepts limit, random, export, and refresh overrides,
not analytical changes. Patch the saved insight to change its values or view.
Compose a report¶
report_definition = {
"version": 1,
"name": "RNA-seq QC",
"layout": {"columns": 12, "row_height": 64},
"insights": [
{
"id": saved["insight_id"],
"layout": {"x": 0, "y": 0, "width": 12, "height": 6},
}
],
"refresh_policy": {"mode": "manual"},
}
check = client.post(
"/reports/validate",
json={**report_definition, "project_id": project_id},
).raise_for_status().json()
if not check["valid"]:
raise ValueError(check["messages"])
report = client.post(
"/reports",
json={
**report_definition,
"project_id": project_id,
},
).raise_for_status().json()
Use /reports/{id}/execute for structured results and /reports/render for a
persisted HTML snapshot. Export saved definitions through their /export.yaml
or /export.json routes.