pooledscreenid 0.1.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pooledscreenid/__init__.py +14 -0
- pooledscreenid/audit.py +186 -0
- pooledscreenid/cli.py +23 -0
- pooledscreenid/ledger.py +42 -0
- pooledscreenid/models.py +64 -0
- pooledscreenid-0.1.1.dist-info/METADATA +109 -0
- pooledscreenid-0.1.1.dist-info/RECORD +11 -0
- pooledscreenid-0.1.1.dist-info/WHEEL +5 -0
- pooledscreenid-0.1.1.dist-info/entry_points.txt +2 -0
- pooledscreenid-0.1.1.dist-info/licenses/LICENSE +21 -0
- pooledscreenid-0.1.1.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"""Public API for PooledScreenID."""
|
|
2
|
+
|
|
3
|
+
from .audit import evaluate_evidence, run_audit, summarize_fold_gains
|
|
4
|
+
from .models import AuditConfig, EvidenceVector
|
|
5
|
+
|
|
6
|
+
__all__ = [
|
|
7
|
+
"AuditConfig",
|
|
8
|
+
"EvidenceVector",
|
|
9
|
+
"evaluate_evidence",
|
|
10
|
+
"run_audit",
|
|
11
|
+
"summarize_fold_gains",
|
|
12
|
+
]
|
|
13
|
+
|
|
14
|
+
__version__ = "0.1.1"
|
pooledscreenid/audit.py
ADDED
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
"""Evidence-vector construction and priority-ordered claim resolution."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import csv
|
|
6
|
+
import hashlib
|
|
7
|
+
import json
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
from statistics import mean
|
|
10
|
+
from typing import Any
|
|
11
|
+
|
|
12
|
+
from .ledger import build_claim_ledger
|
|
13
|
+
from .models import AuditConfig, EvidenceVector
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def sha256_file(path: str | Path) -> str:
|
|
17
|
+
target = Path(path)
|
|
18
|
+
return hashlib.sha256(target.read_bytes()).hexdigest()
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def summarize_fold_gains(path: str | Path) -> dict[str, Any]:
|
|
22
|
+
"""Summarize a frozen fold table.
|
|
23
|
+
|
|
24
|
+
Required columns are `fold`, `unadjusted_gain` and `adjusted_gain`.
|
|
25
|
+
Folds are descriptive repetitions, not independent biological units.
|
|
26
|
+
"""
|
|
27
|
+
target = Path(path)
|
|
28
|
+
with target.open(newline="", encoding="utf-8") as handle:
|
|
29
|
+
rows = list(csv.DictReader(handle))
|
|
30
|
+
if not rows:
|
|
31
|
+
raise ValueError("fold-gain table is empty")
|
|
32
|
+
required = {"fold", "unadjusted_gain", "adjusted_gain"}
|
|
33
|
+
missing = required - set(rows[0])
|
|
34
|
+
if missing:
|
|
35
|
+
raise ValueError(f"missing fold columns: {sorted(missing)}")
|
|
36
|
+
folds = [row["fold"] for row in rows]
|
|
37
|
+
if len(folds) != len(set(folds)):
|
|
38
|
+
raise ValueError("fold identifiers must be unique")
|
|
39
|
+
unadjusted = [float(row["unadjusted_gain"]) for row in rows]
|
|
40
|
+
adjusted = [float(row["adjusted_gain"]) for row in rows]
|
|
41
|
+
return {
|
|
42
|
+
"folds": len(rows),
|
|
43
|
+
"unadjusted_gain_mean": mean(unadjusted),
|
|
44
|
+
"adjusted_gain_mean": mean(adjusted),
|
|
45
|
+
"unadjusted_gain_range": [min(unadjusted), max(unadjusted)],
|
|
46
|
+
"adjusted_gain_range": [min(adjusted), max(adjusted)],
|
|
47
|
+
"input_sha256": sha256_file(target),
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def evaluate_evidence(config: AuditConfig, summary: dict[str, Any]) -> EvidenceVector:
|
|
52
|
+
threshold = config.materiality_threshold
|
|
53
|
+
unadjusted = float(summary["unadjusted_gain_mean"])
|
|
54
|
+
adjusted = float(summary["adjusted_gain_mean"])
|
|
55
|
+
material = unadjusted >= threshold
|
|
56
|
+
control_associated = material and adjusted < threshold
|
|
57
|
+
|
|
58
|
+
distance: float | None = None
|
|
59
|
+
if config.eta is None or config.eta_boundary is None:
|
|
60
|
+
separability = "not_evaluated"
|
|
61
|
+
else:
|
|
62
|
+
distance = config.eta_boundary - config.eta
|
|
63
|
+
if config.eta > config.eta_boundary:
|
|
64
|
+
separability = "non_identifiable"
|
|
65
|
+
elif distance <= config.boundary_zone:
|
|
66
|
+
separability = "boundary_proximal"
|
|
67
|
+
else:
|
|
68
|
+
separability = "within_calibrated_region"
|
|
69
|
+
|
|
70
|
+
external_status = str(config.external_calibration.get("status", "not_evaluated"))
|
|
71
|
+
if separability == "non_identifiable":
|
|
72
|
+
resolution = "non_identifiable"
|
|
73
|
+
elif separability == "boundary_proximal":
|
|
74
|
+
resolution = "restricted_boundary_proximal"
|
|
75
|
+
elif not material:
|
|
76
|
+
resolution = "no_material_increment"
|
|
77
|
+
elif control_associated:
|
|
78
|
+
resolution = "control_associated"
|
|
79
|
+
elif external_status == "supportive_same_estimand":
|
|
80
|
+
resolution = "externally_supported_surviving_increment"
|
|
81
|
+
else:
|
|
82
|
+
resolution = "surviving_increment"
|
|
83
|
+
|
|
84
|
+
allowed = [
|
|
85
|
+
f"The frozen {config.estimand} and its uncertainty may be reported.",
|
|
86
|
+
"Cold-start transport and information-source attribution are reported separately.",
|
|
87
|
+
]
|
|
88
|
+
restricted: list[str] = []
|
|
89
|
+
prohibited = [
|
|
90
|
+
"Prediction alone does not establish a binding or causal mechanism.",
|
|
91
|
+
"This analysis does not support patient-level treatment recommendation.",
|
|
92
|
+
]
|
|
93
|
+
if not material:
|
|
94
|
+
restricted.append("No material increment was observed at the frozen threshold.")
|
|
95
|
+
prohibited.append("Do not interpret the result as equivalence or a biological null.")
|
|
96
|
+
if control_associated:
|
|
97
|
+
restricted.append("The apparent increment is associated with the outcome-blind control channel.")
|
|
98
|
+
prohibited.append("Do not claim that adjustment proves the shared signal is purely technical.")
|
|
99
|
+
if separability in {"non_identifiable", "boundary_proximal"}:
|
|
100
|
+
restricted.append("Fine-grained attribution is restricted by the prespecified separability assessment.")
|
|
101
|
+
prohibited.append("Do not make a structure-specific attribution from this dataset.")
|
|
102
|
+
if separability == "not_evaluated":
|
|
103
|
+
prohibited.append("Do not claim that representation separability was established.")
|
|
104
|
+
if external_status == "supportive_distinct_estimand":
|
|
105
|
+
restricted.append(
|
|
106
|
+
"External positive calibration concerns a distinct estimand and does not validate the target representation."
|
|
107
|
+
)
|
|
108
|
+
elif external_status in {"not_evaluated", "external_contrast_only"}:
|
|
109
|
+
prohibited.append("Do not claim external calibration of the target estimand.")
|
|
110
|
+
|
|
111
|
+
context = {
|
|
112
|
+
"prediction_unit": config.prediction_unit,
|
|
113
|
+
"independent_unit": config.independent_unit,
|
|
114
|
+
"block_unit": config.block_unit,
|
|
115
|
+
"target_representation": config.target_representation,
|
|
116
|
+
"outcome_blind_control": config.outcome_blind_control,
|
|
117
|
+
"source_id": config.source_id,
|
|
118
|
+
"fold_summary": summary,
|
|
119
|
+
"folds_are_independent_biological_units": False,
|
|
120
|
+
}
|
|
121
|
+
return EvidenceVector(
|
|
122
|
+
dataset_id=config.dataset_id,
|
|
123
|
+
folds=int(summary["folds"]),
|
|
124
|
+
unadjusted_gain_mean=unadjusted,
|
|
125
|
+
adjusted_gain_mean=adjusted,
|
|
126
|
+
materiality_threshold=threshold,
|
|
127
|
+
material_signal="supported" if material else "below_threshold",
|
|
128
|
+
control_association="supported" if control_associated else "not_supported",
|
|
129
|
+
separability=separability,
|
|
130
|
+
external_calibration=config.external_calibration,
|
|
131
|
+
eta=config.eta,
|
|
132
|
+
eta_boundary=config.eta_boundary,
|
|
133
|
+
boundary_distance=distance,
|
|
134
|
+
claim_resolution=resolution,
|
|
135
|
+
allowed_claims=tuple(allowed),
|
|
136
|
+
restricted_claims=tuple(restricted),
|
|
137
|
+
prohibited_claims=tuple(prohibited),
|
|
138
|
+
audit_context=context,
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
def _markdown(report: dict[str, Any]) -> str:
|
|
143
|
+
return "\n".join(
|
|
144
|
+
[
|
|
145
|
+
f"# {report['dataset_id']} PooledScreenID report",
|
|
146
|
+
"",
|
|
147
|
+
f"- Claim resolution: `{report['claim_resolution']}`",
|
|
148
|
+
f"- Unadjusted gain: `{report['unadjusted_gain_mean']:.6f}`",
|
|
149
|
+
f"- Adjusted gain: `{report['adjusted_gain_mean']:.6f}`",
|
|
150
|
+
f"- Materiality threshold: `{report['materiality_threshold']:.6f}`",
|
|
151
|
+
f"- Separability: `{report['separability']}`",
|
|
152
|
+
f"- External calibration: `{report['external_calibration']['status']}`",
|
|
153
|
+
"",
|
|
154
|
+
"## Allowed claims",
|
|
155
|
+
*[f"- {x}" for x in report["allowed_claims"]],
|
|
156
|
+
"",
|
|
157
|
+
"## Restricted claims",
|
|
158
|
+
*([f"- {x}" for x in report["restricted_claims"]] or ["- None recorded."]),
|
|
159
|
+
"",
|
|
160
|
+
"## Prohibited interpretations",
|
|
161
|
+
*[f"- {x}" for x in report["prohibited_claims"]],
|
|
162
|
+
"",
|
|
163
|
+
]
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
def run_audit(config_path: str | Path, output_dir: str | Path) -> tuple[dict[str, Any], dict[str, Any]]:
|
|
168
|
+
config_file = Path(config_path).resolve()
|
|
169
|
+
config = AuditConfig.from_dict(json.loads(config_file.read_text(encoding="utf-8")))
|
|
170
|
+
fold_file = (config_file.parent / config.fold_gains_csv).resolve()
|
|
171
|
+
summary = summarize_fold_gains(fold_file)
|
|
172
|
+
vector = evaluate_evidence(config, summary)
|
|
173
|
+
report = vector.to_dict()
|
|
174
|
+
report["software"] = {"name": "pooledscreenid", "version": "0.1.1"}
|
|
175
|
+
report["config_sha256"] = sha256_file(config_file)
|
|
176
|
+
ledger = build_claim_ledger(report)
|
|
177
|
+
target = Path(output_dir)
|
|
178
|
+
target.mkdir(parents=True, exist_ok=True)
|
|
179
|
+
(target / "report.json").write_text(json.dumps(report, indent=2) + "\n", encoding="utf-8")
|
|
180
|
+
(target / "report.md").write_text(_markdown(report), encoding="utf-8")
|
|
181
|
+
(target / "claim_ledger.json").write_text(json.dumps(ledger, indent=2) + "\n", encoding="utf-8")
|
|
182
|
+
if config.expected_claim_resolution and report["claim_resolution"] != config.expected_claim_resolution:
|
|
183
|
+
raise RuntimeError(
|
|
184
|
+
f"frozen expectation mismatch: {report['claim_resolution']} != {config.expected_claim_resolution}"
|
|
185
|
+
)
|
|
186
|
+
return report, ledger
|
pooledscreenid/cli.py
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"""Command-line interface."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import argparse
|
|
6
|
+
import json
|
|
7
|
+
|
|
8
|
+
from .audit import run_audit
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def main() -> None:
|
|
12
|
+
parser = argparse.ArgumentParser(prog="pooledscreenid")
|
|
13
|
+
sub = parser.add_subparsers(dest="command", required=True)
|
|
14
|
+
audit = sub.add_parser("audit", help="run an evidence-to-claim audit")
|
|
15
|
+
audit.add_argument("--config", required=True)
|
|
16
|
+
audit.add_argument("--output-dir", required=True)
|
|
17
|
+
args = parser.parse_args()
|
|
18
|
+
report, _ = run_audit(args.config, args.output_dir)
|
|
19
|
+
print(json.dumps({"dataset_id": report["dataset_id"], "claim_resolution": report["claim_resolution"]}))
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
if __name__ == "__main__":
|
|
23
|
+
main()
|
pooledscreenid/ledger.py
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"""Versioned machine-readable claim ledger."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def build_claim_ledger(report: dict[str, Any]) -> dict[str, Any]:
|
|
9
|
+
evidence_id = f"{report['dataset_id']}:screen-audit-v1"
|
|
10
|
+
return {
|
|
11
|
+
"schema_version": "1.1.0",
|
|
12
|
+
"software": report["software"],
|
|
13
|
+
"dataset_id": report["dataset_id"],
|
|
14
|
+
"evidence": [
|
|
15
|
+
{
|
|
16
|
+
"evidence_id": evidence_id,
|
|
17
|
+
"material_signal": report["material_signal"],
|
|
18
|
+
"control_association": report["control_association"],
|
|
19
|
+
"separability": report["separability"],
|
|
20
|
+
"external_calibration": report["external_calibration"],
|
|
21
|
+
"claim_resolution": report["claim_resolution"],
|
|
22
|
+
"resolution_inputs": {
|
|
23
|
+
"material_signal": report["material_signal"],
|
|
24
|
+
"control_association": report["control_association"],
|
|
25
|
+
"separability": report["separability"],
|
|
26
|
+
"external_calibration": report["external_calibration"]["status"],
|
|
27
|
+
},
|
|
28
|
+
"config_sha256": report["config_sha256"],
|
|
29
|
+
"input_sha256": report["audit_context"]["fold_summary"]["input_sha256"],
|
|
30
|
+
}
|
|
31
|
+
],
|
|
32
|
+
"allowed_claims": [
|
|
33
|
+
{"text": text, "evidence_ids": [evidence_id]} for text in report["allowed_claims"]
|
|
34
|
+
],
|
|
35
|
+
"restricted_claims": [
|
|
36
|
+
{"text": text, "evidence_ids": [evidence_id]} for text in report["restricted_claims"]
|
|
37
|
+
],
|
|
38
|
+
"prohibited_claims": [
|
|
39
|
+
{"text": text, "evidence_ids": [evidence_id]} for text in report["prohibited_claims"]
|
|
40
|
+
],
|
|
41
|
+
"human_review_required": True,
|
|
42
|
+
}
|
pooledscreenid/models.py
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"""Typed configuration and evidence objects."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from dataclasses import asdict, dataclass, field
|
|
6
|
+
from typing import Any
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@dataclass(frozen=True)
|
|
10
|
+
class AuditConfig:
|
|
11
|
+
dataset_id: str
|
|
12
|
+
fold_gains_csv: str
|
|
13
|
+
materiality_threshold: float
|
|
14
|
+
target_representation: str
|
|
15
|
+
outcome_blind_control: str
|
|
16
|
+
prediction_unit: str
|
|
17
|
+
independent_unit: str
|
|
18
|
+
block_unit: str
|
|
19
|
+
estimand: str
|
|
20
|
+
eta: float | None = None
|
|
21
|
+
eta_boundary: float | None = None
|
|
22
|
+
boundary_zone: float = 0.0
|
|
23
|
+
source_id: str = ""
|
|
24
|
+
external_calibration: dict[str, Any] = field(
|
|
25
|
+
default_factory=lambda: {
|
|
26
|
+
"status": "not_evaluated",
|
|
27
|
+
"source": "",
|
|
28
|
+
"estimand": "",
|
|
29
|
+
"note": "No external calibration was supplied for this audit.",
|
|
30
|
+
}
|
|
31
|
+
)
|
|
32
|
+
expected_claim_resolution: str | None = None
|
|
33
|
+
metadata: dict[str, Any] = field(default_factory=dict)
|
|
34
|
+
|
|
35
|
+
@classmethod
|
|
36
|
+
def from_dict(cls, value: dict[str, Any]) -> "AuditConfig":
|
|
37
|
+
return cls(**value)
|
|
38
|
+
|
|
39
|
+
def to_dict(self) -> dict[str, Any]:
|
|
40
|
+
return asdict(self)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
@dataclass(frozen=True)
|
|
44
|
+
class EvidenceVector:
|
|
45
|
+
dataset_id: str
|
|
46
|
+
folds: int
|
|
47
|
+
unadjusted_gain_mean: float
|
|
48
|
+
adjusted_gain_mean: float
|
|
49
|
+
materiality_threshold: float
|
|
50
|
+
material_signal: str
|
|
51
|
+
control_association: str
|
|
52
|
+
separability: str
|
|
53
|
+
external_calibration: dict[str, Any]
|
|
54
|
+
eta: float | None
|
|
55
|
+
eta_boundary: float | None
|
|
56
|
+
boundary_distance: float | None
|
|
57
|
+
claim_resolution: str
|
|
58
|
+
allowed_claims: tuple[str, ...]
|
|
59
|
+
restricted_claims: tuple[str, ...]
|
|
60
|
+
prohibited_claims: tuple[str, ...]
|
|
61
|
+
audit_context: dict[str, Any]
|
|
62
|
+
|
|
63
|
+
def to_dict(self) -> dict[str, Any]:
|
|
64
|
+
return asdict(self)
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: pooledscreenid
|
|
3
|
+
Version: 0.1.1
|
|
4
|
+
Summary: Outcome-blind shortcut and separability diagnostics for pooled variant-effect screens
|
|
5
|
+
Author: Niu Niu, Fang Wei, Yan Wang, Hu Liu, Bin Wu
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Documentation, https://doi.org/10.5281/zenodo.22156510
|
|
8
|
+
Project-URL: Repository, https://doi.org/10.5281/zenodo.22156510
|
|
9
|
+
Keywords: deep mutational scanning,cold start,negative control,identifiability,variant effect
|
|
10
|
+
Classifier: Development Status :: 4 - Beta
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
16
|
+
Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
|
|
17
|
+
Requires-Python: >=3.10
|
|
18
|
+
Description-Content-Type: text/markdown
|
|
19
|
+
License-File: LICENSE
|
|
20
|
+
Dynamic: license-file
|
|
21
|
+
|
|
22
|
+
# PooledScreenID
|
|
23
|
+
|
|
24
|
+
PooledScreenID is a small, installable Python package for reporting four
|
|
25
|
+
quantities separately in cold-start pooled variant-effect analyses:
|
|
26
|
+
|
|
27
|
+
1. material predictive gain;
|
|
28
|
+
2. association with an outcome-blind control channel;
|
|
29
|
+
3. representation separability at a prespecified operating scale;
|
|
30
|
+
4. external calibration, kept distinct from the target estimand; and
|
|
31
|
+
5. the resulting allowed, restricted and prohibited claims.
|
|
32
|
+
|
|
33
|
+
The package does not infer a molecular mechanism and does not make treatment
|
|
34
|
+
recommendations. A cold split is treated as a transport test, not as proof of
|
|
35
|
+
the information source used by a model.
|
|
36
|
+
|
|
37
|
+
## Install
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
python -m pip install pooledscreenid-0.1.1-py3-none-any.whl
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
For a source checkout:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
python -m pip install -e .
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Minimal Python API
|
|
50
|
+
|
|
51
|
+
```python
|
|
52
|
+
from pooledscreenid import run_audit
|
|
53
|
+
|
|
54
|
+
report, ledger = run_audit(
|
|
55
|
+
config_path="examples/configs/egfr.json",
|
|
56
|
+
output_dir="example_output/egfr",
|
|
57
|
+
)
|
|
58
|
+
print(report["claim_resolution"])
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Command line
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
pooledscreenid audit \
|
|
65
|
+
--config examples/configs/egfr.json \
|
|
66
|
+
--output-dir example_output/egfr
|
|
67
|
+
|
|
68
|
+
pooledscreenid audit \
|
|
69
|
+
--config examples/configs/met.json \
|
|
70
|
+
--output-dir example_output/met
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Each run writes `report.json`, `report.md` and `claim_ledger.json`. Inputs,
|
|
74
|
+
configuration, source hashes and expected outputs are frozen in the release.
|
|
75
|
+
The ledger exposes `material_signal`, `control_association`, `separability` and
|
|
76
|
+
`external_calibration` as independent fields. `claim_resolution` is generated
|
|
77
|
+
from those fields under priority-ordered rules and never replaces them.
|
|
78
|
+
|
|
79
|
+
PooledScreenID 0.1.1 is the article-linked frozen release. The public API is
|
|
80
|
+
managed with semantic versioning. It supports Python 3.10-3.13 and has no
|
|
81
|
+
third-party runtime dependencies; the test suite uses pytest.
|
|
82
|
+
|
|
83
|
+
## Included end-to-end examples
|
|
84
|
+
|
|
85
|
+
- `EGFR`: ten frozen variant-cold folds from the L858R-background pooled EGFR
|
|
86
|
+
inhibitor screen, plus the outcome-free geometry and conditional operating
|
|
87
|
+
boundary used in the manuscript.
|
|
88
|
+
- `MET`: ten frozen variant-cold folds from an independently selected pooled
|
|
89
|
+
MET inhibitor screen. The example demonstrates a result below the materiality
|
|
90
|
+
gate and explicitly leaves separability unevaluated.
|
|
91
|
+
|
|
92
|
+
These examples begin with frozen, source-derived fold diagnostics rather than
|
|
93
|
+
raw sequencing reads. They reproduce the evidence-to-claim stage of the
|
|
94
|
+
framework; raw count processing and model fitting remain documented in the
|
|
95
|
+
accompanying analysis repository.
|
|
96
|
+
|
|
97
|
+
## Interpretation order
|
|
98
|
+
|
|
99
|
+
The software reports the four-axis evidence vector before returning a summary label. If
|
|
100
|
+
shared predictability exceeds its prespecified boundary, or lies inside a
|
|
101
|
+
prespecified boundary zone, fine-grained attribution is restricted before any
|
|
102
|
+
control-specific contrast is interpreted. Absence of a material increment is
|
|
103
|
+
not an equivalence or biological-null claim.
|
|
104
|
+
|
|
105
|
+
## Release integrity
|
|
106
|
+
|
|
107
|
+
`RELEASE_MANIFEST.json` and `SHA256SUMS.txt` bind the software, tests, continuous-integration configuration, examples,
|
|
108
|
+
configuration files and claim ledger to this release. The Zenodo record is the
|
|
109
|
+
permanent release series: <https://doi.org/10.5281/zenodo.22156510>.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
pooledscreenid/__init__.py,sha256=9o0NnQxjPSiEPOkB9CSV8WQ4a6mjQk92ps2c4VZb67I,305
|
|
2
|
+
pooledscreenid/audit.py,sha256=b2p55RmTYJWwQ5gGv2Cx2MsIYB0qIGJtlCP0Rs_uOh4,8092
|
|
3
|
+
pooledscreenid/cli.py,sha256=HhIgkN4tyI5ekIT1b4XgAsdIkBQYlPqqj4IE_FOGrRI,684
|
|
4
|
+
pooledscreenid/ledger.py,sha256=Mj0jD49eyXyPrTb_Ob4VH6AkRDFt_wg51lXAsuSdGxA,1746
|
|
5
|
+
pooledscreenid/models.py,sha256=p7tUH6kJ0xbHHyV4e5Tb7DHxia6o1BdRIBjEI0Et1A4,1737
|
|
6
|
+
pooledscreenid-0.1.1.dist-info/licenses/LICENSE,sha256=LLLMBRn7oZ4PwrMz6U8UCSVYRigdirt1qhSA6mP7ju0,1084
|
|
7
|
+
pooledscreenid-0.1.1.dist-info/METADATA,sha256=tZFvDpwtXnWJdX_jtAn4adM1Br5fmAbQyHpKujTZ0xA,4236
|
|
8
|
+
pooledscreenid-0.1.1.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
|
|
9
|
+
pooledscreenid-0.1.1.dist-info/entry_points.txt,sha256=yf1FXDIoXcQunmZ58K4UJO4nuO7LsTcSELBm6TEvAqU,59
|
|
10
|
+
pooledscreenid-0.1.1.dist-info/top_level.txt,sha256=j6eeGZFsoHs0t_XDOw04BjRL8Tl_otA3G0bpwccAtTQ,15
|
|
11
|
+
pooledscreenid-0.1.1.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 PooledScreenID contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
pooledscreenid
|