From 50b951bd78d08cd181bcea81c3522b8b29999339 Mon Sep 17 00:00:00 2001 From: Dan Birman Date: Tue, 6 Oct 2026 11:36:35 -0700 Subject: [PATCH 1/5] docs: revise and improve QC pages, add new tag widget --- .github/workflows/update_dev_docs.yml | 10 + .gitignore | 1 + .readthedocs.yaml | 2 + CONTRIBUTING.md | 7 + docs/base/core/quality_control.md | 41 +- docs/source/biodata_models/organizations.md | 124 ++--- docs/source/biodata_models/species.md | 34 +- docs/source/components/devices.md | 2 +- docs/source/quality_control.md | 41 +- qc-tree-app/.gitignore | 2 + qc-tree-app/index.html | 17 + qc-tree-app/src/QCWidget.tsx | 407 ++++++++++++++ qc-tree-app/src/main.tsx | 31 ++ qc-tree-app/src/qcWidget.css | 560 ++++++++++++++++++++ qc-tree-app/src/vocabularies.ts | 28 + qc-tree-app/src/widgetTree.ts | 95 ++++ qc-tree-app/src/widgetTypes.ts | 35 ++ qc-tree-app/vite.config.ts | 26 + 18 files changed, 1367 insertions(+), 96 deletions(-) create mode 100644 qc-tree-app/.gitignore create mode 100644 qc-tree-app/index.html create mode 100644 qc-tree-app/src/QCWidget.tsx create mode 100644 qc-tree-app/src/main.tsx create mode 100644 qc-tree-app/src/qcWidget.css create mode 100644 qc-tree-app/src/vocabularies.ts create mode 100644 qc-tree-app/src/widgetTree.ts create mode 100644 qc-tree-app/src/widgetTypes.ts create mode 100644 qc-tree-app/vite.config.ts diff --git a/.github/workflows/update_dev_docs.yml b/.github/workflows/update_dev_docs.yml index 65571aa8..92d79009 100644 --- a/.github/workflows/update_dev_docs.yml +++ b/.github/workflows/update_dev_docs.yml @@ -21,6 +21,16 @@ jobs: python-version: '3.10' - name: Install dependencies run: uv sync --locked --group dev --group docs + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: "20" + - name: Build documentation widgets + run: | + npm --prefix diagram-app ci + npm --prefix diagram-app run build + npm --prefix qc-tree-app ci + npm --prefix qc-tree-app run build - name: Generate docs run: | uv run python src/biodata_schema/utils/docs/model_generator.py diff --git a/.gitignore b/.gitignore index ba73fec7..849fe07d 100644 --- a/.gitignore +++ b/.gitignore @@ -151,6 +151,7 @@ examples/*.json # diagram-app (React Flow schema diagram embedded in the docs front page) diagram-app/node_modules/ docs/source/_static/schema-diagram/ +docs/source/_static/qc-tree-app/ docs/base/models/* .github/copilot-instructions.md schema_tree.md diff --git a/.readthedocs.yaml b/.readthedocs.yaml index ec58f06b..d49f4e9c 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -10,6 +10,8 @@ build: pre_build: - npm --prefix diagram-app ci - npm --prefix diagram-app run build + - npm --prefix qc-tree-app ci + - npm --prefix qc-tree-app run build python: install: diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index fff4608b..651c1d86 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -51,6 +51,13 @@ npm --prefix diagram-app ci npm --prefix diagram-app run build ``` +The quality-control page embeds the interactive hierarchy builder (`qc-tree-app/`). Build its JS/CSS bundle before building the docs as well: + +```bash +npm --prefix qc-tree-app ci +npm --prefix qc-tree-app run build +``` + Then to create the documentation html files, run: ```bash diff --git a/docs/base/core/quality_control.md b/docs/base/core/quality_control.md index a9e99065..5d30443f 100644 --- a/docs/base/core/quality_control.md +++ b/docs/base/core/quality_control.md @@ -10,21 +10,24 @@ Every [QCMetric](#qcmetric) has a `Status` which takes the value of the metric a ## Details -### Metrics +The metrics defined during quality control should define whether or not an asset can be used for analysis and the properties of an asset that could influence how an analysis is performed. There are two levels of QC: -Each [QCMetric](#qcmetric) is a single value or array of values that can be computed, or observed, about one modality in a data asset. These can have any type. Metrics should be significant: i.e. whether they pass or fail should matter for the modality. Metrics need to be human understandable. If you find yourself generating more than fifty metrics for a modality you should group them together (i.e. make the value a dictionary combining similar metrics and the rule an evaluation of multiple fields in the dictionary). +- Quality control metrics that are **not allowed to fail** are metrics that at `stage:raw` would prevent an asset from being processed or that at `stage:processing` would prevent an asset from being analyzed. This is a very high bar. Another way of saying this is that if the goals of the data acquisition were met, then all metrics that are 'not allowed to fail' should be passing. +- Quality control metrics that are **allowed to fail** are metrics that will influence the analysis of data, for example by indicating that one element of an asset cannot be used. These assets do not invalidate further analysis but they change how analysis should be performed. -Each [QCMetric](#qcmetric) has a [Status](#status). The [Status](#status) should depend directly on the `QCMetric.value`, either by a simple function: "value>5", or by a qualitative rule: "Field of view includes visual areas". The `QCMetric.description` field should describe the rule used to set the status. Metrics can be evaluated multiple times, in which case the new status should be appended the `QCMetric.status_history`. +The second kind of metrics are identified by the `QualityControl.allow_tag_failures` field, details below. -Each [QCMetric](#qcmetric) is annotated with three pieces of additional metadata: the [Stage](#stage) during which it was evaluated, the [Modality](biodata_models/modalities.md#modality) of the evaluated data, and [tags](#tags). +### Metrics -### Curations +Each [QCMetric](#qcmetric) is a single value or array of values that can be computed, or observed, about one modality in a data asset. These can have any type. Metrics should be significant: i.e. whether they pass or fail should matter for the modality. Metrics need to be human understandable. If you find yourself generating more metrics than a human can reasonably parse for a modality you should group them together (i.e. make the value a dictionary combining similar metrics). -If you find yourself computing a value for something smaller than an entire modality of data in an asset you are performing *curation*, i.e. you are determining the status of a subset of a modality in the data asset. We provide the [CurationMetric](#curationmetric) for this purpose. You should put a dictionary in the `CurationMetric.value` field that contains a mapping between the subsets (usually neurons, ROIs, channels, etc) and their values. +Each [QCMetric](#qcmetric) has a [Status](#status). The [Status](#status) should depend directly on the `QCMetric.value`, either by a simple function: "value>5", or by a qualitative rule: "Field of view includes visual areas". The `QCMetric.description` field should describe the rule used to set the status. The status of a metric should be appended the `QCMetric.status_history`. + +Each [QCMetric](#qcmetric) is annotated with three pieces of additional metadata: the [Stage](#stage) during which it was evaluated, the [Modality](biodata_models/modalities.md#modality) of the evaluated data, and [tags](#tags). ### Tags -`tags` are groups of descriptors that define how metrics are organized hierarchically, making it easier to visualize metrics. Good tag keys (groups) are things like "probe" and good tag values are things like "Probe A" or just "A". +`tags` are groups of descriptors that define how metrics are grouped hierarchically, making it easier to visualize metrics. Good tag keys (groups) are things like "probe" and good tag values (group members) are things like "Probe A" or just "A". ```python # For an electrophysiology metric @@ -39,7 +42,19 @@ tags = { } ``` -Use the `QualityControl.default_grouping` list to define how users should organize a visualization by default. In almost all cases *modality should be the top-level grouping*. For example, building on the example above you might group by: `["modality", ("probe", "video"), "shank"]` to get a tree split by modality first (which naturally splits ephys and behavior-videos tags into two groups), then by which probe or video a metric belongs to, and finally only for probes the individual shanks are split into groups. +When multiple QC stages are selected, they split at the top of the hierarchy. Multiple modalities split at the next level, or at the top when only one stage is selected. These fixed levels are followed by the tag levels in `QualityControl.default_grouping`. For example, `["stage", "modality", ("probe", "video"), "shank"]` groups first by stage, then by modality, then by probe or video at the same level, and finally by shank. + +Use the builder to define tag keys and values, drag tag keys into level buckets, and preview the resulting hierarchy: + +```{raw} html + +
+ +``` + +### Curations + +If you find yourself computing a value for something that is smaller than an entire modality of data and is repeated (e.g. neurons) in an asset you are performing *curation*, i.e. you are determining the status of a subset of a modality in the data asset. We provide the [CurationMetric](#curationmetric) for this purpose. You should put a dictionary in the `CurationMetric.value` field that contains a mapping between the subsets (usually neurons, ROIs, channels, etc) and their values. ### QualityControl.evaluate_status() @@ -53,6 +68,16 @@ Then, given the status of all the remaining metrics in the group: 2. If any metric is pending and the rest pass the evaluation is pending 3. If all metrics pass the evaluation passes +### QualityControl.status + +The `QualityControl.status` field is a dictionary that maps individual tag `key:value` pairs to their status. For example a typical status dictionary might look like this: + +``` +{ + "modality:behavior": "PASS", +} +``` + **Q: What is a metric reference?** Each [QCMetric](#qcmetric) should include a `QCMetric.reference`. References should be publicly accessible images, figures, multi-panel figures, and videos that support the metric value/status or provide the information necessary for manual annotation. diff --git a/docs/source/biodata_models/organizations.md b/docs/source/biodata_models/organizations.md index da8c6c2e..6f1e1d1f 100644 --- a/docs/source/biodata_models/organizations.md +++ b/docs/source/biodata_models/organizations.md @@ -9,130 +9,130 @@ Organization | Name | name | abbreviation | registry | registry_identifier | |------|------|------|------|------| | `AA_OPTO_ELECTRONIC` | `AA Opto Electronic` | `None` | `None` | `None` | -| `ABCAM` | `Abcam` | `None` | `Research Organization Registry (ROR)` | `02e1wjw63` | -| `ADDGENE` | `Addgene` | `None` | `Research Organization Registry (ROR)` | `01nn1pw54` | -| `AI` | `Allen Institute` | `AI` | `Research Organization Registry (ROR)` | `03cpe7c52` | -| `AIBS` | `Allen Institute for Brain Science` | `AIBS` | `Research Organization Registry (ROR)` | `00dcv1019` | +| `ABCAM` | `Abcam` | `None` | `Registry.ROR` | `02e1wjw63` | +| `ADDGENE` | `Addgene` | `None` | `Registry.ROR` | `01nn1pw54` | +| `AI` | `Allen Institute` | `AI` | `Registry.ROR` | `03cpe7c52` | +| `AIBS` | `Allen Institute for Brain Science` | `AIBS` | `Registry.ROR` | `00dcv1019` | | `AILIPU` | `Ailipu Technology Co` | `Ailipu` | `None` | `None` | -| `AIND` | `Allen Institute for Neural Dynamics` | `AIND` | `Research Organization Registry (ROR)` | `04szwah67` | -| `AMS_OSRAM` | `ams OSRAM` | `None` | `Research Organization Registry (ROR)` | `045d0h266` | +| `AIND` | `Allen Institute for Neural Dynamics` | `AIND` | `Registry.ROR` | `04szwah67` | +| `AMS_OSRAM` | `ams OSRAM` | `None` | `Registry.ROR` | `045d0h266` | | `ANTIBODIES_INC` | `Antibodies Inc` | `None` | `None` | `None` | | `ARDUINO` | `Arduino` | `None` | `None` | `None` | | `ARECONT_VISION_COSTAR` | `Arecont Vision Costar` | `None` | `None` | `None` | | `ASI` | `Applied Scientific Instrumentation` | `ASI` | `None` | `None` | -| `ASUS` | `ASUS` | `None` | `Research Organization Registry (ROR)` | `00bxkz165` | +| `ASUS` | `ASUS` | `None` | `Registry.ROR` | `00bxkz165` | | `BASLER` | `Basler` | `None` | `None` | `None` | -| `BCM` | `Baylor College of Medicine` | `BCM` | `Research Organization Registry (ROR)` | `02pttbw34` | -| `BROADCOM` | `Broadcom` | `None` | `Research Organization Registry (ROR)` | `035gt5s03` | -| `BRUKER` | `Bruker` | `None` | `Research Organization Registry (ROR)` | `04r739x86` | -| `BU` | `Boston University` | `BU` | `Research Organization Registry (ROR)` | `05qwgg493` | -| `CAJAL` | `Cajal Neuroscience` | `Cajal` | `Research Organization Registry (ROR)` | `05pdc0q70` | +| `BCM` | `Baylor College of Medicine` | `BCM` | `Registry.ROR` | `02pttbw34` | +| `BROADCOM` | `Broadcom` | `None` | `Registry.ROR` | `035gt5s03` | +| `BRUKER` | `Bruker` | `None` | `Registry.ROR` | `04r739x86` | +| `BU` | `Boston University` | `BU` | `Registry.ROR` | `05qwgg493` | +| `CAJAL` | `Cajal Neuroscience` | `Cajal` | `Registry.ROR` | `05pdc0q70` | | `CAMBRIDGE_TECHNOLOGY` | `Cambridge Technology` | `None` | `None` | `None` | -| `CARL_ZEISS` | `Carl Zeiss` | `None` | `Research Organization Registry (ROR)` | `01xk5xs43` | -| `CHAMPALIMAUD` | `Champalimaud Foundation` | `Champalimaud` | `Research Organization Registry (ROR)` | `03g001n57` | +| `CARL_ZEISS` | `Carl Zeiss` | `None` | `Registry.ROR` | `01xk5xs43` | +| `CHAMPALIMAUD` | `Champalimaud Foundation` | `Champalimaud` | `Registry.ROR` | `03g001n57` | | `CHROMA` | `Chroma` | `None` | `None` | `None` | -| `COHERENT_SCIENTIFIC` | `Coherent Scientific` | `None` | `Research Organization Registry (ROR)` | `031tysd23` | -| `COLUMBIA` | `Columbia University` | `Columbia` | `Research Organization Registry (ROR)` | `00hj8s172` | +| `COHERENT_SCIENTIFIC` | `Coherent Scientific` | `None` | `Registry.ROR` | `031tysd23` | +| `COLUMBIA` | `Columbia University` | `Columbia` | `Registry.ROR` | `00hj8s172` | | `COMPUTAR` | `Computar` | `None` | `None` | `None` | | `CONOPTICS` | `Conoptics` | `None` | `None` | `None` | | `CRESTOPTICS` | `CrestOptics` | `None` | `None` | `None` | -| `CRL` | `Charles River Laboratories` | `CRL` | `Research Organization Registry (ROR)` | `03ndmsg87` | +| `CRL` | `Charles River Laboratories` | `CRL` | `Registry.ROR` | `03ndmsg87` | | `CUSTOM` | `Custom` | `None` | `None` | `None` | -| `CZI` | `Chan Zuckerberg Initiative` | `CZI` | `Research Organization Registry (ROR)` | `02qenvm24` | +| `CZI` | `Chan Zuckerberg Initiative` | `CZI` | `Registry.ROR` | `02qenvm24` | | `DIGIKEY` | `DigiKey` | `None` | `None` | `None` | | `DODOTRONIC` | `Dodotronic` | `None` | `None` | `None` | -| `DORIC` | `Doric` | `None` | `Research Organization Registry (ROR)` | `059n53q30` | +| `DORIC` | `Doric` | `None` | `Registry.ROR` | `059n53q30` | | `EALING` | `Ealing` | `None` | `None` | `None` | -| `EDMUND_OPTICS` | `Edmund Optics` | `None` | `Research Organization Registry (ROR)` | `01j1gwp17` | -| `EMORY` | `Emory University` | `Emory` | `Research Organization Registry (ROR)` | `03czfpz43` | +| `EDMUND_OPTICS` | `Edmund Optics` | `None` | `Registry.ROR` | `01j1gwp17` | +| `EMORY` | `Emory University` | `Emory` | `Registry.ROR` | `03czfpz43` | | `EURESYS` | `Euresys` | `None` | `None` | `None` | -| `EXCELITAS_TECHNOLOGIES` | `Excelitas Technologies` | `None` | `Research Organization Registry (ROR)` | `01tpbbf75` | -| `FLIR` | `Teledyne FLIR` | `FLIR` | `Research Organization Registry (ROR)` | `01j1gwp17` | +| `EXCELITAS_TECHNOLOGIES` | `Excelitas Technologies` | `None` | `Registry.ROR` | `01tpbbf75` | +| `FLIR` | `Teledyne FLIR` | `FLIR` | `Registry.ROR` | `01j1gwp17` | | `FUJINON` | `Fujinon` | `None` | `None` | `None` | -| `HAMAMATSU` | `Hamamatsu` | `None` | `Research Organization Registry (ROR)` | `03natb733` | +| `HAMAMATSU` | `Hamamatsu` | `None` | `Registry.ROR` | `03natb733` | | `HAMILTON` | `Hamilton` | `None` | `None` | `None` | -| `HUST` | `Huazhong University of Science and Technology` | `HUST` | `Research Organization Registry (ROR)` | `00p991c53` | -| `IDT` | `Integrated DNA Technologies` | `IDT` | `Research Organization Registry (ROR)` | `009jvpf03` | -| `IMEC` | `Interuniversity Microelectronics Center` | `IMEC` | `Research Organization Registry (ROR)` | `02kcbn207` | +| `HUST` | `Huazhong University of Science and Technology` | `HUST` | `Registry.ROR` | `00p991c53` | +| `IDT` | `Integrated DNA Technologies` | `IDT` | `Registry.ROR` | `009jvpf03` | +| `IMEC` | `Interuniversity Microelectronics Center` | `IMEC` | `Registry.ROR` | `02kcbn207` | | `INFINITY_PHOTO_OPTICAL` | `Infinity Photo-Optical` | `None` | `None` | `None` | -| `INVITROGEN` | `Invitrogen` | `None` | `Research Organization Registry (ROR)` | `03x1ewr52` | +| `INVITROGEN` | `Invitrogen` | `None` | `Registry.ROR` | `03x1ewr52` | | `IR_ROBOT_CO` | `IR Robot Co` | `None` | `None` | `None` | | `ISL` | `ISL Products International` | `ISL` | `None` | `None` | | `ITEM` | `Item` | `None` | `None` | `None` | -| `JANELIA` | `Janelia Research Campus` | `Janelia` | `Research Organization Registry (ROR)` | `013sk6x84` | -| `JAX` | `Jackson Laboratory` | `JAX` | `Research Organization Registry (ROR)` | `021sy4w91` | -| `JENOPTIK` | `Jenoptik` | `None` | `Research Organization Registry (ROR)` | `05g7t5c49` | -| `JHU` | `Johns Hopkins University` | `JHU` | `Research Organization Registry (ROR)` | `00za53h95` | +| `JANELIA` | `Janelia Research Campus` | `Janelia` | `Registry.ROR` | `013sk6x84` | +| `JAX` | `Jackson Laboratory` | `JAX` | `Registry.ROR` | `021sy4w91` | +| `JENOPTIK` | `Jenoptik` | `None` | `Registry.ROR` | `05g7t5c49` | +| `JHU` | `Johns Hopkins University` | `JHU` | `Registry.ROR` | `00za53h95` | | `JULABO` | `Julabo` | `None` | `None` | `None` | -| `KENT_SCIENTIFIC_CORPORATION` | `Kent Scientific Corporation` | `None` | `Research Organization Registry (ROR)` | `03xkj6a08` | -| `KOWA` | `Kowa` | `None` | `Research Organization Registry (ROR)` | `03zbwg482` | +| `KENT_SCIENTIFIC_CORPORATION` | `Kent Scientific Corporation` | `None` | `Registry.ROR` | `03xkj6a08` | +| `KOWA` | `Kowa` | `None` | `Registry.ROR` | `03zbwg482` | | `LASOS` | `LASOS Lasertechnik` | `LASOS` | `None` | `None` | | `LEICA` | `Leica` | `None` | `None` | `None` | -| `LG` | `LG` | `None` | `Research Organization Registry (ROR)` | `02b948n83` | +| `LG` | `LG` | `None` | `Registry.ROR` | `02b948n83` | | `LIFECANVAS` | `LifeCanvas` | `None` | `None` | `None` | | `LUMENCOR` | `Lumencor` | `None` | `None` | `None` | | `LUMEN_DYNAMICS` | `Lumen Dynamics` | `None` | `None` | `None` | -| `MBF` | `MBF Bioscience` | `MBF` | `Research Organization Registry (ROR)` | `02zynam48` | -| `MEADOWLARK_OPTICS` | `Meadowlark Optics` | `None` | `Research Organization Registry (ROR)` | `00n8qbq54` | -| `MIBR` | `McGovern Institute for Brain Research` | `MIBR` | `Research Organization Registry (ROR)` | `05ymca674` | +| `MBF` | `MBF Bioscience` | `MBF` | `Registry.ROR` | `02zynam48` | +| `MEADOWLARK_OPTICS` | `Meadowlark Optics` | `None` | `Registry.ROR` | `00n8qbq54` | +| `MIBR` | `McGovern Institute for Brain Research` | `MIBR` | `Registry.ROR` | `05ymca674` | | `MIDOPT` | `Midwest Optical Systems, Inc.` | `MidOpt` | `None` | `None` | -| `MIT` | `Massachusetts Institute of Technology` | `MIT` | `Research Organization Registry (ROR)` | `042nb2s44` | +| `MIT` | `Massachusetts Institute of Technology` | `MIT` | `Registry.ROR` | `042nb2s44` | | `MITUTUYO` | `Mitutuyo` | `None` | `None` | `None` | | `MIT_BCS` | `MIT Department of Brain and Cognitive Sciences` | `MIT-BCS` | `None` | `None` | -| `MJFF` | `Michael J. Fox Foundation for Parkinson's Research` | `MJFF` | `Research Organization Registry (ROR)` | `03arq3225` | -| `MKS_NEWPORT` | `MKS Newport` | `None` | `Research Organization Registry (ROR)` | `00k17f049` | +| `MJFF` | `Michael J. Fox Foundation for Parkinson's Research` | `MJFF` | `Registry.ROR` | `03arq3225` | +| `MKS_NEWPORT` | `MKS Newport` | `None` | `Registry.ROR` | `00k17f049` | | `MOLECULAR_INSTRUMENTS` | `Molecular Instruments` | `None` | `None` | `None` | | `MPI` | `MPI` | `MPI` | `None` | `None` | -| `NATIONAL_INSTRUMENTS` | `National Instruments` | `None` | `Research Organization Registry (ROR)` | `026exqw73` | +| `NATIONAL_INSTRUMENTS` | `National Instruments` | `None` | `Registry.ROR` | `026exqw73` | | `NAVITAR` | `Navitar` | `None` | `None` | `None` | -| `NCCIH` | `National Center for Complementary and Integrative Health` | `NCCIH` | `Research Organization Registry (ROR)` | `00190t495` | +| `NCCIH` | `National Center for Complementary and Integrative Health` | `NCCIH` | `Registry.ROR` | `00190t495` | | `NEURALYNX` | `NeuraLynx` | `None` | `None` | `None` | | `NEUROPHOTOMETRICS` | `Neurophotometrics` | `None` | `None` | `None` | | `NEW_SCALE_TECHNOLOGIES` | `New Scale Technologies` | `None` | `None` | `None` | -| `NIKON` | `Nikon` | `None` | `Research Organization Registry (ROR)` | `0280y9h11` | -| `NIMH` | `National Institute of Mental Health` | `NIMH` | `Research Organization Registry (ROR)` | `04xeg9z08` | -| `NINDS` | `National Institute of Neurological Disorders and Stroke` | `NINDS` | `Research Organization Registry (ROR)` | `01s5ya894` | +| `NIKON` | `Nikon` | `None` | `Registry.ROR` | `0280y9h11` | +| `NIMH` | `National Institute of Mental Health` | `NIMH` | `Registry.ROR` | `04xeg9z08` | +| `NINDS` | `National Institute of Neurological Disorders and Stroke` | `NINDS` | `Registry.ROR` | `01s5ya894` | | `NRESEARCH_INC` | `NResearch Inc` | `None` | `None` | `None` | -| `NYU` | `New York University` | `NYU` | `Research Organization Registry (ROR)` | `0190ak572` | -| `OEPS` | `Open Ephys Production Site` | `OEPS` | `Research Organization Registry (ROR)` | `007rkz355` | -| `OLYMPUS` | `Olympus` | `None` | `Research Organization Registry (ROR)` | `02vcdte90` | +| `NYU` | `New York University` | `NYU` | `Registry.ROR` | `0190ak572` | +| `OEPS` | `Open Ephys Production Site` | `OEPS` | `Registry.ROR` | `007rkz355` | +| `OLYMPUS` | `Olympus` | `None` | `Registry.ROR` | `02vcdte90` | | `OPTOTUNE` | `Optotune` | `None` | `None` | `None` | | `OTHER` | `Other` | `None` | `None` | `None` | -| `OXFORD_INSTRUMENTS` | `Oxford Instruments` | `None` | `Research Organization Registry (ROR)` | `01age2z78` | +| `OXFORD_INSTRUMENTS` | `Oxford Instruments` | `None` | `Registry.ROR` | `01age2z78` | | `OXXIUS` | `Oxxius` | `None` | `None` | `None` | | `PLACID_INDUSTRIES` | `Placid Industries` | `None` | `None` | `None` | | `PRIZMATIX` | `Prizmatix` | `None` | `None` | `None` | | `QUANTIFI` | `Quantifi` | `None` | `None` | `None` | | `RASPBERRY_PI` | `Raspberry Pi` | `None` | `None` | `None` | -| `ROCKLAND` | `Rockland Immunochemicals` | `ROCKLAND` | `Research Organization Registry (ROR)` | `02z2r2t61` | +| `ROCKLAND` | `Rockland Immunochemicals` | `ROCKLAND` | `Registry.ROR` | `02z2r2t61` | | `SAME_SKY` | `Same Sky` | `None` | `None` | `None` | | `SCHNEIDER_KREUZNACH` | `Schneider-Kreuznach` | `None` | `None` | `None` | -| `SCIENTIFICA` | `Scientifica` | `None` | `Research Organization Registry (ROR)` | `00z72df47` | +| `SCIENTIFICA` | `Scientifica` | `None` | `Registry.ROR` | `00z72df47` | | `SECOND_ORDER_EFFECTS` | `Second Order Effects` | `None` | `None` | `None` | | `SEMROCK` | `Semrock` | `None` | `None` | `None` | | `SICGEN` | `SICGEN` | `None` | `None` | `None` | | `SIGMA_ALDRICH` | `Sigma-Aldrich` | `None` | `None` | `None` | -| `SIMONS_FOUNDATION` | `Simons Foundation` | `None` | `Research Organization Registry (ROR)` | `01cmst727` | -| `SPECTRA_PHYSICS` | `Spectra-Physics` | `None` | `Research Organization Registry (ROR)` | `02ad9kp97` | +| `SIMONS_FOUNDATION` | `Simons Foundation` | `None` | `Registry.ROR` | `01cmst727` | +| `SPECTRA_PHYSICS` | `Spectra-Physics` | `None` | `Registry.ROR` | `02ad9kp97` | | `SPINNAKER` | `Spinnaker` | `None` | `None` | `None` | -| `STANFORD_UNIVERSITY` | `Stanford University` | `None` | `Research Organization Registry (ROR)` | `00f54p054` | +| `STANFORD_UNIVERSITY` | `Stanford University` | `None` | `Registry.ROR` | `00f54p054` | | `SYNAPTIC_SYSTEMS` | `Synaptic Systems` | `None` | `None` | `None` | | `TAMRON` | `Tamron` | `None` | `None` | `None` | | `TELEDYNE_VISION_SOLUTIONS` | `Teledyne Vision Solutions` | `None` | `None` | `None` | -| `TE_CONNECTIVITY` | `TE Connectivity` | `None` | `Research Organization Registry (ROR)` | `034frgp20` | -| `THERMO_FISHER_SCIENTIFIC` | `Thermo Fisher Scientific` | `None` | `Research Organization Registry (ROR)` | `03x1ewr52` | +| `TE_CONNECTIVITY` | `TE Connectivity` | `None` | `Registry.ROR` | `034frgp20` | +| `THERMO_FISHER_SCIENTIFIC` | `Thermo Fisher Scientific` | `None` | `Registry.ROR` | `03x1ewr52` | | `THE_IMAGING_SOURCE` | `The Imaging Source` | `None` | `None` | `None` | | `THE_LEE_COMPANY` | `The Lee Company` | `None` | `None` | `None` | -| `THORLABS` | `Thorlabs` | `None` | `Research Organization Registry (ROR)` | `04gsnvb07` | +| `THORLABS` | `Thorlabs` | `None` | `Registry.ROR` | `04gsnvb07` | | `TMC` | `Technical Manufacturing Corporation` | `TMC` | `None` | `None` | | `TRANSDUCER_TECHNIQUES` | `Transducer Techniques` | `None` | `None` | `None` | -| `TWCF` | `Templeton World Charity Foundation` | `TWCF` | `Research Organization Registry (ROR)` | `00x0z1472` | +| `TWCF` | `Templeton World Charity Foundation` | `TWCF` | `Registry.ROR` | `00x0z1472` | | `TYMPHANY` | `Tymphany` | `None` | `None` | `None` | -| `UCSD` | `University of California, San Diego` | `UCSD` | `Research Organization Registry (ROR)` | `0168r3w48` | +| `UCSD` | `University of California, San Diego` | `UCSD` | `Registry.ROR` | `0168r3w48` | | `UNKNOWN` | `Unknown` | `UNKNOWN` | `None` | `None` | -| `UPENN` | `University of Pennsylvania` | `UPENN` | `Research Organization Registry (ROR)` | `00b30xv10` | +| `UPENN` | `University of Pennsylvania` | `UPENN` | `Registry.ROR` | `00b30xv10` | | `VIEWORKS` | `Vieworks` | `None` | `None` | `None` | | `VORTRAN` | `Vortran` | `None` | `None` | `None` | -| `WPI` | `World Precision Intstruments` | `WPI` | `Research Organization Registry (ROR)` | `03st5df34` | +| `WPI` | `World Precision Intstruments` | `WPI` | `Registry.ROR` | `03st5df34` | diff --git a/docs/source/biodata_models/species.md b/docs/source/biodata_models/species.md index 0ee0feb3..4644d958 100644 --- a/docs/source/biodata_models/species.md +++ b/docs/source/biodata_models/species.md @@ -8,21 +8,21 @@ Species | Name | name | common_name | registry | registry_identifier | |------|------|------|------|------| -| `ALPACA` | `Vicuna pacos` | `Alpaca` | `National Center for Biotechnology Information (NCBI)` | `NCBI:txid30538` | -| `CHICKEN` | `Gallus gallus` | `Chicken` | `National Center for Biotechnology Information (NCBI)` | `NCBI:txid9031` | -| `COMMON_MARMOSET` | `Callithrix jacchus` | `Common marmoset` | `National Center for Biotechnology Information (NCBI)` | `NCBI:txid9483` | -| `COMMON_SQUIRREL_MONKEY` | `Saimiri sciureus` | `Common squirrel monkey` | `National Center for Biotechnology Information (NCBI)` | `NCBI:txid9521` | -| `CRAB_EATING_MACAQUE` | `Macaca fascicularis` | `Crab-eating macaque` | `National Center for Biotechnology Information (NCBI)` | `NCBI:txid9541` | -| `DONKEY` | `Equus asinus` | `Donkey` | `National Center for Biotechnology Information (NCBI)` | `NCBI:txid9793` | -| `EUROPEAN_RABBIT` | `Oryctolagus cuniculus` | `European rabbit` | `National Center for Biotechnology Information (NCBI)` | `NCBI:txid9986` | -| `GOAT` | `Carpa hircus` | `Goat` | `National Center for Biotechnology Information (NCBI)` | `NCBI:txid9925` | -| `GUINEA_PIG` | `Cavia porcellus` | `Guinea pig` | `National Center for Biotechnology Information (NCBI)` | `NCBI:txid10141` | -| `HOUSE_MOUSE` | `Mus musculus` | `House mouse` | `National Center for Biotechnology Information (NCBI)` | `NCBI:txid10090` | -| `HUMAN` | `Homo sapiens` | `Human` | `National Center for Biotechnology Information (NCBI)` | `NCBI:txid9606` | -| `LLAMA` | `Lama glama` | `Llama` | `National Center for Biotechnology Information (NCBI)` | `NCBI:txid9844` | -| `NORWAY_RAT` | `Rattus norvegicus` | `Norway rat` | `National Center for Biotechnology Information (NCBI)` | `NCBI:txid10116` | -| `PIG_TAILED_MACAQUE` | `Macaca nemestrina` | `Pig-tailed macaque` | `National Center for Biotechnology Information (NCBI)` | `NCBI:txid9545` | -| `RHESUS_MACAQUE` | `Macaca mulatta` | `Rhesus macaque` | `National Center for Biotechnology Information (NCBI)` | `NCBI:txid9544` | +| `ALPACA` | `Vicuna pacos` | `Alpaca` | `Registry.NCBI` | `NCBI:txid30538` | +| `CHICKEN` | `Gallus gallus` | `Chicken` | `Registry.NCBI` | `NCBI:txid9031` | +| `COMMON_MARMOSET` | `Callithrix jacchus` | `Common marmoset` | `Registry.NCBI` | `NCBI:txid9483` | +| `COMMON_SQUIRREL_MONKEY` | `Saimiri sciureus` | `Common squirrel monkey` | `Registry.NCBI` | `NCBI:txid9521` | +| `CRAB_EATING_MACAQUE` | `Macaca fascicularis` | `Crab-eating macaque` | `Registry.NCBI` | `NCBI:txid9541` | +| `DONKEY` | `Equus asinus` | `Donkey` | `Registry.NCBI` | `NCBI:txid9793` | +| `EUROPEAN_RABBIT` | `Oryctolagus cuniculus` | `European rabbit` | `Registry.NCBI` | `NCBI:txid9986` | +| `GOAT` | `Carpa hircus` | `Goat` | `Registry.NCBI` | `NCBI:txid9925` | +| `GUINEA_PIG` | `Cavia porcellus` | `Guinea pig` | `Registry.NCBI` | `NCBI:txid10141` | +| `HOUSE_MOUSE` | `Mus musculus` | `House mouse` | `Registry.NCBI` | `NCBI:txid10090` | +| `HUMAN` | `Homo sapiens` | `Human` | `Registry.NCBI` | `NCBI:txid9606` | +| `LLAMA` | `Lama glama` | `Llama` | `Registry.NCBI` | `NCBI:txid9844` | +| `NORWAY_RAT` | `Rattus norvegicus` | `Norway rat` | `Registry.NCBI` | `NCBI:txid10116` | +| `PIG_TAILED_MACAQUE` | `Macaca nemestrina` | `Pig-tailed macaque` | `Registry.NCBI` | `NCBI:txid9545` | +| `RHESUS_MACAQUE` | `Macaca mulatta` | `Rhesus macaque` | `Registry.NCBI` | `NCBI:txid9544` | ### Strain @@ -31,8 +31,8 @@ Strain | Name | name | species | registry | registry_identifier | |------|------|------|------|------| -| `BALB_C` | `BALB/c` | `Mus musculus` | `Mouse Genome Informatics (MGI)` | `MGI:2159737` | -| `C57BL_6J` | `C57BL/6J` | `Mus musculus` | `Mouse Genome Informatics (MGI)` | `MGI:3028467` | +| `BALB_C` | `BALB/c` | `Mus musculus` | `Registry.MGI` | `MGI:2159737` | +| `C57BL_6J` | `C57BL/6J` | `Mus musculus` | `Registry.MGI` | `MGI:3028467` | | `UNKNOWN` | `Unknown` | `Mus musculus` | `None` | `None` | diff --git a/docs/source/components/devices.md b/docs/source/components/devices.md index d1cdf693..78012d3a 100644 --- a/docs/source/components/devices.md +++ b/docs/source/components/devices.md @@ -783,7 +783,7 @@ Multichannel electrophysiology DAQ | Field | Type | Title (Description) | |-------|------|-------------| | `ports` | List[[ProbePort](#probeport)] | Acquisition board ports | -| `data_interface` | `"USB"` | | +| `data_interface` | `"DataInterface.USB"` | | | `manufacturer` | [Organization](../biodata_models/organizations.md#organization) | | | `channels` | List[[DAQChannel](#daqchannel)] | DAQ channels | | `firmware_version` | `Optional[str]` | Firmware version | diff --git a/docs/source/quality_control.md b/docs/source/quality_control.md index 22b77551..c3b6057c 100644 --- a/docs/source/quality_control.md +++ b/docs/source/quality_control.md @@ -10,21 +10,24 @@ Every [QCMetric](#qcmetric) has a `Status` which takes the value of the metric a ## Details -### Metrics +The metrics defined during quality control should define whether or not an asset can be used for analysis and the properties of an asset that could influence how an analysis is performed. There are two levels of QC: -Each [QCMetric](#qcmetric) is a single value or array of values that can be computed, or observed, about one modality in a data asset. These can have any type. Metrics should be significant: i.e. whether they pass or fail should matter for the modality. Metrics need to be human understandable. If you find yourself generating more than fifty metrics for a modality you should group them together (i.e. make the value a dictionary combining similar metrics and the rule an evaluation of multiple fields in the dictionary). +- Quality control metrics that are **not allowed to fail** are metrics that at `stage:raw` would prevent an asset from being processed or that at `stage:processing` would prevent an asset from being analyzed. This is a very high bar. Another way of saying this is that if the goals of the data acquisition were met, then all metrics that are 'not allowed to fail' should be passing. +- Quality control metrics that are **allowed to fail** are metrics that will influence the analysis of data, for example by indicating that one element of an asset cannot be used. These assets do not invalidate further analysis but they change how analysis should be performed. -Each [QCMetric](#qcmetric) has a [Status](#status). The [Status](#status) should depend directly on the `QCMetric.value`, either by a simple function: "value>5", or by a qualitative rule: "Field of view includes visual areas". The `QCMetric.description` field should describe the rule used to set the status. Metrics can be evaluated multiple times, in which case the new status should be appended the `QCMetric.status_history`. +The second kind of metrics are identified by the `QualityControl.allow_tag_failures` field, details below. -Each [QCMetric](#qcmetric) is annotated with three pieces of additional metadata: the [Stage](#stage) during which it was evaluated, the [Modality](biodata_models/modalities.md#modality) of the evaluated data, and [tags](#tags). +### Metrics -### Curations +Each [QCMetric](#qcmetric) is a single value or array of values that can be computed, or observed, about one modality in a data asset. These can have any type. Metrics should be significant: i.e. whether they pass or fail should matter for the modality. Metrics need to be human understandable. If you find yourself generating more metrics than a human can reasonably parse for a modality you should group them together (i.e. make the value a dictionary combining similar metrics). -If you find yourself computing a value for something smaller than an entire modality of data in an asset you are performing *curation*, i.e. you are determining the status of a subset of a modality in the data asset. We provide the [CurationMetric](#curationmetric) for this purpose. You should put a dictionary in the `CurationMetric.value` field that contains a mapping between the subsets (usually neurons, ROIs, channels, etc) and their values. +Each [QCMetric](#qcmetric) has a [Status](#status). The [Status](#status) should depend directly on the `QCMetric.value`, either by a simple function: "value>5", or by a qualitative rule: "Field of view includes visual areas". The `QCMetric.description` field should describe the rule used to set the status. The status of a metric should be appended the `QCMetric.status_history`. + +Each [QCMetric](#qcmetric) is annotated with three pieces of additional metadata: the [Stage](#stage) during which it was evaluated, the [Modality](biodata_models/modalities.md#modality) of the evaluated data, and [tags](#tags). ### Tags -`tags` are groups of descriptors that define how metrics are organized hierarchically, making it easier to visualize metrics. Good tag keys (groups) are things like "probe" and good tag values are things like "Probe A" or just "A". +`tags` are groups of descriptors that define how metrics are grouped hierarchically, making it easier to visualize metrics. Good tag keys (groups) are things like "probe" and good tag values (group members) are things like "Probe A" or just "A". ```python # For an electrophysiology metric @@ -39,7 +42,19 @@ tags = { } ``` -Use the `QualityControl.default_grouping` list to define how users should organize a visualization by default. In almost all cases *modality should be the top-level grouping*. For example, building on the example above you might group by: `["modality", ("probe", "video"), "shank"]` to get a tree split by modality first (which naturally splits ephys and behavior-videos tags into two groups), then by which probe or video a metric belongs to, and finally only for probes the individual shanks are split into groups. +When multiple QC stages are selected, they split at the top of the hierarchy. Multiple modalities split at the next level, or at the top when only one stage is selected. These fixed levels are followed by the tag levels in `QualityControl.default_grouping`. For example, `["stage", "modality", ("probe", "video"), "shank"]` groups first by stage, then by modality, then by probe or video at the same level, and finally by shank. + +Use the builder to define tag keys and values, drag tag keys into level buckets, and preview the resulting hierarchy: + +```{raw} html + +
+ +``` + +### Curations + +If you find yourself computing a value for something that is smaller than an entire modality of data and is repeated (e.g. neurons) in an asset you are performing *curation*, i.e. you are determining the status of a subset of a modality in the data asset. We provide the [CurationMetric](#curationmetric) for this purpose. You should put a dictionary in the `CurationMetric.value` field that contains a mapping between the subsets (usually neurons, ROIs, channels, etc) and their values. ### QualityControl.evaluate_status() @@ -53,6 +68,16 @@ Then, given the status of all the remaining metrics in the group: 2. If any metric is pending and the rest pass the evaluation is pending 3. If all metrics pass the evaluation passes +### QualityControl.status + +The `QualityControl.status` field is a dictionary that maps individual tag `key:value` pairs to their status. For example a typical status dictionary might look like this: + +``` +{ + "modality:behavior": "PASS", +} +``` + **Q: What is a metric reference?** Each [QCMetric](#qcmetric) should include a `QCMetric.reference`. References should be publicly accessible images, figures, multi-panel figures, and videos that support the metric value/status or provide the information necessary for manual annotation. diff --git a/qc-tree-app/.gitignore b/qc-tree-app/.gitignore new file mode 100644 index 00000000..b9470778 --- /dev/null +++ b/qc-tree-app/.gitignore @@ -0,0 +1,2 @@ +node_modules/ +dist/ diff --git a/qc-tree-app/index.html b/qc-tree-app/index.html new file mode 100644 index 00000000..0321f75e --- /dev/null +++ b/qc-tree-app/index.html @@ -0,0 +1,17 @@ + + + + + + QC Tree Builder + + + +
+ + + diff --git a/qc-tree-app/src/QCWidget.tsx b/qc-tree-app/src/QCWidget.tsx new file mode 100644 index 00000000..b1d457d1 --- /dev/null +++ b/qc-tree-app/src/QCWidget.tsx @@ -0,0 +1,407 @@ +import { useState, type DragEvent } from "react"; +import type { + FixedSelections, + GroupField, + GroupStep, + HierarchyStep, + TagDefinition, + TreeBranch, +} from "./widgetTypes"; +import { buildTree, fieldKey, formatDefaultGrouping } from "./widgetTree"; +import { MODALITIES, QC_STAGES, type Modality, type Stage } from "./vocabularies"; + +const FIELD_DRAG_TYPE = "application/x-qc-tree-field"; +const STEP_DRAG_TYPE = "application/x-qc-tree-step"; + +const initialTags: TagDefinition[] = [ + { id: "probe", key: "probe", values: "A, B", modalityScope: "ecephys" }, + { id: "video", key: "video", values: "left body, right body", modalityScope: "behavior-videos" }, + { id: "shank", key: "shank", values: "0, 1", modalityScope: "ecephys" }, +]; + +const initialGrouping: GroupStep[] = [ + { id: "group-probe-video", fields: ["tag:probe", "tag:video"] }, + { id: "group-shank", fields: ["tag:shank"] }, +]; + +const initialModalities: Modality[] = ["ecephys", "behavior", "behavior-videos"]; +const initialStages: Stage[] = ["Raw data", "Processing"]; + +function makeId(): string { + return crypto.randomUUID(); +} + +function toggleValue(values: Value[], value: Value): Value[] { + return values.includes(value) ? values.filter((item) => item !== value) : [...values, value]; +} + +function getFieldOptions(tags: TagDefinition[]): GroupField[] { + const options: GroupField[] = []; + const seenKeys = new Set(); + + for (const tag of tags) { + const key = tag.key.trim(); + if (!key || seenKeys.has(key)) continue; + seenKeys.add(key); + options.push(`tag:${tag.id}`); + } + + return options; +} + +function TreeList({ branches, root = false }: { branches: TreeBranch[]; root?: boolean }) { + if (!branches.length) return null; + + return ( +
    + {branches.map((branch) => ( +
  • +
    + {branch.key} + {branch.value} +
    + +
  • + ))} +
+ ); +} + +export default function QCWidget() { + const [tags, setTags] = useState(initialTags); + const [grouping, setGrouping] = useState(initialGrouping); + const [modalities, setModalities] = useState(initialModalities); + const [stages, setStages] = useState(initialStages); + const selections: FixedSelections = { modalities, stages }; + const effectiveGrouping: HierarchyStep[] = []; + if (stages.length > 1) { + effectiveGrouping.push({ id: "fixed-stage", fields: ["stage"], fixed: true }); + } + if (modalities.length > 1) { + effectiveGrouping.push({ id: "fixed-modality", fields: ["modality"], fixed: true }); + } + const fixedGrouping = [...effectiveGrouping]; + effectiveGrouping.push( + ...grouping + .filter((step) => step.fields.length > 0) + .map((step) => ({ ...step, fixed: false })), + ); + const tree = buildTree(effectiveGrouping, tags, selections); + const fieldOptions = getFieldOptions(tags); + const activeFields = new Set(grouping.flatMap((step) => step.fields)); + const availableFields = fieldOptions.filter((field) => !activeFields.has(field)); + const groupingCode = formatDefaultGrouping(effectiveGrouping, tags); + + function removeField(field: GroupField) { + setGrouping((current) => + current.map((step) => ({ ...step, fields: step.fields.filter((item) => item !== field) })), + ); + } + + function placeField(field: GroupField, targetId?: string) { + setGrouping((current) => { + const source = current.find((step) => step.fields.includes(field)); + if (source?.id === targetId) return current; + + const next = current.map((step) => ({ + ...step, + fields: step.fields.filter((item) => item !== field), + })); + const target = next.find((step) => step.id === targetId); + + if (target) { + return next.map((step) => + step.id === targetId ? { ...step, fields: [...step.fields, field] } : step, + ); + } + return [...next, { id: makeId(), fields: [field] }]; + }); + } + + function addLevel() { + setGrouping((current) => [...current, { id: makeId(), fields: [] }]); + } + + function moveStep(stepId: string, targetId?: string) { + setGrouping((current) => { + if (stepId === targetId) return current; + const sourceIndex = current.findIndex((step) => step.id === stepId); + if (sourceIndex < 0) return current; + + const next = [...current]; + const [step] = next.splice(sourceIndex, 1); + const targetIndex = targetId ? next.findIndex((item) => item.id === targetId) : next.length; + next.splice(targetIndex < 0 ? next.length : targetIndex, 0, step); + return next; + }); + } + + function handleDrop(event: DragEvent, targetId?: string) { + event.preventDefault(); + event.stopPropagation(); + const field = event.dataTransfer.getData(FIELD_DRAG_TYPE) as GroupField; + const stepId = event.dataTransfer.getData(STEP_DRAG_TYPE); + + if (field) placeField(field, targetId); + else if (stepId) moveStep(stepId, targetId); + } + + function startFieldDrag(event: DragEvent, field: GroupField) { + event.dataTransfer.effectAllowed = "copyMove"; + event.dataTransfer.setData(FIELD_DRAG_TYPE, field); + } + + function startStepDrag(event: DragEvent, stepId: string) { + event.dataTransfer.effectAllowed = "move"; + event.dataTransfer.setData(STEP_DRAG_TYPE, stepId); + } + + function updateTag(tagId: string, change: Partial) { + setTags((current) => current.map((tag) => (tag.id === tagId ? { ...tag, ...change } : tag))); + } + + function addTag() { + setTags((current) => [ + ...current, + { id: makeId(), key: "", values: "", modalityScope: "all" }, + ]); + } + + function removeTag(tagId: string) { + setTags((current) => current.filter((tag) => tag.id !== tagId)); + removeField(`tag:${tagId}`); + } + + function updateVocabulary( + values: Value[], + value: Value, + update: (next: Value[]) => void, + ) { + update(toggleValue(values, value)); + } + + return ( +
+
+
+
+
+ Stage values {stages.length} selected +
+ {QC_STAGES.map((stage) => ( + + ))} +
+
+ +
+ Modality values {modalities.length} selected +
+ {MODALITIES.map((modality) => ( + + ))} +
+
+
+ +
+
Tag definitions
+
+ + {tags.map((tag) => ( +
+ updateTag(tag.id, { key: event.currentTarget.value })} + placeholder="tag key" + value={tag.key} + /> + updateTag(tag.id, { values: event.currentTarget.value })} + placeholder="A, B" + value={tag.values} + /> + + +
+ ))} +
+ +
+ +
+
default_grouping
+
+
+ Available tags + Drag keys into a level +
+
+ {availableFields.map((field) => ( + + ))} + {availableFields.length === 0 && ( + All tag keys are in a level + )} +
+
+ +
    event.preventDefault()} + onDrop={(event) => handleDrop(event)} + > + {fixedGrouping.map((step, index) => ( +
  1. + + {index + 1} +
    + {step.fields.map((field) => ( + + + + ))} +
    +
  2. + ))} + {grouping.map((step, index) => { + const levelNumber = fixedGrouping.length + index + 1; + return ( +
  3. event.preventDefault()} + onDrop={(event) => handleDrop(event, step.id)} + > +
    + + Level {levelNumber} + Multiple keys form a tuple + +
    +
    + {step.fields.map((field) => ( + startFieldDrag(event, field)} + title={`Drag ${fieldKey(field, tags)} to another level`} + > + {fieldKey(field, tags)} + + + ))} + {step.fields.length === 0 && ( + Drop tag keys here + )} +
    +
  4. + ); + })} + {fixedGrouping.length + grouping.length === 0 && ( +
  5. Add a level, then drag tag keys into it.
  6. + )} +
+ + + + + {groupingCode} + +
+
+ +
+ {tree.length ? ( + + ) : ( +

Choose a grouping field and values to preview the hierarchy.

+ )} +
+
+
+ ); +} \ No newline at end of file diff --git a/qc-tree-app/src/main.tsx b/qc-tree-app/src/main.tsx new file mode 100644 index 00000000..e63ae974 --- /dev/null +++ b/qc-tree-app/src/main.tsx @@ -0,0 +1,31 @@ +import React from "react"; +import ReactDOM from "react-dom/client"; +import App from "./QCWidget"; +import "./qcWidget.css"; + +function mount(element: HTMLElement) { + if (element.dataset.mounted) return; + element.dataset.mounted = "true"; + ReactDOM.createRoot(element).render( + + + , + ); +} + +function mountAll() { + const targets = document.querySelectorAll(".qc-tree-app"); + if (targets.length) { + targets.forEach(mount); + return; + } + + const standaloneRoot = document.getElementById("root"); + if (standaloneRoot) mount(standaloneRoot); +} + +if (document.readyState === "loading") { + document.addEventListener("DOMContentLoaded", mountAll); +} else { + mountAll(); +} diff --git a/qc-tree-app/src/qcWidget.css b/qc-tree-app/src/qcWidget.css new file mode 100644 index 00000000..5c56ebf5 --- /dev/null +++ b/qc-tree-app/src/qcWidget.css @@ -0,0 +1,560 @@ +.qc-tree-widget { + --qc-border: var(--color-foreground-border, #d8d8d8); + --qc-muted: var(--color-foreground-muted, #666); + --qc-link: var(--color-brand-content, #0645ad); + --qc-background: var(--color-background-primary, #fff); + --qc-background-muted: var(--color-background-secondary, #f7f7f7); + box-sizing: border-box; + width: 100%; + color: var(--color-foreground-primary, inherit); + font: inherit; + font-size: 0.9em; + line-height: 1.45; + container-name: qc-widget; + container-type: inline-size; + border: 1px solid var(--qc-border); + background: var(--qc-background); +} + +.qc-tree-widget *, +.qc-tree-widget *::before, +.qc-tree-widget *::after { + box-sizing: border-box; +} + +.qc-tree-widget button, +.qc-tree-widget input, +.qc-tree-widget select { + max-width: 100%; + color: inherit; + font: inherit; +} + +.qc-tree-widget button { + cursor: pointer; +} + +.qc-tree-widget :focus-visible { + outline: 2px solid var(--qc-link); + outline-offset: 2px; +} + +.qc-widget-layout { + display: grid; + grid-template-columns: minmax(0, 1fr); + min-width: 0; +} + +.qc-controls { + min-width: 0; + padding: 12px; +} + +.qc-vocabulary { + min-width: 0; + border-bottom: 1px solid var(--qc-border); + padding-bottom: 8px; +} + +.qc-label { + margin-bottom: 6px; + color: var(--qc-muted); + font-family: ui-monospace, SFMono-Regular, Consolas, monospace; + font-size: 0.83em; + font-weight: 600; +} + +.qc-step-fields, +.qc-vocabulary-options, +.qc-stage-options { + display: flex; + flex-wrap: wrap; + align-items: center; + gap: 5px; +} + +.qc-field-options { + display: flex; + flex-direction: column; + align-items: stretch; + gap: 4px; + margin-bottom: 8px; +} + +.qc-field-options-heading { + display: flex; + justify-content: space-between; + gap: 8px; + color: var(--qc-muted); + font-size: 0.76em; +} + +.qc-field-options-heading span:last-child { + text-align: right; +} + +.qc-field-option-list { + display: flex; + flex-wrap: wrap; + align-items: center; + gap: 5px; +} + +.qc-no-available-tags { + color: var(--qc-muted); + font-size: 0.8em; +} + +.qc-field-option { + min-height: 27px; + border: 1px solid var(--qc-border); + border-radius: 2px; + background: var(--qc-background); + padding: 2px 7px; + color: var(--qc-link) !important; + font-family: ui-monospace, SFMono-Regular, Consolas, monospace !important; + font-size: 0.82em !important; +} + +.qc-field-option:hover { + border-color: var(--qc-link); + background: var(--qc-background-muted); +} + +.qc-grouping-list { + display: flex; + flex-direction: column; + align-items: stretch; + min-height: 39px; + margin: 8px 0 0; + padding: 0; + list-style: none; + gap: 5px; +} + +.qc-grouping-list.is-empty { + border: 1px dashed var(--qc-border); + padding: 6px; +} + +.qc-grouping-empty { + color: var(--qc-muted); + font-size: 0.85em; + list-style: none; +} + +.qc-grouping-step { + display: flex; + width: 100%; + flex: 0 0 auto; + min-width: 0; + min-height: 32px; + align-items: center; + gap: 6px; + border: 1px solid var(--qc-border); + background: var(--qc-background); + padding: 2px 5px 2px 2px; +} + +.qc-grouping-step.is-fixed { + background: var(--qc-background-muted); +} + +.qc-level-bucket { + flex-direction: column; + align-items: stretch; + gap: 0; + overflow: hidden; + padding: 0; +} + +.qc-level-header { + display: flex; + min-width: 0; + min-height: 34px; + align-items: center; + gap: 6px; + padding: 2px 6px 2px 2px; +} + +.qc-level-title { + flex: 0 0 auto; + font-size: 0.84em; +} + +.qc-level-hint { + min-width: 0; + overflow: hidden; + color: var(--qc-muted); + font-size: 0.72em; + text-overflow: ellipsis; + white-space: nowrap; +} + +.qc-remove-level { + flex: 0 0 auto; + margin-left: auto; + border: 0; + background: transparent; + color: var(--qc-muted); + font-size: 0.72em; +} + +.qc-remove-level:hover { + color: var(--qc-link); +} + +.qc-level-dropzone { + display: flex; + min-height: 45px; + flex-wrap: wrap; + align-content: flex-start; + align-items: center; + gap: 5px; + margin: 0 6px 6px; + border: 1px dashed var(--qc-border); + padding: 6px; +} + +.qc-drop-hint { + color: var(--qc-muted); + font-size: 0.78em; +} + +.qc-level-tag { + display: inline-flex; + min-height: 27px; + align-items: center; + gap: 5px; + border: 1px solid var(--qc-border); + background: var(--qc-background-muted); + padding: 2px 4px 2px 7px; + cursor: grab; +} + +.qc-level-tag:active { + cursor: grabbing; +} + +.qc-level-tag code { + color: var(--qc-link); + font-size: 0.82em; +} + +.qc-level-tag button { + width: 18px; + height: 19px; + border: 0; + background: transparent; + color: var(--qc-muted); + font-size: 1.1em; + line-height: 1; +} + +.qc-add-level { + margin-top: 7px; + border: 0; + background: transparent; + padding: 2px 0; + color: var(--qc-link) !important; + font-size: 0.82em !important; +} + +.qc-fixed-lock { + width: 32px; + flex: 0 0 32px; + color: var(--qc-muted); + font-size: 0.62em; + text-align: center; + text-transform: uppercase; +} + +.qc-drag-handle { + display: grid; + width: 19px; + height: 24px; + flex: 0 0 19px; + place-items: center; + border: 0; + background: transparent; + color: var(--qc-muted) !important; + cursor: grab !important; + font-size: 0.75em !important; +} + +.qc-step-number { + width: 13px; + color: var(--qc-muted); + font-size: 0.75em; + text-align: center; +} + +.qc-step-fields { + display: flex; + flex: 1 1 auto; + flex-wrap: wrap; + min-width: 0; +} + +.qc-step-field { + display: inline-flex; + min-height: 23px; + align-items: center; + gap: 4px; + color: var(--qc-link); + font-size: 0.82em; +} + +.qc-step-field code { + color: inherit; + font-size: 0.95em; +} + +.qc-step-field > .qc-fixed-field:disabled { + width: auto; + height: auto; + flex: 0 0 auto; + border: 0; + background: transparent; + color: var(--qc-muted); + cursor: not-allowed; + font-family: ui-monospace, SFMono-Regular, Consolas, monospace; + font-size: 0.95em; + opacity: 1; + padding: 0; + white-space: nowrap; +} + +.qc-step-field > button { + width: 17px; + height: 19px; + border: 0; + background: transparent; + color: var(--qc-muted); + font-size: 1.15em; + line-height: 1; +} + +.qc-step-field > button:hover, +.qc-remove-tag:hover { + color: var(--qc-link); +} + +.qc-or { + margin: 0 2px 0 4px; + color: var(--qc-muted); + font-size: 0.85em; +} + +.qc-grouping-code { + display: block; + overflow-wrap: anywhere; + margin-top: 8px; + border-left: 2px solid var(--qc-border); + background: var(--qc-background-muted); + padding: 5px 8px; + color: var(--color-foreground-primary, #222); + font-size: 0.8em; +} + +.qc-tag-definitions { + margin-top: 10px; + border-top: 1px solid var(--qc-border); + padding-top: 7px; +} + +.qc-tag-definitions-title, +.qc-modality-picker legend { + margin-bottom: 5px; + color: var(--qc-link); + font-size: 0.86em; +} + +.qc-modality-picker { + min-width: 0; + margin: 0; + border: 0; + padding: 0; +} + +.qc-tag-table { + min-width: 0; + margin-top: 7px; +} + +.qc-tag-headings, +.qc-tag-row { + display: grid; + grid-template-columns: minmax(64px, 0.8fr) minmax(74px, 1.2fr) minmax(74px, 0.7fr) 20px; + align-items: center; + gap: 5px; +} + +.qc-tag-headings { + margin: 0 0 3px; + color: var(--qc-muted); + font-size: 0.72em; +} + +.qc-tag-row + .qc-tag-row { + margin-top: 4px; +} + +.qc-tag-row input, +.qc-tag-row select { + width: 100%; + min-width: 0; + height: 27px; + border: 1px solid var(--qc-border); + border-radius: 2px; + background: var(--qc-background); + padding: 2px 5px; + font-size: 0.78em; +} + +.qc-tag-row input { + font-family: ui-monospace, SFMono-Regular, Consolas, monospace; +} + +.qc-tag-row select { + padding-right: 2px; +} + +.qc-remove-tag { + width: 20px; + height: 24px; + border: 0; + background: transparent; + color: var(--qc-muted); + font-size: 1.15em; +} + +.qc-add-tag { + margin-top: 6px; + border: 0; + background: transparent; + padding: 2px 0; + color: var(--qc-link) !important; + font-size: 0.82em !important; +} + +.qc-modality-picker legend span, +.qc-stage-picker legend span { + color: var(--qc-muted); + font-size: 0.9em; +} + +.qc-vocabulary-options { + padding: 6px 2px 2px; +} + +.qc-vocabulary-options label, +.qc-stage-options label { + display: inline-flex; + align-items: center; + gap: 3px; + color: var(--color-foreground-primary, inherit); + font-size: 0.76em; + white-space: nowrap; +} + +.qc-tree-widget input[type="checkbox"] { + width: 13px; + height: 13px; + margin: 0; + accent-color: var(--qc-link); +} + +.qc-stage-picker { + min-width: 0; + margin: 0 0 7px; + border: 0; + padding: 0; +} + +.qc-stage-picker legend, +.qc-modality-picker legend { + padding: 0; +} + +.qc-stage-picker legend { + margin-bottom: 4px; + color: var(--qc-link); + font-size: 0.86em; +} + +.qc-stage-options { + gap: 5px 10px; +} + +.qc-tree-preview { + min-width: 0; + min-height: 120px; + border-top: 1px solid var(--qc-border); + background: var(--qc-background); + padding: 12px; +} + +.qc-tree-list { + min-width: 0; + margin: 0; + padding: 0; + list-style: none; +} + +.qc-tree-list[role="group"] { + margin-left: 8px; + border-left: 1px solid var(--qc-border); + padding-left: 12px; +} + +.qc-tree-branch { + position: relative; + min-width: 0; + padding: 3px 0; + list-style: none; +} + +.qc-tree-list[role="group"] > .qc-tree-branch::before { + position: absolute; + top: 14px; + left: -12px; + width: 11px; + border-top: 1px solid var(--qc-border); + content: ""; +} + +.qc-tree-entry { + display: flex; + min-width: 0; + align-items: baseline; + gap: 8px; + overflow-wrap: anywhere; +} + +.qc-tree-entry code { + flex: 0 0 auto; + color: var(--qc-link); + font-size: 0.78em; +} + +.qc-tree-entry span { + font-size: 0.86em; +} + +.qc-tree-empty { + margin: 0; + color: var(--qc-muted); + font-size: 0.84em; +} + +@container qc-widget (min-width: 760px) { + .qc-widget-layout { + grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); + } + + .qc-tree-preview { + border-top: 0; + border-left: 1px solid var(--qc-border); + } +} \ No newline at end of file diff --git a/qc-tree-app/src/vocabularies.ts b/qc-tree-app/src/vocabularies.ts new file mode 100644 index 00000000..0e60a4e1 --- /dev/null +++ b/qc-tree-app/src/vocabularies.ts @@ -0,0 +1,28 @@ +export const QC_STAGES = ["Raw data", "Processing", "Analysis", "Multi-asset"] as const; +export type Stage = (typeof QC_STAGES)[number]; + +export const MODALITIES = [ + { name: "Barcoded anatomy resolved by sequencing", abbreviation: "BARseq" }, + { name: "Behavior", abbreviation: "behavior" }, + { name: "Behavior videos", abbreviation: "behavior-videos" }, + { name: "Brightfield microscopy", abbreviation: "brightfield" }, + { name: "Confocal microscopy", abbreviation: "confocal" }, + { name: "Extracellular electrophysiology", abbreviation: "ecephys" }, + { name: "Electron microscopy", abbreviation: "EM" }, + { name: "Electromyography", abbreviation: "EMG" }, + { name: "Fiber photometry", abbreviation: "fib" }, + { name: "Fluorescence micro-optical sectioning tomography", abbreviation: "fMOST" }, + { name: "Intracellular electrophysiology", abbreviation: "icephys" }, + { name: "Intrinsic signal imaging", abbreviation: "ISI" }, + { name: "Multiplexed analysis of projections by sequencing", abbreviation: "MAPseq" }, + { name: "Multiplexed error-robust fluorescence in situ hybridization", abbreviation: "merfish" }, + { name: "Magnetic resonance imaging", abbreviation: "MRI" }, + { name: "One-photon imaging", abbreviation: "one-photon" }, + { name: "Planar optical physiology", abbreviation: "pophys" }, + { name: "Single cell RNA sequencing", abbreviation: "scRNAseq" }, + { name: "Random access projection microscopy", abbreviation: "slap2" }, + { name: "Selective plane illumination microscopy", abbreviation: "SPIM" }, + { name: "Serial two-photon tomogrophy", abbreviation: "STPT" }, +] as const; + +export type Modality = (typeof MODALITIES)[number]["abbreviation"]; diff --git a/qc-tree-app/src/widgetTree.ts b/qc-tree-app/src/widgetTree.ts new file mode 100644 index 00000000..02f21a55 --- /dev/null +++ b/qc-tree-app/src/widgetTree.ts @@ -0,0 +1,95 @@ +import type { FixedSelections, HierarchyField, HierarchyStep, TagDefinition, TreeBranch } from "./widgetTypes"; +import type { Modality, Stage } from "./vocabularies"; + +type TreeContext = { + modality?: Modality; + stage?: Stage; +}; + +type Candidate = { + key: string; + value: string; + context: TreeContext; +}; + +export function fieldKey(field: HierarchyField, tags: TagDefinition[]): string { + if (field === "modality" || field === "stage") return field; + return tags.find((tag) => `tag:${tag.id}` === field)?.key.trim() || "tag"; +} + +export function formatDefaultGrouping(grouping: HierarchyStep[], tags: TagDefinition[]): string { + const entries = grouping.map((step) => { + const keys = step.fields.map((field) => JSON.stringify(fieldKey(field, tags))); + return keys.length === 1 ? keys[0] : `(${keys.join(", ")})`; + }); + + return `default_grouping = [${entries.join(", ")}]`; +} + +function candidatesForField( + field: HierarchyField, + context: TreeContext, + tags: TagDefinition[], + selections: FixedSelections, +): Candidate[] { + if (field === "modality") { + if (context.modality) return []; + return selections.modalities.map((value) => ({ + key: "modality", + value, + context: { ...context, modality: value }, + })); + } + + if (field === "stage") { + if (context.stage) return []; + return selections.stages.map((value) => ({ + key: "stage", + value, + context: { ...context, stage: value }, + })); + } + + const tag = tags.find((item) => `tag:${item.id}` === field); + if (!tag || (context.modality && tag.modalityScope !== "all" && tag.modalityScope !== context.modality)) { + return []; + } + + return Array.from(new Set(tag.values.split(",").map((value) => value.trim()).filter(Boolean))).map((value) => ({ + key: fieldKey(field, tags), + value, + context, + })); +} + +function buildLevel( + grouping: HierarchyStep[], + tags: TagDefinition[], + selections: FixedSelections, + depth: number, + context: TreeContext, +): TreeBranch[] { + const step = grouping[depth]; + if (!step) return []; + + return step.fields.flatMap((field) => + candidatesForField(field, context, tags, selections).map((candidate) => ({ + id: `${step.id}:${field}:${candidate.value}`, + key: candidate.key, + value: candidate.value, + children: buildLevel(grouping, tags, selections, depth + 1, candidate.context), + })), + ); +} + +export function buildTree( + grouping: HierarchyStep[], + tags: TagDefinition[], + selections: FixedSelections, +): TreeBranch[] { + const context = { + ...(selections.modalities.length === 1 ? { modality: selections.modalities[0] } : {}), + ...(selections.stages.length === 1 ? { stage: selections.stages[0] } : {}), + }; + return buildLevel(grouping, tags, selections, 0, context); +} \ No newline at end of file diff --git a/qc-tree-app/src/widgetTypes.ts b/qc-tree-app/src/widgetTypes.ts new file mode 100644 index 00000000..0411cb3c --- /dev/null +++ b/qc-tree-app/src/widgetTypes.ts @@ -0,0 +1,35 @@ +import type { Modality, Stage } from "./vocabularies"; + +export type TagDefinition = { + id: string; + key: string; + values: string; + modalityScope: Modality | "all"; +}; + +export type GroupField = `tag:${string}`; + +export type HierarchyField = "modality" | "stage" | GroupField; + +export type GroupStep = { + id: string; + fields: GroupField[]; +}; + +export type HierarchyStep = { + id: string; + fields: HierarchyField[]; + fixed?: boolean; +}; + +export type FixedSelections = { + modalities: Modality[]; + stages: Stage[]; +}; + +export type TreeBranch = { + id: string; + key: string; + value: string; + children: TreeBranch[]; +}; \ No newline at end of file diff --git a/qc-tree-app/vite.config.ts b/qc-tree-app/vite.config.ts new file mode 100644 index 00000000..3d802f4f --- /dev/null +++ b/qc-tree-app/vite.config.ts @@ -0,0 +1,26 @@ +import { defineConfig } from "vite"; +import react from "@vitejs/plugin-react"; +import { dirname, resolve } from "node:path"; +import { fileURLToPath } from "node:url"; + +const root = dirname(fileURLToPath(import.meta.url)); + +export default defineConfig(({ command }) => ({ + root, + plugins: [react()], + server: { host: "127.0.0.1", port: 5174, strictPort: false }, + ...(command === "build" ? { define: { "process.env.NODE_ENV": JSON.stringify("production") } } : {}), + build: { + outDir: resolve(root, "../docs/source/_static/qc-tree-app"), + emptyOutDir: false, + cssCodeSplit: false, + lib: { + entry: resolve(root, "src/main.tsx"), + formats: ["es"], + fileName: () => "qc-tree-app.js", + }, + rollupOptions: { + output: { assetFileNames: "qc-tree-app.[ext]" }, + }, + }, +})); From 22a98fb7f6b6a689726b34cf2b188f555b231f9c Mon Sep 17 00:00:00 2001 From: Dan Birman Date: Tue, 6 Oct 2026 11:45:33 -0700 Subject: [PATCH 2/5] chore: ensure new qc app package info is included --- .gitignore | 3 + qc-tree-app/package-lock.json | 1792 +++++++++++++++++++++++++++++++++ qc-tree-app/package.json | 22 + qc-tree-app/tsconfig.json | 16 + 4 files changed, 1833 insertions(+) create mode 100644 qc-tree-app/package-lock.json create mode 100644 qc-tree-app/package.json create mode 100644 qc-tree-app/tsconfig.json diff --git a/.gitignore b/.gitignore index 849fe07d..694c7703 100644 --- a/.gitignore +++ b/.gitignore @@ -147,6 +147,9 @@ examples/*.json !diagram-app/package.json !diagram-app/package-lock.json !diagram-app/tsconfig.json +!qc-tree-app/package.json +!qc-tree-app/package-lock.json +!qc-tree-app/tsconfig.json # diagram-app (React Flow schema diagram embedded in the docs front page) diagram-app/node_modules/ diff --git a/qc-tree-app/package-lock.json b/qc-tree-app/package-lock.json new file mode 100644 index 00000000..6608a7f7 --- /dev/null +++ b/qc-tree-app/package-lock.json @@ -0,0 +1,1792 @@ +{ + "name": "biodata-schema-qc-tree-app", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "biodata-schema-qc-tree-app", + "version": "0.1.0", + "dependencies": { + "react": "^18.3.1", + "react-dom": "^18.3.1" + }, + "devDependencies": { + "@types/react": "^18.3.12", + "@types/react-dom": "^18.3.1", + "@vitejs/plugin-react": "^4.3.4", + "typescript": "^5.6.3", + "vite": "^5.4.11" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz", + "integrity": "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.29.7", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.7.tgz", + "integrity": "sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.7.tgz", + "integrity": "sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@babel/generator": "^7.29.7", + "@babel/helper-compilation-targets": "^7.29.7", + "@babel/helper-module-transforms": "^7.29.7", + "@babel/helpers": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/template": "^7.29.7", + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7", + "@jridgewell/remapping": "^2.3.5", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/generator": { + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.8.tgz", + "integrity": "sha512-gZbepsdh3WDtgZKWL+vTPh71LSBrm/Y4/QDZBVCcYfmeTEEuoOYwlSy+G1StfJg+/Zy550u/3TATbm7qDbbMtg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.8", + "@babel/types": "^7.29.8", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.29.7.tgz", + "integrity": "sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.29.7", + "@babel/helper-validator-option": "^7.29.7", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-globals": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.29.7.tgz", + "integrity": "sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.29.7.tgz", + "integrity": "sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.29.7.tgz", + "integrity": "sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7", + "@babel/traverse": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.29.7.tgz", + "integrity": "sha512-G7sHYigPY17oO5SYWnfD/0MTBwVR781S/JI643e/JhUYgVgWE/61SoW3NH9KWUKyKq5LVh3npif99Wkt6j86Jw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz", + "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz", + "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.29.7.tgz", + "integrity": "sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.7.tgz", + "integrity": "sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.29.9", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.9.tgz", + "integrity": "sha512-CjXrNHTnvqBVqHgdBysY3vk2T8tpJHb5/RMeHJBTyVa9xgugCB0CJTx/3oO8RV2QRQP391RWpB7D6hLjm8V9uA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.8" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-self": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.29.7.tgz", + "integrity": "sha512-TL0hMc9xzy86VD31nUiwzd5otRAcyEPcsegCxolO0PvcXuH1v0kECe/UIznYFihpkvU5wg/jk4v0TTEFfm53fw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-source": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.29.7.tgz", + "integrity": "sha512-06IyK09H3wi4cGbhDBwp5gUGo0IKtnYa8tyTiephirPCK6fbobVGiXMMI5zLQ4aKEYP3wZ3ArU44o+8KMrSG/Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/template": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.29.7.tgz", + "integrity": "sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.8.tgz", + "integrity": "sha512-I5z7H3bf/41ktsNVLtpN0wAa336HkqIHQ5BuPLEhTkt1jVSyZpeNKIzTgEWmlxjdg81R0IgUCcaE+Ok3NvrfZg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@babel/generator": "^7.29.8", + "@babel/helper-globals": "^7.29.7", + "@babel/parser": "^7.29.8", + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.8", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.8.tgz", + "integrity": "sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", + "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", + "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", + "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", + "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", + "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", + "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", + "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", + "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", + "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", + "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", + "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", + "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", + "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", + "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", + "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", + "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", + "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", + "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", + "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", + "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", + "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", + "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", + "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.6.0.tgz", + "integrity": "sha512-T7jf+5zgsZHwNJ4lvQ7/aezbyk0nNX+zJVWpmHA7VYsEx7a7qr5Rg5IbtJFqkgze5Y2sruq1RUY8Q837Od7iFw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@napi-rs/lzma-linux-x64-gnu": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/@napi-rs/lzma-linux-x64-gnu/-/lzma-linux-x64-gnu-1.5.1.tgz", + "integrity": "sha512-oTXEIha4SsuXdTA4Iyskj0kpdx2yVXdhd75c2v3xGrHFfVMsbhTPZU/nMPL4sWKo4pBHm3aucLaqGlF696dTyQ==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^22.20 || ^24.12 || >=25" + } + }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.0-beta.27", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.27.tgz", + "integrity": "sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.64.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.64.0.tgz", + "integrity": "sha512-FLLpX941CD/7aBvX3GqLGBM9OvY5PGXTryPJkG5r5/OuBpZpV5k45Uo3RxAvqd35tsyc3hH1bhtz921IKzoIzg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.64.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.64.0.tgz", + "integrity": "sha512-iI32XM/jnDYJsvx5ai/za/7gWO9XoSeFFtU06/ZCaRgyilfJOjaopD3nOpk2WrTCGOyeDt4hleUiGOAnd5tHNg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.64.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.64.0.tgz", + "integrity": "sha512-dRBZlbt2sEtF8Mn4MODThze9fIPdDoOhVSlXMAKy5dQbOYK9pOOoPY4Fat3OTtr0+8zbJo5TTZwlsfxY/kDNJg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.64.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.64.0.tgz", + "integrity": "sha512-Y3whrJOMucfkhgNkvcM93M6j8C53iEAMmPMYD99C6G1kUy4ELigLWk9ar2/4aCBSRgsql0zdlOemLgW2m5GZgQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.64.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.64.0.tgz", + "integrity": "sha512-S6S1GEzPjFF6IONYJX3AKt/799+8RgBgCcwRnUo+Ep1IvBxUbw5M51iU0TDdK2NWWVnSvCQ8yi6Em0fGASMOng==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.64.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.64.0.tgz", + "integrity": "sha512-Ed1DPoFENkXj4IGzSB12SesV40iP6LxCCrbTIkSGIQBpOOxpBM+0kj62lmaeIHfMWTDoddqTOtqc7s8LYfn+Pw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.64.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.64.0.tgz", + "integrity": "sha512-J/6xhutJPtFyIkmHdf4olOdHHKH5kOJNumojdWn+Elv5ICEYTVOa362Vw27TxsK0BLzb1le3EDlO3UbvFK1lnQ==", + "cpu": [ + "arm" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.64.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.64.0.tgz", + "integrity": "sha512-G4L/Nnx59d2LvDoV/P4S5lZ7oVLT6hodOHMacqjiq2LL2gts86KbkEBTYL53+fBt0odhf7XPIbIATGoYiJctxg==", + "cpu": [ + "arm" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.64.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.64.0.tgz", + "integrity": "sha512-zF16pvJDEUksGYRbfnXne7pdklAyj2XDmJeYKgP93oq0cUyX9Y8O7lUo1R+IY1GagP/YBvCEDCe7eEcAKpw//g==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.64.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.64.0.tgz", + "integrity": "sha512-nIggWn8n+w12+R5lsV+PYYoUY8vuObxPAQqJI7WES+9v0qspYuAHoZMfYM0yLxlipasT5BY9ht5W8t5c/rSCkg==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.64.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.64.0.tgz", + "integrity": "sha512-WLOTiHPzszP0dxIMsHpFeDSOSB5I49Mj8K4+yKE3H1X/D0JRG5XZ5jrctJLMjnUc/LUzaKiwq6EHWNJ8pup8PA==", + "cpu": [ + "loong64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-musl": { + "version": "4.64.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.64.0.tgz", + "integrity": "sha512-35RK9aRhh7g7Pmeu5gQ01aCvrhXzj9LoBE6xtUcEH1ns+nyTaSzxSpADmBQINu4QiTDGvmQYwo1j5hlg1rRXFw==", + "cpu": [ + "loong64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.64.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.64.0.tgz", + "integrity": "sha512-RqTfnpoTjuWfPAmqK5p2edt2AMCDJWm6oTn7sKfmyx+6tRga0ip05SJ977o6udTcIiDeF/CJMUfkaN4gtWt6Aw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-musl": { + "version": "4.64.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.64.0.tgz", + "integrity": "sha512-RQjZPigjxFvFZDijG6rjlSXxhRaTf9zLYVpGK+lVcga64oMqP1GbgVqCb46eHTTceSIgp89Ja0y5aPe3GFBYHg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.64.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.64.0.tgz", + "integrity": "sha512-tjL58mgQcTRnDRpeky+Sth1MKQeYi2Ct6r3Luq9E5aTSjnM/i/JbozqZkKqp9thM5+oDSZxo+05f9kdQedfTGA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.64.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.64.0.tgz", + "integrity": "sha512-ictoRyVaoZ8C67myHef+8hhCa6IplXJJ/xUCkVCxziV4zxMZh+jvhkhGsPBLqj1S72fnqD0QH5zL4lcaa4X7DQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.64.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.64.0.tgz", + "integrity": "sha512-8aVvZ2hfr9RLFzBQkQNmYeHLDja8fLeQAmLt757zdKN/B+8L809KlLJKctQjS22wZotptV8G6o7fVPuAs8S1tQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.64.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.64.0.tgz", + "integrity": "sha512-2dEF8GAcDKwshUfydD+GhosppNyBzhVUHkdFF3CXd3FpOkzj/RZzF5aoEtzklujklT5qFVRU2GK/cFeLaTNKVg==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.64.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.64.0.tgz", + "integrity": "sha512-3XHTvoo2hKkh0MiOfS7SkhHjMaaWF7P4F3drocZZaho/Z8w7h/jpnuBHm91BOQLfvrKHs1yR+zir4E8RI3XzTQ==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openbsd-x64": { + "version": "4.64.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.64.0.tgz", + "integrity": "sha512-HKtkzodL4a3KFWDXDoO61cRynAWTR3LnAE0oGtfG9lcNFpNuVYUFOByxDgNqEvic9rvaQbAj+SFwTEWDptRaIw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.64.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.64.0.tgz", + "integrity": "sha512-JBsxqiY16uyyCujtoC3s7zL+SrYyNElptD7K4V+KUoJ2V8/XG3hPWpheK+SuPwNh1cikJvIZmIdsrYXvD6PLJw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.64.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.64.0.tgz", + "integrity": "sha512-S5Qrijh37qhnUYQ0ay8WN3LuWeKjow7wTUyCOPMZtnXiBXYXdsZETI6ZLfYnQAKovltckPLBFdNeD61P2rJc7g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.64.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.64.0.tgz", + "integrity": "sha512-zbZ6iMmLFEsCtTdc2/y1F/cDFVNNCPF7Ae8PCT/wdPE//hGwYp6r+MyCLMFX+kOeIe09Pz6ASfnnfpSTN1FJQQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.64.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.64.0.tgz", + "integrity": "sha512-L6Hw69oNpuYaOr1zCG30v0/DqKYCSRwodPGwIcVZ/6f8SOzq9rxtL/xNVI5MO4wjli+Ko0ErK9uHJL3mNPt8wQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.64.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.64.0.tgz", + "integrity": "sha512-nl+CTWIgOGszQmUz/kanfgrfFZ4qiwxKIfT/ryl3N3Ewk5tqizmYtNXiqb7Bu/fDtNgu1kyxdFiAUJNur3iysg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", + "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz", + "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.28.2" + } + }, + "node_modules/@types/estree": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/prop-types": { + "version": "15.7.15", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.15.tgz", + "integrity": "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/react": { + "version": "18.3.31", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.31.tgz", + "integrity": "sha512-vfEqpXTvwT91yhmwdfouStN2hSKwTvyRs8qpLfADyrq/kxDw0hZM7Wk9Ug1FELj8hIby+S/+kQCSRFF32nv2Qw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/prop-types": "*", + "csstype": "^3.2.2" + } + }, + "node_modules/@types/react-dom": { + "version": "18.3.7", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.7.tgz", + "integrity": "sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@types/react": "^18.0.0" + } + }, + "node_modules/@vitejs/plugin-react": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.7.0.tgz", + "integrity": "sha512-gUu9hwfWvvEDBBmgtAowQCojwZmJ5mcLn3aufeCsitijs3+f2NsrPtlAWIR6OPiqljl96GVCUbLe0HyqIpVaoA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.28.0", + "@babel/plugin-transform-react-jsx-self": "^7.27.1", + "@babel/plugin-transform-react-jsx-source": "^7.27.1", + "@rolldown/pluginutils": "1.0.0-beta.27", + "@types/babel__core": "^7.20.5", + "react-refresh": "^0.17.0" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "peerDependencies": { + "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" + } + }, + "node_modules/baseline-browser-mapping": { + "version": "2.11.27", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.11.27.tgz", + "integrity": "sha512-ElY12DaROGuan+lMmZ8Cvo/ZUbXPe7Enc/9VU/b1T3Kp4dwytRcNdR8DoSJN5SNJT/CuvcCA0DHDVmMOCePdRQ==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.cjs" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/browserslist": { + "version": "4.29.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.29.3.tgz", + "integrity": "sha512-1R4kiYKXGViqEN0CnoDrXc1StD9niAwu+j2dukWzrD4bJgsD4lDmEp0CRbc6E/vYJIfTHwPmwyaKtVSudICdPA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "baseline-browser-mapping": "^2.11.26", + "caniuse-lite": "^1.0.30001813", + "electron-to-chromium": "^1.5.439", + "node-releases": "^2.0.57", + "update-browserslist-db": "^1.3.3" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001814", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001814.tgz", + "integrity": "sha512-/Uaf1lAzr59XcMpW0o96WoEfr+VXK2OX4U9AgFoiSHsVJ4HppnIFUjtYzsyDH2+tgANaQb2/oxYGwCPapN1FpA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/electron-to-chromium": { + "version": "1.5.445", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.445.tgz", + "integrity": "sha512-iX7o1nF+qNb3Bv5mLYgqfgF9Znh9e/8MKXdmbb8Gv2Q47OKIzTwEPD1oda1HrgEwYatTLJj0wQjHvIFt8Db53Q==", + "dev": true, + "license": "ISC" + }, + "node_modules/esbuild": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", + "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.21.5", + "@esbuild/android-arm": "0.21.5", + "@esbuild/android-arm64": "0.21.5", + "@esbuild/android-x64": "0.21.5", + "@esbuild/darwin-arm64": "0.21.5", + "@esbuild/darwin-x64": "0.21.5", + "@esbuild/freebsd-arm64": "0.21.5", + "@esbuild/freebsd-x64": "0.21.5", + "@esbuild/linux-arm": "0.21.5", + "@esbuild/linux-arm64": "0.21.5", + "@esbuild/linux-ia32": "0.21.5", + "@esbuild/linux-loong64": "0.21.5", + "@esbuild/linux-mips64el": "0.21.5", + "@esbuild/linux-ppc64": "0.21.5", + "@esbuild/linux-riscv64": "0.21.5", + "@esbuild/linux-s390x": "0.21.5", + "@esbuild/linux-x64": "0.21.5", + "@esbuild/netbsd-x64": "0.21.5", + "@esbuild/openbsd-x64": "0.21.5", + "@esbuild/sunos-x64": "0.21.5", + "@esbuild/win32-arm64": "0.21.5", + "@esbuild/win32-ia32": "0.21.5", + "@esbuild/win32-x64": "0.21.5" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "license": "MIT" + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "license": "MIT", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.20", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.20.tgz", + "integrity": "sha512-uKdg2G3GNCKQn9byYOpxbGqrT2fGO5KRt5J/8b3pok8rT6qxGWF6hxMyJiEYtAf+FVyYuD9hRaDqX5uPFYJ4ZQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/node-releases": { + "version": "2.0.57", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.57.tgz", + "integrity": "sha512-kQK9LGGFiHtrWiNhZtA7Qbw17AQz+dmsEKODRIVTXA9+e5MS/2gZEBhYJt13GrAz5/IOZKddH/0Z3TP/Zgo+yw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/postcss": { + "version": "8.5.29", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.29.tgz", + "integrity": "sha512-49cGhUbXj8Qenv0iTMxA1cFBzxXoctpC9Ujd77t1WcbJIr6nF/eI7g/8MgxrYldFRuAXvja7xQRwavoW7kgrxQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.19", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/react": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.2" + }, + "peerDependencies": { + "react": "^18.3.1" + } + }, + "node_modules/react-refresh": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.17.0.tgz", + "integrity": "sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/rollup": { + "version": "4.64.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.64.0.tgz", + "integrity": "sha512-gjA/kFeDfffII8COoPsvLPvE16hWDTEc1+0QKQNKUkuV8iJjqsC4xXs8/FzuL0v9EV39kuxTbAgcFoTRyy2TGQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.9" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@napi-rs/lzma-linux-x64-gnu": "1.5.1", + "@rollup/rollup-android-arm-eabi": "4.64.0", + "@rollup/rollup-android-arm64": "4.64.0", + "@rollup/rollup-darwin-arm64": "4.64.0", + "@rollup/rollup-darwin-x64": "4.64.0", + "@rollup/rollup-freebsd-arm64": "4.64.0", + "@rollup/rollup-freebsd-x64": "4.64.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.64.0", + "@rollup/rollup-linux-arm-musleabihf": "4.64.0", + "@rollup/rollup-linux-arm64-gnu": "4.64.0", + "@rollup/rollup-linux-arm64-musl": "4.64.0", + "@rollup/rollup-linux-loong64-gnu": "4.64.0", + "@rollup/rollup-linux-loong64-musl": "4.64.0", + "@rollup/rollup-linux-ppc64-gnu": "4.64.0", + "@rollup/rollup-linux-ppc64-musl": "4.64.0", + "@rollup/rollup-linux-riscv64-gnu": "4.64.0", + "@rollup/rollup-linux-riscv64-musl": "4.64.0", + "@rollup/rollup-linux-s390x-gnu": "4.64.0", + "@rollup/rollup-linux-x64-gnu": "4.64.0", + "@rollup/rollup-linux-x64-musl": "4.64.0", + "@rollup/rollup-openbsd-x64": "4.64.0", + "@rollup/rollup-openharmony-arm64": "4.64.0", + "@rollup/rollup-win32-arm64-msvc": "4.64.0", + "@rollup/rollup-win32-ia32-msvc": "4.64.0", + "@rollup/rollup-win32-x64-gnu": "4.64.0", + "@rollup/rollup-win32-x64-msvc": "4.64.0", + "fsevents": "~2.3.2" + } + }, + "node_modules/scheduler": { + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + } + }, + "node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/source-map-js": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.2.tgz", + "integrity": "sha512-KGj/8Y43x35aZVDtt+J4mK1hoLGHULMYfSkODJNQjNDC3oW1PqPoxMwo0pLUsWM/UEGzON/NxeHywEfNXNP3Vw==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.3.3.tgz", + "integrity": "sha512-pJ2sYawQS0R/WI928Gj5GlPhTGzbMelq0+4INtSYNDV9ErKJcX6xjGWkoG/VnB3dpUm00zALaqkrUD77pO5TDQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/vite": { + "version": "5.4.21", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.21.tgz", + "integrity": "sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.21.3", + "postcss": "^8.4.43", + "rollup": "^4.20.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true, + "license": "ISC" + } + } +} diff --git a/qc-tree-app/package.json b/qc-tree-app/package.json new file mode 100644 index 00000000..03f6c44f --- /dev/null +++ b/qc-tree-app/package.json @@ -0,0 +1,22 @@ +{ + "name": "biodata-schema-qc-tree-app", + "private": true, + "version": "0.1.0", + "type": "module", + "scripts": { + "dev": "vite --host 127.0.0.1", + "build": "tsc --noEmit && vite build", + "preview": "vite preview --host 127.0.0.1" + }, + "dependencies": { + "react": "^18.3.1", + "react-dom": "^18.3.1" + }, + "devDependencies": { + "@types/react": "^18.3.12", + "@types/react-dom": "^18.3.1", + "@vitejs/plugin-react": "^4.3.4", + "typescript": "^5.6.3", + "vite": "^5.4.11" + } +} diff --git a/qc-tree-app/tsconfig.json b/qc-tree-app/tsconfig.json new file mode 100644 index 00000000..a627621e --- /dev/null +++ b/qc-tree-app/tsconfig.json @@ -0,0 +1,16 @@ +{ + "compilerOptions": { + "target": "ES2020", + "useDefineForClassFields": true, + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "module": "ESNext", + "skipLibCheck": true, + "moduleResolution": "bundler", + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "react-jsx", + "strict": true + }, + "include": ["src"] +} From 9b991655f37cf7b49a5ee5a692838cc0d7557221 Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 6 Oct 2026 18:46:58 +0000 Subject: [PATCH 3/5] update docs --- docs/source/biodata_models/organizations.md | 124 ++++++++++---------- docs/source/biodata_models/species.md | 34 +++--- docs/source/components/devices.md | 2 +- 3 files changed, 80 insertions(+), 80 deletions(-) diff --git a/docs/source/biodata_models/organizations.md b/docs/source/biodata_models/organizations.md index 6f1e1d1f..da8c6c2e 100644 --- a/docs/source/biodata_models/organizations.md +++ b/docs/source/biodata_models/organizations.md @@ -9,130 +9,130 @@ Organization | Name | name | abbreviation | registry | registry_identifier | |------|------|------|------|------| | `AA_OPTO_ELECTRONIC` | `AA Opto Electronic` | `None` | `None` | `None` | -| `ABCAM` | `Abcam` | `None` | `Registry.ROR` | `02e1wjw63` | -| `ADDGENE` | `Addgene` | `None` | `Registry.ROR` | `01nn1pw54` | -| `AI` | `Allen Institute` | `AI` | `Registry.ROR` | `03cpe7c52` | -| `AIBS` | `Allen Institute for Brain Science` | `AIBS` | `Registry.ROR` | `00dcv1019` | +| `ABCAM` | `Abcam` | `None` | `Research Organization Registry (ROR)` | `02e1wjw63` | +| `ADDGENE` | `Addgene` | `None` | `Research Organization Registry (ROR)` | `01nn1pw54` | +| `AI` | `Allen Institute` | `AI` | `Research Organization Registry (ROR)` | `03cpe7c52` | +| `AIBS` | `Allen Institute for Brain Science` | `AIBS` | `Research Organization Registry (ROR)` | `00dcv1019` | | `AILIPU` | `Ailipu Technology Co` | `Ailipu` | `None` | `None` | -| `AIND` | `Allen Institute for Neural Dynamics` | `AIND` | `Registry.ROR` | `04szwah67` | -| `AMS_OSRAM` | `ams OSRAM` | `None` | `Registry.ROR` | `045d0h266` | +| `AIND` | `Allen Institute for Neural Dynamics` | `AIND` | `Research Organization Registry (ROR)` | `04szwah67` | +| `AMS_OSRAM` | `ams OSRAM` | `None` | `Research Organization Registry (ROR)` | `045d0h266` | | `ANTIBODIES_INC` | `Antibodies Inc` | `None` | `None` | `None` | | `ARDUINO` | `Arduino` | `None` | `None` | `None` | | `ARECONT_VISION_COSTAR` | `Arecont Vision Costar` | `None` | `None` | `None` | | `ASI` | `Applied Scientific Instrumentation` | `ASI` | `None` | `None` | -| `ASUS` | `ASUS` | `None` | `Registry.ROR` | `00bxkz165` | +| `ASUS` | `ASUS` | `None` | `Research Organization Registry (ROR)` | `00bxkz165` | | `BASLER` | `Basler` | `None` | `None` | `None` | -| `BCM` | `Baylor College of Medicine` | `BCM` | `Registry.ROR` | `02pttbw34` | -| `BROADCOM` | `Broadcom` | `None` | `Registry.ROR` | `035gt5s03` | -| `BRUKER` | `Bruker` | `None` | `Registry.ROR` | `04r739x86` | -| `BU` | `Boston University` | `BU` | `Registry.ROR` | `05qwgg493` | -| `CAJAL` | `Cajal Neuroscience` | `Cajal` | `Registry.ROR` | `05pdc0q70` | +| `BCM` | `Baylor College of Medicine` | `BCM` | `Research Organization Registry (ROR)` | `02pttbw34` | +| `BROADCOM` | `Broadcom` | `None` | `Research Organization Registry (ROR)` | `035gt5s03` | +| `BRUKER` | `Bruker` | `None` | `Research Organization Registry (ROR)` | `04r739x86` | +| `BU` | `Boston University` | `BU` | `Research Organization Registry (ROR)` | `05qwgg493` | +| `CAJAL` | `Cajal Neuroscience` | `Cajal` | `Research Organization Registry (ROR)` | `05pdc0q70` | | `CAMBRIDGE_TECHNOLOGY` | `Cambridge Technology` | `None` | `None` | `None` | -| `CARL_ZEISS` | `Carl Zeiss` | `None` | `Registry.ROR` | `01xk5xs43` | -| `CHAMPALIMAUD` | `Champalimaud Foundation` | `Champalimaud` | `Registry.ROR` | `03g001n57` | +| `CARL_ZEISS` | `Carl Zeiss` | `None` | `Research Organization Registry (ROR)` | `01xk5xs43` | +| `CHAMPALIMAUD` | `Champalimaud Foundation` | `Champalimaud` | `Research Organization Registry (ROR)` | `03g001n57` | | `CHROMA` | `Chroma` | `None` | `None` | `None` | -| `COHERENT_SCIENTIFIC` | `Coherent Scientific` | `None` | `Registry.ROR` | `031tysd23` | -| `COLUMBIA` | `Columbia University` | `Columbia` | `Registry.ROR` | `00hj8s172` | +| `COHERENT_SCIENTIFIC` | `Coherent Scientific` | `None` | `Research Organization Registry (ROR)` | `031tysd23` | +| `COLUMBIA` | `Columbia University` | `Columbia` | `Research Organization Registry (ROR)` | `00hj8s172` | | `COMPUTAR` | `Computar` | `None` | `None` | `None` | | `CONOPTICS` | `Conoptics` | `None` | `None` | `None` | | `CRESTOPTICS` | `CrestOptics` | `None` | `None` | `None` | -| `CRL` | `Charles River Laboratories` | `CRL` | `Registry.ROR` | `03ndmsg87` | +| `CRL` | `Charles River Laboratories` | `CRL` | `Research Organization Registry (ROR)` | `03ndmsg87` | | `CUSTOM` | `Custom` | `None` | `None` | `None` | -| `CZI` | `Chan Zuckerberg Initiative` | `CZI` | `Registry.ROR` | `02qenvm24` | +| `CZI` | `Chan Zuckerberg Initiative` | `CZI` | `Research Organization Registry (ROR)` | `02qenvm24` | | `DIGIKEY` | `DigiKey` | `None` | `None` | `None` | | `DODOTRONIC` | `Dodotronic` | `None` | `None` | `None` | -| `DORIC` | `Doric` | `None` | `Registry.ROR` | `059n53q30` | +| `DORIC` | `Doric` | `None` | `Research Organization Registry (ROR)` | `059n53q30` | | `EALING` | `Ealing` | `None` | `None` | `None` | -| `EDMUND_OPTICS` | `Edmund Optics` | `None` | `Registry.ROR` | `01j1gwp17` | -| `EMORY` | `Emory University` | `Emory` | `Registry.ROR` | `03czfpz43` | +| `EDMUND_OPTICS` | `Edmund Optics` | `None` | `Research Organization Registry (ROR)` | `01j1gwp17` | +| `EMORY` | `Emory University` | `Emory` | `Research Organization Registry (ROR)` | `03czfpz43` | | `EURESYS` | `Euresys` | `None` | `None` | `None` | -| `EXCELITAS_TECHNOLOGIES` | `Excelitas Technologies` | `None` | `Registry.ROR` | `01tpbbf75` | -| `FLIR` | `Teledyne FLIR` | `FLIR` | `Registry.ROR` | `01j1gwp17` | +| `EXCELITAS_TECHNOLOGIES` | `Excelitas Technologies` | `None` | `Research Organization Registry (ROR)` | `01tpbbf75` | +| `FLIR` | `Teledyne FLIR` | `FLIR` | `Research Organization Registry (ROR)` | `01j1gwp17` | | `FUJINON` | `Fujinon` | `None` | `None` | `None` | -| `HAMAMATSU` | `Hamamatsu` | `None` | `Registry.ROR` | `03natb733` | +| `HAMAMATSU` | `Hamamatsu` | `None` | `Research Organization Registry (ROR)` | `03natb733` | | `HAMILTON` | `Hamilton` | `None` | `None` | `None` | -| `HUST` | `Huazhong University of Science and Technology` | `HUST` | `Registry.ROR` | `00p991c53` | -| `IDT` | `Integrated DNA Technologies` | `IDT` | `Registry.ROR` | `009jvpf03` | -| `IMEC` | `Interuniversity Microelectronics Center` | `IMEC` | `Registry.ROR` | `02kcbn207` | +| `HUST` | `Huazhong University of Science and Technology` | `HUST` | `Research Organization Registry (ROR)` | `00p991c53` | +| `IDT` | `Integrated DNA Technologies` | `IDT` | `Research Organization Registry (ROR)` | `009jvpf03` | +| `IMEC` | `Interuniversity Microelectronics Center` | `IMEC` | `Research Organization Registry (ROR)` | `02kcbn207` | | `INFINITY_PHOTO_OPTICAL` | `Infinity Photo-Optical` | `None` | `None` | `None` | -| `INVITROGEN` | `Invitrogen` | `None` | `Registry.ROR` | `03x1ewr52` | +| `INVITROGEN` | `Invitrogen` | `None` | `Research Organization Registry (ROR)` | `03x1ewr52` | | `IR_ROBOT_CO` | `IR Robot Co` | `None` | `None` | `None` | | `ISL` | `ISL Products International` | `ISL` | `None` | `None` | | `ITEM` | `Item` | `None` | `None` | `None` | -| `JANELIA` | `Janelia Research Campus` | `Janelia` | `Registry.ROR` | `013sk6x84` | -| `JAX` | `Jackson Laboratory` | `JAX` | `Registry.ROR` | `021sy4w91` | -| `JENOPTIK` | `Jenoptik` | `None` | `Registry.ROR` | `05g7t5c49` | -| `JHU` | `Johns Hopkins University` | `JHU` | `Registry.ROR` | `00za53h95` | +| `JANELIA` | `Janelia Research Campus` | `Janelia` | `Research Organization Registry (ROR)` | `013sk6x84` | +| `JAX` | `Jackson Laboratory` | `JAX` | `Research Organization Registry (ROR)` | `021sy4w91` | +| `JENOPTIK` | `Jenoptik` | `None` | `Research Organization Registry (ROR)` | `05g7t5c49` | +| `JHU` | `Johns Hopkins University` | `JHU` | `Research Organization Registry (ROR)` | `00za53h95` | | `JULABO` | `Julabo` | `None` | `None` | `None` | -| `KENT_SCIENTIFIC_CORPORATION` | `Kent Scientific Corporation` | `None` | `Registry.ROR` | `03xkj6a08` | -| `KOWA` | `Kowa` | `None` | `Registry.ROR` | `03zbwg482` | +| `KENT_SCIENTIFIC_CORPORATION` | `Kent Scientific Corporation` | `None` | `Research Organization Registry (ROR)` | `03xkj6a08` | +| `KOWA` | `Kowa` | `None` | `Research Organization Registry (ROR)` | `03zbwg482` | | `LASOS` | `LASOS Lasertechnik` | `LASOS` | `None` | `None` | | `LEICA` | `Leica` | `None` | `None` | `None` | -| `LG` | `LG` | `None` | `Registry.ROR` | `02b948n83` | +| `LG` | `LG` | `None` | `Research Organization Registry (ROR)` | `02b948n83` | | `LIFECANVAS` | `LifeCanvas` | `None` | `None` | `None` | | `LUMENCOR` | `Lumencor` | `None` | `None` | `None` | | `LUMEN_DYNAMICS` | `Lumen Dynamics` | `None` | `None` | `None` | -| `MBF` | `MBF Bioscience` | `MBF` | `Registry.ROR` | `02zynam48` | -| `MEADOWLARK_OPTICS` | `Meadowlark Optics` | `None` | `Registry.ROR` | `00n8qbq54` | -| `MIBR` | `McGovern Institute for Brain Research` | `MIBR` | `Registry.ROR` | `05ymca674` | +| `MBF` | `MBF Bioscience` | `MBF` | `Research Organization Registry (ROR)` | `02zynam48` | +| `MEADOWLARK_OPTICS` | `Meadowlark Optics` | `None` | `Research Organization Registry (ROR)` | `00n8qbq54` | +| `MIBR` | `McGovern Institute for Brain Research` | `MIBR` | `Research Organization Registry (ROR)` | `05ymca674` | | `MIDOPT` | `Midwest Optical Systems, Inc.` | `MidOpt` | `None` | `None` | -| `MIT` | `Massachusetts Institute of Technology` | `MIT` | `Registry.ROR` | `042nb2s44` | +| `MIT` | `Massachusetts Institute of Technology` | `MIT` | `Research Organization Registry (ROR)` | `042nb2s44` | | `MITUTUYO` | `Mitutuyo` | `None` | `None` | `None` | | `MIT_BCS` | `MIT Department of Brain and Cognitive Sciences` | `MIT-BCS` | `None` | `None` | -| `MJFF` | `Michael J. Fox Foundation for Parkinson's Research` | `MJFF` | `Registry.ROR` | `03arq3225` | -| `MKS_NEWPORT` | `MKS Newport` | `None` | `Registry.ROR` | `00k17f049` | +| `MJFF` | `Michael J. Fox Foundation for Parkinson's Research` | `MJFF` | `Research Organization Registry (ROR)` | `03arq3225` | +| `MKS_NEWPORT` | `MKS Newport` | `None` | `Research Organization Registry (ROR)` | `00k17f049` | | `MOLECULAR_INSTRUMENTS` | `Molecular Instruments` | `None` | `None` | `None` | | `MPI` | `MPI` | `MPI` | `None` | `None` | -| `NATIONAL_INSTRUMENTS` | `National Instruments` | `None` | `Registry.ROR` | `026exqw73` | +| `NATIONAL_INSTRUMENTS` | `National Instruments` | `None` | `Research Organization Registry (ROR)` | `026exqw73` | | `NAVITAR` | `Navitar` | `None` | `None` | `None` | -| `NCCIH` | `National Center for Complementary and Integrative Health` | `NCCIH` | `Registry.ROR` | `00190t495` | +| `NCCIH` | `National Center for Complementary and Integrative Health` | `NCCIH` | `Research Organization Registry (ROR)` | `00190t495` | | `NEURALYNX` | `NeuraLynx` | `None` | `None` | `None` | | `NEUROPHOTOMETRICS` | `Neurophotometrics` | `None` | `None` | `None` | | `NEW_SCALE_TECHNOLOGIES` | `New Scale Technologies` | `None` | `None` | `None` | -| `NIKON` | `Nikon` | `None` | `Registry.ROR` | `0280y9h11` | -| `NIMH` | `National Institute of Mental Health` | `NIMH` | `Registry.ROR` | `04xeg9z08` | -| `NINDS` | `National Institute of Neurological Disorders and Stroke` | `NINDS` | `Registry.ROR` | `01s5ya894` | +| `NIKON` | `Nikon` | `None` | `Research Organization Registry (ROR)` | `0280y9h11` | +| `NIMH` | `National Institute of Mental Health` | `NIMH` | `Research Organization Registry (ROR)` | `04xeg9z08` | +| `NINDS` | `National Institute of Neurological Disorders and Stroke` | `NINDS` | `Research Organization Registry (ROR)` | `01s5ya894` | | `NRESEARCH_INC` | `NResearch Inc` | `None` | `None` | `None` | -| `NYU` | `New York University` | `NYU` | `Registry.ROR` | `0190ak572` | -| `OEPS` | `Open Ephys Production Site` | `OEPS` | `Registry.ROR` | `007rkz355` | -| `OLYMPUS` | `Olympus` | `None` | `Registry.ROR` | `02vcdte90` | +| `NYU` | `New York University` | `NYU` | `Research Organization Registry (ROR)` | `0190ak572` | +| `OEPS` | `Open Ephys Production Site` | `OEPS` | `Research Organization Registry (ROR)` | `007rkz355` | +| `OLYMPUS` | `Olympus` | `None` | `Research Organization Registry (ROR)` | `02vcdte90` | | `OPTOTUNE` | `Optotune` | `None` | `None` | `None` | | `OTHER` | `Other` | `None` | `None` | `None` | -| `OXFORD_INSTRUMENTS` | `Oxford Instruments` | `None` | `Registry.ROR` | `01age2z78` | +| `OXFORD_INSTRUMENTS` | `Oxford Instruments` | `None` | `Research Organization Registry (ROR)` | `01age2z78` | | `OXXIUS` | `Oxxius` | `None` | `None` | `None` | | `PLACID_INDUSTRIES` | `Placid Industries` | `None` | `None` | `None` | | `PRIZMATIX` | `Prizmatix` | `None` | `None` | `None` | | `QUANTIFI` | `Quantifi` | `None` | `None` | `None` | | `RASPBERRY_PI` | `Raspberry Pi` | `None` | `None` | `None` | -| `ROCKLAND` | `Rockland Immunochemicals` | `ROCKLAND` | `Registry.ROR` | `02z2r2t61` | +| `ROCKLAND` | `Rockland Immunochemicals` | `ROCKLAND` | `Research Organization Registry (ROR)` | `02z2r2t61` | | `SAME_SKY` | `Same Sky` | `None` | `None` | `None` | | `SCHNEIDER_KREUZNACH` | `Schneider-Kreuznach` | `None` | `None` | `None` | -| `SCIENTIFICA` | `Scientifica` | `None` | `Registry.ROR` | `00z72df47` | +| `SCIENTIFICA` | `Scientifica` | `None` | `Research Organization Registry (ROR)` | `00z72df47` | | `SECOND_ORDER_EFFECTS` | `Second Order Effects` | `None` | `None` | `None` | | `SEMROCK` | `Semrock` | `None` | `None` | `None` | | `SICGEN` | `SICGEN` | `None` | `None` | `None` | | `SIGMA_ALDRICH` | `Sigma-Aldrich` | `None` | `None` | `None` | -| `SIMONS_FOUNDATION` | `Simons Foundation` | `None` | `Registry.ROR` | `01cmst727` | -| `SPECTRA_PHYSICS` | `Spectra-Physics` | `None` | `Registry.ROR` | `02ad9kp97` | +| `SIMONS_FOUNDATION` | `Simons Foundation` | `None` | `Research Organization Registry (ROR)` | `01cmst727` | +| `SPECTRA_PHYSICS` | `Spectra-Physics` | `None` | `Research Organization Registry (ROR)` | `02ad9kp97` | | `SPINNAKER` | `Spinnaker` | `None` | `None` | `None` | -| `STANFORD_UNIVERSITY` | `Stanford University` | `None` | `Registry.ROR` | `00f54p054` | +| `STANFORD_UNIVERSITY` | `Stanford University` | `None` | `Research Organization Registry (ROR)` | `00f54p054` | | `SYNAPTIC_SYSTEMS` | `Synaptic Systems` | `None` | `None` | `None` | | `TAMRON` | `Tamron` | `None` | `None` | `None` | | `TELEDYNE_VISION_SOLUTIONS` | `Teledyne Vision Solutions` | `None` | `None` | `None` | -| `TE_CONNECTIVITY` | `TE Connectivity` | `None` | `Registry.ROR` | `034frgp20` | -| `THERMO_FISHER_SCIENTIFIC` | `Thermo Fisher Scientific` | `None` | `Registry.ROR` | `03x1ewr52` | +| `TE_CONNECTIVITY` | `TE Connectivity` | `None` | `Research Organization Registry (ROR)` | `034frgp20` | +| `THERMO_FISHER_SCIENTIFIC` | `Thermo Fisher Scientific` | `None` | `Research Organization Registry (ROR)` | `03x1ewr52` | | `THE_IMAGING_SOURCE` | `The Imaging Source` | `None` | `None` | `None` | | `THE_LEE_COMPANY` | `The Lee Company` | `None` | `None` | `None` | -| `THORLABS` | `Thorlabs` | `None` | `Registry.ROR` | `04gsnvb07` | +| `THORLABS` | `Thorlabs` | `None` | `Research Organization Registry (ROR)` | `04gsnvb07` | | `TMC` | `Technical Manufacturing Corporation` | `TMC` | `None` | `None` | | `TRANSDUCER_TECHNIQUES` | `Transducer Techniques` | `None` | `None` | `None` | -| `TWCF` | `Templeton World Charity Foundation` | `TWCF` | `Registry.ROR` | `00x0z1472` | +| `TWCF` | `Templeton World Charity Foundation` | `TWCF` | `Research Organization Registry (ROR)` | `00x0z1472` | | `TYMPHANY` | `Tymphany` | `None` | `None` | `None` | -| `UCSD` | `University of California, San Diego` | `UCSD` | `Registry.ROR` | `0168r3w48` | +| `UCSD` | `University of California, San Diego` | `UCSD` | `Research Organization Registry (ROR)` | `0168r3w48` | | `UNKNOWN` | `Unknown` | `UNKNOWN` | `None` | `None` | -| `UPENN` | `University of Pennsylvania` | `UPENN` | `Registry.ROR` | `00b30xv10` | +| `UPENN` | `University of Pennsylvania` | `UPENN` | `Research Organization Registry (ROR)` | `00b30xv10` | | `VIEWORKS` | `Vieworks` | `None` | `None` | `None` | | `VORTRAN` | `Vortran` | `None` | `None` | `None` | -| `WPI` | `World Precision Intstruments` | `WPI` | `Registry.ROR` | `03st5df34` | +| `WPI` | `World Precision Intstruments` | `WPI` | `Research Organization Registry (ROR)` | `03st5df34` | diff --git a/docs/source/biodata_models/species.md b/docs/source/biodata_models/species.md index 4644d958..0ee0feb3 100644 --- a/docs/source/biodata_models/species.md +++ b/docs/source/biodata_models/species.md @@ -8,21 +8,21 @@ Species | Name | name | common_name | registry | registry_identifier | |------|------|------|------|------| -| `ALPACA` | `Vicuna pacos` | `Alpaca` | `Registry.NCBI` | `NCBI:txid30538` | -| `CHICKEN` | `Gallus gallus` | `Chicken` | `Registry.NCBI` | `NCBI:txid9031` | -| `COMMON_MARMOSET` | `Callithrix jacchus` | `Common marmoset` | `Registry.NCBI` | `NCBI:txid9483` | -| `COMMON_SQUIRREL_MONKEY` | `Saimiri sciureus` | `Common squirrel monkey` | `Registry.NCBI` | `NCBI:txid9521` | -| `CRAB_EATING_MACAQUE` | `Macaca fascicularis` | `Crab-eating macaque` | `Registry.NCBI` | `NCBI:txid9541` | -| `DONKEY` | `Equus asinus` | `Donkey` | `Registry.NCBI` | `NCBI:txid9793` | -| `EUROPEAN_RABBIT` | `Oryctolagus cuniculus` | `European rabbit` | `Registry.NCBI` | `NCBI:txid9986` | -| `GOAT` | `Carpa hircus` | `Goat` | `Registry.NCBI` | `NCBI:txid9925` | -| `GUINEA_PIG` | `Cavia porcellus` | `Guinea pig` | `Registry.NCBI` | `NCBI:txid10141` | -| `HOUSE_MOUSE` | `Mus musculus` | `House mouse` | `Registry.NCBI` | `NCBI:txid10090` | -| `HUMAN` | `Homo sapiens` | `Human` | `Registry.NCBI` | `NCBI:txid9606` | -| `LLAMA` | `Lama glama` | `Llama` | `Registry.NCBI` | `NCBI:txid9844` | -| `NORWAY_RAT` | `Rattus norvegicus` | `Norway rat` | `Registry.NCBI` | `NCBI:txid10116` | -| `PIG_TAILED_MACAQUE` | `Macaca nemestrina` | `Pig-tailed macaque` | `Registry.NCBI` | `NCBI:txid9545` | -| `RHESUS_MACAQUE` | `Macaca mulatta` | `Rhesus macaque` | `Registry.NCBI` | `NCBI:txid9544` | +| `ALPACA` | `Vicuna pacos` | `Alpaca` | `National Center for Biotechnology Information (NCBI)` | `NCBI:txid30538` | +| `CHICKEN` | `Gallus gallus` | `Chicken` | `National Center for Biotechnology Information (NCBI)` | `NCBI:txid9031` | +| `COMMON_MARMOSET` | `Callithrix jacchus` | `Common marmoset` | `National Center for Biotechnology Information (NCBI)` | `NCBI:txid9483` | +| `COMMON_SQUIRREL_MONKEY` | `Saimiri sciureus` | `Common squirrel monkey` | `National Center for Biotechnology Information (NCBI)` | `NCBI:txid9521` | +| `CRAB_EATING_MACAQUE` | `Macaca fascicularis` | `Crab-eating macaque` | `National Center for Biotechnology Information (NCBI)` | `NCBI:txid9541` | +| `DONKEY` | `Equus asinus` | `Donkey` | `National Center for Biotechnology Information (NCBI)` | `NCBI:txid9793` | +| `EUROPEAN_RABBIT` | `Oryctolagus cuniculus` | `European rabbit` | `National Center for Biotechnology Information (NCBI)` | `NCBI:txid9986` | +| `GOAT` | `Carpa hircus` | `Goat` | `National Center for Biotechnology Information (NCBI)` | `NCBI:txid9925` | +| `GUINEA_PIG` | `Cavia porcellus` | `Guinea pig` | `National Center for Biotechnology Information (NCBI)` | `NCBI:txid10141` | +| `HOUSE_MOUSE` | `Mus musculus` | `House mouse` | `National Center for Biotechnology Information (NCBI)` | `NCBI:txid10090` | +| `HUMAN` | `Homo sapiens` | `Human` | `National Center for Biotechnology Information (NCBI)` | `NCBI:txid9606` | +| `LLAMA` | `Lama glama` | `Llama` | `National Center for Biotechnology Information (NCBI)` | `NCBI:txid9844` | +| `NORWAY_RAT` | `Rattus norvegicus` | `Norway rat` | `National Center for Biotechnology Information (NCBI)` | `NCBI:txid10116` | +| `PIG_TAILED_MACAQUE` | `Macaca nemestrina` | `Pig-tailed macaque` | `National Center for Biotechnology Information (NCBI)` | `NCBI:txid9545` | +| `RHESUS_MACAQUE` | `Macaca mulatta` | `Rhesus macaque` | `National Center for Biotechnology Information (NCBI)` | `NCBI:txid9544` | ### Strain @@ -31,8 +31,8 @@ Strain | Name | name | species | registry | registry_identifier | |------|------|------|------|------| -| `BALB_C` | `BALB/c` | `Mus musculus` | `Registry.MGI` | `MGI:2159737` | -| `C57BL_6J` | `C57BL/6J` | `Mus musculus` | `Registry.MGI` | `MGI:3028467` | +| `BALB_C` | `BALB/c` | `Mus musculus` | `Mouse Genome Informatics (MGI)` | `MGI:2159737` | +| `C57BL_6J` | `C57BL/6J` | `Mus musculus` | `Mouse Genome Informatics (MGI)` | `MGI:3028467` | | `UNKNOWN` | `Unknown` | `Mus musculus` | `None` | `None` | diff --git a/docs/source/components/devices.md b/docs/source/components/devices.md index 78012d3a..d1cdf693 100644 --- a/docs/source/components/devices.md +++ b/docs/source/components/devices.md @@ -783,7 +783,7 @@ Multichannel electrophysiology DAQ | Field | Type | Title (Description) | |-------|------|-------------| | `ports` | List[[ProbePort](#probeport)] | Acquisition board ports | -| `data_interface` | `"DataInterface.USB"` | | +| `data_interface` | `"USB"` | | | `manufacturer` | [Organization](../biodata_models/organizations.md#organization) | | | `channels` | List[[DAQChannel](#daqchannel)] | DAQ channels | | `firmware_version` | `Optional[str]` | Firmware version | From cf21b92472d26168e9f6d884bb892cd6c5f4a0b5 Mon Sep 17 00:00:00 2001 From: Dan Birman Date: Wed, 7 Oct 2026 12:41:36 -0700 Subject: [PATCH 4/5] docs: clean up metric definitions --- docs/base/core/quality_control.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/docs/base/core/quality_control.md b/docs/base/core/quality_control.md index 5d30443f..f102f4da 100644 --- a/docs/base/core/quality_control.md +++ b/docs/base/core/quality_control.md @@ -12,10 +12,12 @@ Every [QCMetric](#qcmetric) has a `Status` which takes the value of the metric a The metrics defined during quality control should define whether or not an asset can be used for analysis and the properties of an asset that could influence how an analysis is performed. There are two levels of QC: -- Quality control metrics that are **not allowed to fail** are metrics that at `stage:raw` would prevent an asset from being processed or that at `stage:processing` would prevent an asset from being analyzed. This is a very high bar. Another way of saying this is that if the goals of the data acquisition were met, then all metrics that are 'not allowed to fail' should be passing. -- Quality control metrics that are **allowed to fail** are metrics that will influence the analysis of data, for example by indicating that one element of an asset cannot be used. These assets do not invalidate further analysis but they change how analysis should be performed. +- Quality control metrics that are **not allowed to fail** are metrics that at `stage:raw` would prevent an asset from being processed or that at `stage:processing` would prevent an asset from being analyzed. This is a very high bar. If the goals of the data acquisition were met (regardless of whether *experimental* goals were met), then all metrics that are 'not allowed to fail' should be passing. +- All other metrics should be **allowed to fail**. -The second kind of metrics are identified by the `QualityControl.allow_tag_failures` field, details below. +For example, if the goal of an acquisition was to collect behavior and fiber photometry, the 'not allowed to fail' metrics should define whether the behavior and fiber photometry data can be analyzed. Metrics that are allowed to fail could include whether the data meets various thresholds of behavior engagement, the signal to noise ratio of the data, and other potentially valuable (but not critical) metrics. + +Metrics that *can fail* are identified by the `QualityControl.allow_tag_failures` field, details below. ### Metrics From 9016f02965382615f50f0e961fdee48a72df905f Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 7 Oct 2026 19:42:41 +0000 Subject: [PATCH 5/5] update docs --- docs/source/quality_control.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/docs/source/quality_control.md b/docs/source/quality_control.md index c3b6057c..876ddd8f 100644 --- a/docs/source/quality_control.md +++ b/docs/source/quality_control.md @@ -12,10 +12,12 @@ Every [QCMetric](#qcmetric) has a `Status` which takes the value of the metric a The metrics defined during quality control should define whether or not an asset can be used for analysis and the properties of an asset that could influence how an analysis is performed. There are two levels of QC: -- Quality control metrics that are **not allowed to fail** are metrics that at `stage:raw` would prevent an asset from being processed or that at `stage:processing` would prevent an asset from being analyzed. This is a very high bar. Another way of saying this is that if the goals of the data acquisition were met, then all metrics that are 'not allowed to fail' should be passing. -- Quality control metrics that are **allowed to fail** are metrics that will influence the analysis of data, for example by indicating that one element of an asset cannot be used. These assets do not invalidate further analysis but they change how analysis should be performed. +- Quality control metrics that are **not allowed to fail** are metrics that at `stage:raw` would prevent an asset from being processed or that at `stage:processing` would prevent an asset from being analyzed. This is a very high bar. If the goals of the data acquisition were met (regardless of whether *experimental* goals were met), then all metrics that are 'not allowed to fail' should be passing. +- All other metrics should be **allowed to fail**. -The second kind of metrics are identified by the `QualityControl.allow_tag_failures` field, details below. +For example, if the goal of an acquisition was to collect behavior and fiber photometry, the 'not allowed to fail' metrics should define whether the behavior and fiber photometry data can be analyzed. Metrics that are allowed to fail could include whether the data meets various thresholds of behavior engagement, the signal to noise ratio of the data, and other potentially valuable (but not critical) metrics. + +Metrics that *can fail* are identified by the `QualityControl.allow_tag_failures` field, details below. ### Metrics