isabl-submit-data — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited isabl-submit-data (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
You are helping the user submit new sequencing data to the Isabl platform.
Work through these steps systematically:
Individual (patient/subject)
├── identifier: unique ID from source system
├── species: HUMAN, MOUSE, etc.
├── gender: MALE, FEMALE, UNKNOWN
├── center: where samples originated
│
└── Sample (tissue specimen)
├── identifier: sample ID
├── category: TUMOR, NORMAL, GERMLINE, etc.
├── disease: disease classification
│
└── Experiment (sequencing run)
├── identifier: library/run ID
├── technique: WGS, WES, RNA, etc.
├── platform: ILLUMINA, ONT, etc.
├── center: where sequenced
├── projects: [project memberships]
└── raw_data: [file paths with metadata]import isabl_cli as ii
# Check available centers
centers = list(ii.get_instances("centers"))
print("Centers:", [c.slug for c in centers])
# Check available techniques
techniques = list(ii.get_instances("techniques"))
print("Techniques:", [(t.slug, t.method) for t in techniques])
# Check available platforms
platforms = list(ii.get_instances("platforms"))
print("Platforms:", [p.slug for p in platforms])
# Check available diseases
diseases = list(ii.get_instances("diseases"))
print("Diseases:", [d.acronym for d in diseases[:10]])
# Check target project
project = ii.get_instance("projects", PROJECT_PK)
print(f"Target project: {project.title}")# Create a new center
center = ii.create_instance("centers", {
"name": "Memorial Sloan Kettering",
"acronym": "MSK",
})
print(f"Created center: {center.slug}")
# Create a new technique
technique = ii.create_instance("techniques", {
"name": "WGS 30X",
"method": "WGS",
"category": "DNA",
})
print(f"Created technique: {technique.slug}")
# Create a new disease
disease = ii.create_instance("diseases", {
"name": "Acute Myeloid Leukemia",
"acronym": "AML",
})
print(f"Created disease: {disease.slug}")# Example: submitting tumor-normal pair
submission_data = {
"individual": {
"identifier": "PATIENT_001",
"species": "HUMAN",
"gender": "FEMALE",
"center": {"slug": "msk"},
},
"samples": [
{
"identifier": "PATIENT_001_TUMOR",
"category": "TUMOR",
"disease": {"acronym": "AML"},
},
{
"identifier": "PATIENT_001_NORMAL",
"category": "NORMAL",
"disease": {"acronym": "AML"},
},
],
"experiments": [
{
"sample_identifier": "PATIENT_001_TUMOR",
"identifier": "LIB_001_T_WGS",
"technique": {"slug": "wgs-30x"},
"platform": {"slug": "illumina-novaseq"},
"center": {"slug": "msk"},
"raw_data": [
{
"file_url": "/data/fastq/LIB_001_T_R1.fastq.gz",
"file_type": "FASTQ",
"file_data": {"read": "R1", "lane": "L001"},
},
{
"file_url": "/data/fastq/LIB_001_T_R2.fastq.gz",
"file_type": "FASTQ",
"file_data": {"read": "R2", "lane": "L001"},
},
],
},
{
"sample_identifier": "PATIENT_001_NORMAL",
"identifier": "LIB_001_N_WGS",
"technique": {"slug": "wgs-30x"},
"platform": {"slug": "illumina-novaseq"},
"center": {"slug": "msk"},
"raw_data": [
{
"file_url": "/data/fastq/LIB_001_N_R1.fastq.gz",
"file_type": "FASTQ",
"file_data": {"read": "R1", "lane": "L001"},
},
{
"file_url": "/data/fastq/LIB_001_N_R2.fastq.gz",
"file_type": "FASTQ",
"file_data": {"read": "R2", "lane": "L001"},
},
],
},
],
}import os
# Check all raw_data files exist
errors = []
for exp in submission_data["experiments"]:
for rd in exp.get("raw_data", []):
path = rd["file_url"]
if not os.path.exists(path):
errors.append(f"Missing: {path}")
if errors:
print("Validation errors:")
for e in errors:
print(f" {e}")
else:
print("All files validated!")
# Check identifiers don't already exist
existing = list(ii.get_experiments(
identifier__in=[e["identifier"] for e in submission_data["experiments"]]
))
if existing:
print(f"Warning: {len(existing)} experiments already exist")# 1. Create individual
individual = ii.create_instance("individuals", {
"identifier": submission_data["individual"]["identifier"],
"species": submission_data["individual"]["species"],
"gender": submission_data["individual"]["gender"],
"center": submission_data["individual"]["center"],
})
print(f"Created individual: {individual.system_id}")
# 2. Create samples
samples = {}
for sample_data in submission_data["samples"]:
sample = ii.create_instance("samples", {
"identifier": sample_data["identifier"],
"category": sample_data["category"],
"disease": sample_data["disease"],
"individual": {"pk": individual.pk},
})
samples[sample_data["identifier"]] = sample
print(f"Created sample: {sample.system_id}")
# 3. Create experiments
for exp_data in submission_data["experiments"]:
sample = samples[exp_data["sample_identifier"]]
experiment = ii.create_instance("experiments", {
"identifier": exp_data["identifier"],
"sample": {"pk": sample.pk},
"technique": exp_data["technique"],
"platform": exp_data["platform"],
"center": exp_data["center"],
"raw_data": exp_data["raw_data"],
"projects": [{"pk": PROJECT_PK}],
})
print(f"Created experiment: {experiment.system_id}")# Create experiment with nested individual/sample
# API will get-or-create the hierarchy
experiment = ii.create_instance("experiments", {
"identifier": "LIB_001_T_WGS",
"sample": {
"identifier": "PATIENT_001_TUMOR",
"category": "TUMOR",
"disease": {"acronym": "AML"},
"individual": {
"identifier": "PATIENT_001",
"species": "HUMAN",
"gender": "FEMALE",
"center": {"slug": "msk"},
},
},
"technique": {"slug": "wgs-30x"},
"platform": {"slug": "illumina-novaseq"},
"center": {"slug": "msk"},
"projects": [{"pk": PROJECT_PK}],
"raw_data": [
{"file_url": "/data/fastq/R1.fastq.gz", "file_type": "FASTQ"},
{"file_url": "/data/fastq/R2.fastq.gz", "file_type": "FASTQ"},
],
})# Create submission form for bulk import
submission = ii.create_instance("submissions", {
"title": "Batch import 2024-01",
"data": {
"experiments": [...], # List of experiment dicts
},
})
# Process the submission
ii.process_submission(submission.pk, commit=True)# Check experiments were created
experiments = list(ii.get_experiments(
projects=PROJECT_PK,
identifier__startswith="LIB_001"
))
print(f"Created {len(experiments)} experiments:")
for exp in experiments:
print(f" {exp.system_id}")
print(f" Sample: {exp.sample.identifier} ({exp.sample.category})")
print(f" Individual: {exp.sample.individual.identifier}")
print(f" Raw data files: {len(exp.raw_data or [])}")The raw_data field is a list of file records:
raw_data = [
{
"file_url": "/path/to/file.fastq.gz", # Required
"file_type": "FASTQ", # FASTQ, BAM, CRAM, etc.
"file_data": { # Optional metadata
"read": "R1", # R1 or R2 for paired
"lane": "L001", # Flowcell lane
"PU": "FLOWCELL:LANE:SAMPLE", # Platform unit
"LB": "library_id", # Library
"PL": "ILLUMINA", # Platform
},
"hash_value": "abc123...", # Optional: file checksum
"hash_method": "MD5", # MD5, SHA256, etc.
}
]| Category | Description |
|---|---|
TUMOR | Tumor tissue |
NORMAL | Normal tissue (for somatic calling) |
GERMLINE | Germline sample |
PRIMARY | Primary tumor |
METASTASIS | Metastatic site |
RELAPSE | Relapse sample |
XENOGRAFT | PDX model |
UNKNOWN | Unknown category |
import pandas as pd
df = pd.read_csv("samples.csv")
for _, row in df.iterrows():
experiment = ii.create_instance("experiments", {
"identifier": row["library_id"],
"sample": {
"identifier": row["sample_id"],
"category": row["category"],
"disease": {"acronym": row["disease"]},
"individual": {
"identifier": row["patient_id"],
"species": "HUMAN",
"center": {"slug": "msk"},
},
},
"technique": {"slug": row["technique"]},
"platform": {"slug": row["platform"]},
"center": {"slug": "msk"},
"projects": [{"pk": PROJECT_PK}],
"raw_data": [
{"file_url": row["r1_path"], "file_type": "FASTQ"},
{"file_url": row["r2_path"], "file_type": "FASTQ"},
],
})
print(f"Created: {experiment.system_id}")# Add raw_data to existing experiment
exp = ii.get_instance("experiments", system_id="ISB_H000001_T01_WGS01")
ii.patch_instance("experiments", exp.pk, {
"raw_data": [
{"file_url": "/new/path/R1.fastq.gz", "file_type": "FASTQ"},
{"file_url": "/new/path/R2.fastq.gz", "file_type": "FASTQ"},
],
})# Add existing experiment to a new project
exp = ii.get_instance("experiments", system_id="ISB_H000001_T01_WGS01")
current_projects = [{"pk": p.pk} for p in exp.projects]
current_projects.append({"pk": NEW_PROJECT_PK})
ii.patch_instance("experiments", exp.pk, {
"projects": current_projects,
})~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.