-
Notifications
You must be signed in to change notification settings - Fork 0
feat: create qc module #17
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
29 commits
Select commit
Hold shift + click to select a range
6e5ef75
feat: start adding qc module
arjunsridhar12345 2e9992b
feat: add rest of initial qc module
arjunsridhar12345 403e406
test: add tests
arjunsridhar12345 8a145c3
build: update dependecies and add optional schema dependency
arjunsridhar12345 845f11f
ci: update workflows to install full dependecies
arjunsridhar12345 92b2904
refactor: major overhaul to match architecture
arjunsridhar12345 40652fe
refactor: forgot these in previous commit
arjunsridhar12345 d06260f
test: update tests
arjunsridhar12345 eec629d
feat: add example notebook
arjunsridhar12345 a32318b
fix: don't return 0 if no trials responded to
arjunsridhar12345 39e8a52
test: update tests
arjunsridhar12345 66e3ef5
refactor: don't re-calculate side bias
arjunsridhar12345 82f97b2
test: update tests
arjunsridhar12345 102248e
feat: add initial example notebook
arjunsridhar12345 f41e2bf
fix: remove unused import
arjunsridhar12345 862d960
chore: linting
arjunsridhar12345 847ae31
feat: add lick interval plot to example notebook
arjunsridhar12345 5e43f97
refactor: use pathlib instead of os
arjunsridhar12345 ea5f767
feat: add more complete example
arjunsridhar12345 e023a32
docs: minor update to readme
arjunsridhar12345 89b5d06
refactor: add more details on qa docstrings
arjunsridhar12345 ec50eec
docs: update qc documentation
arjunsridhar12345 9121783
fix: PR feedback
arjunsridhar12345 1667cf1
refactor: pass in trials dataframe instead of a billion parameters
arjunsridhar12345 07edbe3
test: update tests
arjunsridhar12345 a5e2822
refactor: round to 3 decimal places
arjunsridhar12345 6a3feb8
refactor: update qc notebook
arjunsridhar12345 9601087
chore: linting
arjunsridhar12345 c47dcad
Merge branch 'dev' into 16-create-qc-module
arjunsridhar12345 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,65 @@ | ||
| """Quality control for dynamic foraging datasets. | ||
|
|
||
| Builds an ``aind_data_schema`` ``QualityControl`` object from primitive behavior | ||
| data (lick times, per-trial choices) plus the contraqctor-based contract QA. | ||
|
|
||
| The module is organized by QC stage: | ||
|
|
||
| - :mod:`~dynamic_foraging_processing.qc._core` -- the shared stage interface, | ||
| schema helpers, per-check result type, and ``QualityControl`` assembler. | ||
| - :mod:`~dynamic_foraging_processing.qc.raw` -- the raw-data (contract QA) stage. | ||
| - :mod:`~dynamic_foraging_processing.qc.processed` -- the processed-data | ||
| (behavior metrics) stage. | ||
| """ | ||
|
|
||
| from dynamic_foraging_processing.qc._core import ( | ||
| DEFAULT_GROUPING, | ||
| STATUS_CONVERTER, | ||
| BaseQC, | ||
| QCResult, | ||
| bool_to_status, | ||
| build_quality_control, | ||
| make_metric, | ||
| now_seattle, | ||
| now_utc, | ||
| to_builtin, | ||
| to_metrics, | ||
| ) | ||
| from dynamic_foraging_processing.qc.processed import ( | ||
| ProcessedQC, | ||
| behavior_qc_results, | ||
| calculate_lick_intervals, | ||
| lick_interval_results, | ||
| plot_lick_intervals, | ||
| plot_side_bias, | ||
| side_bias_result, | ||
| ) | ||
| from dynamic_foraging_processing.qc.raw import ( | ||
| RawQC, | ||
| contract_qc_metrics, | ||
| results_to_metrics, | ||
| ) | ||
|
|
||
| __all__ = [ | ||
| "DEFAULT_GROUPING", | ||
| "STATUS_CONVERTER", | ||
| "BaseQC", | ||
| "ProcessedQC", | ||
| "QCResult", | ||
| "RawQC", | ||
| "behavior_qc_results", | ||
| "bool_to_status", | ||
| "build_quality_control", | ||
| "calculate_lick_intervals", | ||
| "contract_qc_metrics", | ||
| "lick_interval_results", | ||
| "make_metric", | ||
| "now_seattle", | ||
| "now_utc", | ||
| "plot_lick_intervals", | ||
| "plot_side_bias", | ||
| "results_to_metrics", | ||
| "side_bias_result", | ||
| "to_builtin", | ||
| "to_metrics", | ||
| ] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| """Shared QC infrastructure: the stage interface, schema helpers, the per-check | ||
| result type, and the ``QualityControl`` assembler. | ||
|
|
||
| These pieces are stage-agnostic; the raw and processed stages build on them. | ||
| """ | ||
|
|
||
| from dynamic_foraging_processing.qc._core.base import BaseQC | ||
| from dynamic_foraging_processing.qc._core.builder import ( | ||
| DEFAULT_GROUPING, | ||
| build_quality_control, | ||
| ) | ||
| from dynamic_foraging_processing.qc._core.result import QCResult, to_metrics | ||
| from dynamic_foraging_processing.qc._core.schema import ( | ||
| STATUS_CONVERTER, | ||
| bool_to_status, | ||
| make_metric, | ||
| now_seattle, | ||
| now_utc, | ||
| to_builtin, | ||
| ) | ||
|
|
||
| __all__ = [ | ||
| "DEFAULT_GROUPING", | ||
| "STATUS_CONVERTER", | ||
| "BaseQC", | ||
| "QCResult", | ||
| "bool_to_status", | ||
| "build_quality_control", | ||
| "make_metric", | ||
| "now_seattle", | ||
| "now_utc", | ||
| "to_builtin", | ||
| "to_metrics", | ||
| ] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| """Shared interface for the dynamic foraging QC stages. | ||
|
|
||
| ``BaseQC`` is an optional base class so the QC stages (raw, processed) share a | ||
| single ``run`` interface. Each concrete stage computes its checks and returns | ||
| them as schema ``QCMetric`` objects, which a caller assembles into one | ||
| ``QualityControl`` (see :func:`build_quality_control`). | ||
| """ | ||
|
|
||
| import abc | ||
| import typing as t | ||
|
|
||
| from aind_data_schema.core.quality_control import QCMetric | ||
|
|
||
|
|
||
| class BaseQC(abc.ABC): | ||
| """Common interface for a QC stage. | ||
|
|
||
| A QC stage takes some slice of a session's data and produces a flat list of | ||
| ``QCMetric`` objects. Subclasses define what slice ``run`` consumes (raw | ||
| acquisition data, processed tables, ...); the return type is shared so the | ||
| metrics can be collected uniformly. | ||
| """ | ||
|
|
||
| @abc.abstractmethod | ||
| def run(self, *args: t.Any, **kwargs: t.Any) -> t.List[QCMetric]: | ||
| """Run this stage's checks and return them as metrics. | ||
|
|
||
| Returns | ||
| ------- | ||
| list of QCMetric | ||
| One metric per check, ready to assemble into a ``QualityControl``. | ||
| """ | ||
| raise NotImplementedError | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,50 @@ | ||
| """Assemble the dynamic foraging ``QualityControl`` object. | ||
|
|
||
| Collects a flat list of metrics (behavior + contract QA) into a single | ||
| ``QualityControl``, wiring up ``default_grouping`` so the QC portal lays out | ||
| ``behavior`` and ``test_suite`` as sibling top-level groups. | ||
| """ | ||
|
|
||
| import typing as t | ||
|
|
||
| from aind_data_schema.core.quality_control import QCMetric, QualityControl | ||
|
|
||
| #: Tag keys laid out as siblings at the top level of the QC portal. | ||
| DEFAULT_GROUPING = ["behavior", "test_suite"] | ||
|
|
||
|
|
||
| def build_quality_control( | ||
| metrics: t.List[QCMetric], | ||
| *, | ||
| default_grouping: t.Optional[t.List[str]] = None, | ||
| allow_tag_failures: t.Optional[t.List[str]] = None, | ||
| key_experimenters: t.Optional[t.List[str]] = None, | ||
| notes: t.Optional[str] = None, | ||
| ) -> QualityControl: | ||
| """Wrap a flat list of metrics into a ``QualityControl`` object. | ||
|
|
||
| Parameters | ||
| ---------- | ||
| metrics : list of QCMetric | ||
| All metrics (behavior + contract QA). | ||
| default_grouping : list of str, optional | ||
| Tag keys the portal groups by. Defaults to ``["behavior", "test_suite"]``. | ||
| allow_tag_failures : list of str, optional | ||
| Tag values whose metric failures should not fail the overall QC. | ||
| key_experimenters : list of str, optional | ||
| Experimenters associated with the session. | ||
| notes : str, optional | ||
| Free-text notes. | ||
|
|
||
| Returns | ||
| ------- | ||
| QualityControl | ||
| The assembled quality-control object. | ||
| """ | ||
| return QualityControl( | ||
| metrics=metrics, | ||
| default_grouping=default_grouping if default_grouping is not None else DEFAULT_GROUPING, | ||
| allow_tag_failures=allow_tag_failures if allow_tag_failures is not None else [], | ||
| key_experimenters=key_experimenters, | ||
| notes=notes, | ||
| ) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,75 @@ | ||
| """The per-check ``QCResult`` and its conversion to a schema ``QCMetric``. | ||
|
|
||
| A ``QCResult`` is the raw outcome of one behavior QC check (a name, value, and | ||
| pass/fail). It converts into an ``aind_data_schema`` ``QCMetric`` via | ||
| ``to_metric``; the assembly step collects those metrics into a | ||
| ``QualityControl``. | ||
| """ | ||
|
|
||
| import dataclasses | ||
| import typing as t | ||
|
|
||
| from aind_data_schema.core.quality_control import QCMetric | ||
|
|
||
| from dynamic_foraging_processing.qc._core.schema import bool_to_status, make_metric | ||
|
|
||
|
|
||
| @dataclasses.dataclass(frozen=True) | ||
| class QCResult: | ||
| """The raw outcome of a single QC check. | ||
|
|
||
| Attributes | ||
| ---------- | ||
| name : str | ||
| Metric name. | ||
| value : Any | ||
| The computed value. | ||
| passed : bool | ||
| Whether the check passed. | ||
| description : str, optional | ||
| Human-readable description. | ||
| reference : str, optional | ||
| Relative path to a supporting asset (e.g. a plot). | ||
| tags : dict of str to str | ||
| Grouping tags (e.g. ``{"behavior": name}``). | ||
| """ | ||
|
|
||
| name: str | ||
| value: t.Any | ||
| passed: bool | ||
| description: t.Optional[str] = None | ||
| reference: t.Optional[str] = None | ||
| tags: t.Dict[str, str] = dataclasses.field(default_factory=dict) | ||
|
|
||
| def to_metric(self) -> QCMetric: | ||
| """Convert this result into a schema ``QCMetric``. | ||
|
|
||
| Returns | ||
| ------- | ||
| QCMetric | ||
| A metric carrying this result's value, pass/fail status, and tags. | ||
| """ | ||
| return make_metric( | ||
| name=self.name, | ||
| value=self.value, | ||
| status=bool_to_status(self.passed), | ||
| description=self.description, | ||
| reference=self.reference, | ||
| tags=self.tags, | ||
| ) | ||
|
|
||
|
|
||
| def to_metrics(results: t.Sequence[QCResult]) -> t.List[QCMetric]: | ||
| """Convert a sequence of ``QCResult`` into schema ``QCMetric`` objects. | ||
|
|
||
| Parameters | ||
| ---------- | ||
| results : sequence of QCResult | ||
| The per-check results to convert. | ||
|
|
||
| Returns | ||
| ------- | ||
| list of QCMetric | ||
| One metric per result. | ||
| """ | ||
| return [result.to_metric() for result in results] |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't seem DF specific. Should this be defined elsewhere, like in aind_data_schema?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah good point. I think looking at it again, some of the classes from the diagram are generic and could live elsewhere and them imported here.
should we make an issue and think about it later on?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@arjunsridhar12345 - yes, make an issue. I don't think
aind-data-schemais the right home, maybe models or elsewhereThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
created here - #21