Skip to content

Commit 6cfd0ea

Browse files
authored
1062 quality control needs versioning for evaluations (#1067)
* refactor: changing references -> reference * feat: add an overall evaluator name * feat: adding QCStatus and lists of status for versioning * chore: lint * tests: updating tests for QCStatus
1 parent ebd9319 commit 6cfd0ea

File tree

4 files changed

+98
-46
lines changed

4 files changed

+98
-46
lines changed

examples/quality_control.json

Lines changed: 36 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
11
{
22
"describedBy": "https://raw.githubusercontent.com/AllenNeuralDynamics/aind-data-schema/main/src/aind_data_schema/core/quality_control.py",
33
"schema_version": "1.0.0",
4-
"overall_status": "Pass",
5-
"overall_status_date": "2022-11-22",
4+
"overall_status": [
5+
{
6+
"evaluator": "Automated",
7+
"status": "Pass",
8+
"timestamp": "2022-11-22"
9+
}
10+
],
611
"evaluations": [
712
{
813
"evaluation_modality": {
@@ -12,29 +17,33 @@
1217
"evaluation_stage": "Processing",
1318
"evaluation_name": "Drift map",
1419
"evaluation_description": "Qualitative check that drift map shows minimal movement",
15-
"evaluator": "Fred Flintstone",
16-
"evaluation_date": "2022-11-22",
1720
"qc_metrics": [
1821
{
1922
"name": "Probe A drift",
2023
"value": "High",
2124
"description": null,
22-
"references": null
25+
"reference": "ecephys-drift-map"
2326
},
2427
{
2528
"name": "Probe B drift",
2629
"value": "Low",
2730
"description": null,
28-
"references": null
31+
"reference": "ecephys-drift-map"
2932
},
3033
{
3134
"name": "Probe C drift",
3235
"value": "Low",
3336
"description": null,
34-
"references": null
37+
"reference": "ecephys-drift-map"
38+
}
39+
],
40+
"evaluation_status": [
41+
{
42+
"evaluator": "Fred Flintstone",
43+
"status": "Fail",
44+
"timestamp": "2022-11-22"
3545
}
3646
],
37-
"stage_status": "Fail",
3847
"notes": "Manually annotated: failed due to high drift on probe A"
3948
},
4049
{
@@ -45,23 +54,27 @@
4554
"evaluation_stage": "Raw data",
4655
"evaluation_name": "Video frame count check",
4756
"evaluation_description": null,
48-
"evaluator": "Fred Flinstone",
49-
"evaluation_date": "2022-11-22",
5057
"qc_metrics": [
5158
{
5259
"name": "video_1_num_frames",
5360
"value": 662,
5461
"description": null,
55-
"references": null
62+
"reference": null
5663
},
5764
{
5865
"name": "video_2_num_frames",
5966
"value": 662,
6067
"description": null,
61-
"references": null
68+
"reference": null
69+
}
70+
],
71+
"evaluation_status": [
72+
{
73+
"evaluator": "Fred Flintstone",
74+
"status": "Fail",
75+
"timestamp": "2022-11-22"
6276
}
6377
],
64-
"stage_status": "Pass",
6578
"notes": "Pass when video_1_num_frames==video_2_num_frames"
6679
},
6780
{
@@ -72,29 +85,33 @@
7285
"evaluation_stage": "Raw data",
7386
"evaluation_name": "Probes present",
7487
"evaluation_description": null,
75-
"evaluator": "Automated",
76-
"evaluation_date": "2022-11-22",
7788
"qc_metrics": [
7889
{
7990
"name": "ProbeA_success",
8091
"value": true,
8192
"description": null,
82-
"references": null
93+
"reference": null
8394
},
8495
{
8596
"name": "ProbeB_success",
8697
"value": true,
8798
"description": null,
88-
"references": null
99+
"reference": null
89100
},
90101
{
91102
"name": "ProbeC_success",
92103
"value": true,
93104
"description": null,
94-
"references": null
105+
"reference": null
106+
}
107+
],
108+
"evaluation_status": [
109+
{
110+
"evaluator": "Automated",
111+
"status": "Pass",
112+
"timestamp": "2022-11-22"
95113
}
96114
],
97-
"stage_status": "Pass",
98115
"notes": null
99116
}
100117
],

examples/quality_control.py

Lines changed: 35 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
from aind_data_schema_models.modalities import Modality
66

7-
from aind_data_schema.core.quality_control import QCEvaluation, QualityControl, QCMetric, Stage, Status
7+
from aind_data_schema.core.quality_control import QCEvaluation, QualityControl, QCMetric, Stage, Status, QCStatus
88

99
t = date(2022, 11, 22)
1010

@@ -13,32 +13,44 @@
1313
evaluation_description="Qualitative check that drift map shows minimal movement",
1414
evaluation_modality=Modality.ECEPHYS,
1515
evaluation_stage=Stage.PROCESSING,
16-
evaluator="Fred Flintstone",
17-
evaluation_date=t,
16+
evaluation_status=[
17+
QCStatus(
18+
evaluator="Fred Flintstone",
19+
timestamp=t,
20+
status=Status.FAIL
21+
)
22+
],
1823
qc_metrics=[
1924
QCMetric(
2025
name="Probe A drift",
21-
value="High"
26+
value="High",
27+
reference="ecephys-drift-map"
2228
),
2329
QCMetric(
2430
name="Probe B drift",
25-
value="Low"
31+
value="Low",
32+
reference="ecephys-drift-map"
2633
),
2734
QCMetric(
2835
name="Probe C drift",
29-
value="Low"
36+
value="Low",
37+
reference="ecephys-drift-map"
3038
)
3139
],
32-
stage_status=Status.FAIL,
3340
notes="Manually annotated: failed due to high drift on probe A"
3441
)
3542

3643
eval1 = QCEvaluation(
3744
evaluation_name="Video frame count check",
3845
evaluation_modality=Modality.BEHAVIOR_VIDEOS,
3946
evaluation_stage=Stage.RAW,
40-
evaluator="Fred Flinstone",
41-
evaluation_date=t,
47+
evaluation_status=[
48+
QCStatus(
49+
evaluator="Fred Flintstone",
50+
timestamp=t,
51+
status=Status.FAIL
52+
)
53+
],
4254
qc_metrics=[
4355
QCMetric(
4456
name="video_1_num_frames",
@@ -49,16 +61,20 @@
4961
value=662
5062
)
5163
],
52-
stage_status=Status.PASS,
5364
notes="Pass when video_1_num_frames==video_2_num_frames"
5465
)
5566

5667
eval2 = QCEvaluation(
5768
evaluation_name="Probes present",
5869
evaluation_modality=Modality.ECEPHYS,
5970
evaluation_stage=Stage.RAW,
60-
evaluator="Automated",
61-
evaluation_date=t,
71+
evaluation_status=[
72+
QCStatus(
73+
evaluator="Automated",
74+
timestamp=t,
75+
status=Status.PASS
76+
)
77+
],
6278
qc_metrics=[
6379
QCMetric(
6480
name="ProbeA_success",
@@ -73,12 +89,16 @@
7389
value=True
7490
)
7591
],
76-
stage_status=Status.PASS,
7792
)
7893

7994
q = QualityControl(
80-
overall_status="Pass",
81-
overall_status_date=t,
95+
overall_status=[
96+
QCStatus(
97+
evaluator="Automated",
98+
timestamp=t,
99+
status=Status.PASS
100+
)
101+
],
82102
evaluations=[eval0, eval1, eval2]
83103
)
84104

src/aind_data_schema/core/quality_control.py

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,21 @@ class Stage(str, Enum):
3131
ANALYSIS = "Analysis"
3232

3333

34+
class QCStatus(BaseModel):
35+
"""Description of a QC status, set by an evaluator"""
36+
37+
evaluator: str = Field(..., title="Status evaluator full name")
38+
status: Status = Field(..., title="Status")
39+
timestamp: date = Field(..., title="Status date")
40+
41+
3442
class QCMetric(BaseModel):
3543
"""Description of a single quality control metric"""
44+
3645
name: str = Field(..., title="Metric name")
3746
value: Any = Field(..., title="Metric value")
3847
description: Optional[str] = Field(default=None, title="Metric description")
39-
references: Optional[List[str]] = Field(default=None, title="Metric reference URLs")
48+
reference: Optional[str] = Field(default=None, title="Metric reference image URL or plot type")
4049

4150

4251
class QCEvaluation(AindModel):
@@ -46,10 +55,8 @@ class QCEvaluation(AindModel):
4655
evaluation_stage: Stage = Field(..., title="Evaluation stage")
4756
evaluation_name: str = Field(..., title="Evaluation name")
4857
evaluation_description: Optional[str] = Field(default=None, title="Evaluation description")
49-
evaluator: str = Field(..., title="Evaluator full name")
50-
evaluation_date: date = Field(..., title="Evaluation date")
5158
qc_metrics: List[QCMetric] = Field(..., title="QC metrics")
52-
stage_status: Status = Field(..., title="Stage status")
59+
evaluation_status: List[QCStatus] = Field(..., title="Evaluation status")
5360
notes: Optional[str] = Field(default=None, title="Notes")
5461

5562

@@ -59,7 +66,6 @@ class QualityControl(AindCoreModel):
5966
_DESCRIBED_BY_URL = AindCoreModel._DESCRIBED_BY_BASE_URL.default + "aind_data_schema/core/quality_control.py"
6067
describedBy: str = Field(_DESCRIBED_BY_URL, json_schema_extra={"const": _DESCRIBED_BY_URL})
6168
schema_version: Literal["1.0.0"] = Field("1.0.0")
62-
overall_status: Status = Field(..., title="Overall status")
63-
overall_status_date: date = Field(..., title="Date of status")
69+
overall_status: List[QCStatus] = Field(..., title="Overall status")
6470
evaluations: List[QCEvaluation] = Field(..., title="Evaluations")
6571
notes: Optional[str] = Field(default=None, title="Notes")

tests/test_quality_control.py

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from aind_data_schema_models.modalities import Modality
77
from pydantic import ValidationError
88

9-
from aind_data_schema.core.quality_control import QCEvaluation, QualityControl, QCMetric, Stage, Status
9+
from aind_data_schema.core.quality_control import QCEvaluation, QualityControl, QCMetric, Stage, Status, QCStatus
1010

1111

1212
class QualityControlTests(unittest.TestCase):
@@ -20,8 +20,13 @@ def test_constructors(self):
2020

2121
test_eval = QCEvaluation(
2222
evaluation_name="Drift map",
23-
evaluator="Bob",
24-
evaluation_date=date.fromisoformat("2020-10-10"),
23+
evaluation_status=[
24+
QCStatus(
25+
evaluator="Fred Flintstone",
26+
timestamp=date.fromisoformat("2020-10-10"),
27+
status=Status.PASS
28+
)
29+
],
2530
evaluation_modality=Modality.ECEPHYS,
2631
evaluation_stage=Stage.PROCESSING,
2732
qc_metrics=[
@@ -36,12 +41,16 @@ def test_constructors(self):
3641
references=["s3://some-data-somewhere"]
3742
)
3843
],
39-
stage_status=Status.PASS,
4044
)
4145

4246
q = QualityControl(
43-
overall_status_date=date.fromisoformat("2020-10-10"),
44-
overall_status=Status.PASS,
47+
overall_status=[
48+
QCStatus(
49+
evaluator="Bob",
50+
timestamp=date.fromisoformat("2020-10-10"),
51+
status=Status.PASS
52+
)
53+
],
4554
evaluations=[
4655
test_eval
4756
],

0 commit comments

Comments
 (0)