From 621b24c14ed701b819eb04746e527d56d077619a Mon Sep 17 00:00:00 2001 From: Danielle Callan Date: Thu, 2 Apr 2026 23:33:28 -0400 Subject: [PATCH 1/7] feat: configure flu workflow and add to workflow json --- catalog/output/qc-report.workflow-mappings.md | 5 +- .../output/workflow-assembly-mappings.json | 4 + catalog/output/workflows.json | 72 ++ .../catalog_build/generated_schema/schema.py | 725 ++++-------------- catalog/schema/generated/schema.ts | 2 +- catalog/schema/generated/workflows.json | 2 +- catalog/source/workflows.yml | 41 +- 7 files changed, 256 insertions(+), 595 deletions(-) diff --git a/catalog/output/qc-report.workflow-mappings.md b/catalog/output/qc-report.workflow-mappings.md index e61fd0e6e..7e718d0f5 100644 --- a/catalog/output/qc-report.workflow-mappings.md +++ b/catalog/output/qc-report.workflow-mappings.md @@ -27,6 +27,7 @@ None | Hi-C Processing: FASTQ to Balanced Cool Files | 4326 | | Hi-C Data Processing: FASTQ to Valid Interaction Pairs | 4326 | | Variant calling and consensus construction from paired end short read data of non-segmented viral genomes | 13 | +| Influenza A isolate subtyping and consensus sequence generation | 7 | | Pox Virus Illumina Amplicon Workflow from half-genomes | 2 | | AMR Gene Detection | 393 | | Genome annotation with Braker3 | 4475 | @@ -35,6 +36,6 @@ None ## Summary Statistics -- Total active workflows: 24 -- Workflows with ≥1 compatible assembly: 24 +- Total active workflows: 25 +- Workflows with ≥1 compatible assembly: 25 - Workflows with 0 compatible assemblies: 0 diff --git a/catalog/output/workflow-assembly-mappings.json b/catalog/output/workflow-assembly-mappings.json index fb4413434..307abd39e 100644 --- a/catalog/output/workflow-assembly-mappings.json +++ b/catalog/output/workflow-assembly-mappings.json @@ -71,6 +71,10 @@ "compatibleAssemblyCount": 4326, "workflowTrsId": "#workflow/github.com/iwc-workflows/hic-hicup-cooler/hic-fastq-to-pairs-hicup/versions/v0.3" }, + { + "compatibleAssemblyCount": 7, + "workflowTrsId": "#workflow/github.com/iwc-workflows/influenza-isolates-consensus-and-subtyping/main/versions/v0.3" + }, { "compatibleAssemblyCount": 2, "workflowTrsId": "#workflow/github.com/iwc-workflows/pox-virus-amplicon/main/versions/v0.4" diff --git a/catalog/output/workflows.json b/catalog/output/workflows.json index b5ee8e0b1..494375b6c 100644 --- a/catalog/output/workflows.json +++ b/catalog/output/workflows.json @@ -534,6 +534,78 @@ "workflowDescription": "Variant calling and consensus sequence generation for batches of Illumina PE sequenced viruses with uncomplicated and stable genome structure (like e.g. Morbilliviruses).", "workflowName": "Variant calling and consensus construction from paired end short read data of non-segmented viral genomes" }, + { + "iwcId": "influenza-isolates-consensus-and-subtyping-main", + "parameters": [ + { + "key": "References per segment collection", + "collection_spec": { + "collection_type": "list", + "name": "Influenza A Segment References", + "elements": [ + { + "ext": "fasta", + "src": "url", + "url": "https://zenodo.org/records/14628364/files/ref_1_pb2.fasta", + "md5": "5c8e6c3e8f3a1c5e5e5e5e5e5e5e5e5e" + }, + { + "ext": "fasta", + "src": "url", + "url": "https://zenodo.org/records/14628364/files/ref_2_pb1.fasta", + "md5": "5c8e6c3e8f3a1c5e5e5e5e5e5e5e5e5f" + }, + { + "ext": "fasta", + "src": "url", + "url": "https://zenodo.org/records/14628364/files/ref_3_pa.fasta", + "md5": "5c8e6c3e8f3a1c5e5e5e5e5e5e5e5e60" + }, + { + "ext": "fasta", + "src": "url", + "url": "https://zenodo.org/records/14628364/files/ref_4_ha.fasta", + "md5": "5c8e6c3e8f3a1c5e5e5e5e5e5e5e5e61" + }, + { + "ext": "fasta", + "src": "url", + "url": "https://zenodo.org/records/14628364/files/ref_5_np.fasta", + "md5": "5c8e6c3e8f3a1c5e5e5e5e5e5e5e5e62" + }, + { + "ext": "fasta", + "src": "url", + "url": "https://zenodo.org/records/14628364/files/ref_6_na.fasta", + "md5": "5c8e6c3e8f3a1c5e5e5e5e5e5e5e5e63" + }, + { + "ext": "fasta", + "src": "url", + "url": "https://zenodo.org/records/14628364/files/ref_7_mp.fasta", + "md5": "5c8e6c3e8f3a1c5e5e5e5e5e5e5e5e64" + }, + { + "ext": "fasta", + "src": "url", + "url": "https://zenodo.org/records/14628364/files/ref_8_ns.fasta", + "md5": "5c8e6c3e8f3a1c5e5e5e5e5e5e5e5e65" + } + ] + } + }, + { + "key": "Sequenced paired-end data", + "variable": "SANGER_READ_RUN_PAIRED" + } + ], + "ploidy": "ANY", + "scope": "ORGANISM", + "taxonomyId": "11320", + "trsId": "#workflow/github.com/iwc-workflows/influenza-isolates-consensus-and-subtyping/main/versions/v0.3", + "workflowDescription": "This workflow performs subtyping and consensus sequence generation for batches of Illumina PE sequenced Influenza A isolates.", + "workflowName": "Influenza A isolate subtyping and consensus sequence generation" + }, { "iwcId": "pox-virus-amplicon-main", "parameters": [ diff --git a/catalog/py_package/catalog_build/generated_schema/schema.py b/catalog/py_package/catalog_build/generated_schema/schema.py index c862e0812..02d0d9d1a 100644 --- a/catalog/py_package/catalog_build/generated_schema/schema.py +++ b/catalog/py_package/catalog_build/generated_schema/schema.py @@ -1,13 +1,32 @@ -from __future__ import annotations +from __future__ import annotations import re import sys -from datetime import date, datetime, time -from decimal import Decimal -from enum import Enum -from typing import Any, ClassVar, Dict, List, Literal, Optional, Union +from datetime import ( + date, + datetime, + time +) +from decimal import Decimal +from enum import Enum +from typing import ( + Any, + ClassVar, + Dict, + List, + Literal, + Optional, + Union +) + +from pydantic import ( + BaseModel, + ConfigDict, + Field, + RootModel, + field_validator +) -from pydantic import BaseModel, ConfigDict, Field, RootModel, field_validator metamodel_version = "None" version = "None" @@ -15,62 +34,52 @@ class ConfiguredBaseModel(BaseModel): model_config = ConfigDict( - validate_assignment=True, - validate_default=True, - extra="forbid", - arbitrary_types_allowed=True, - use_enum_values=True, - strict=False, + validate_assignment = True, + validate_default = True, + extra = "forbid", + arbitrary_types_allowed = True, + use_enum_values = True, + strict = False, ) pass + + class LinkMLMeta(RootModel): root: Dict[str, Any] = {} model_config = ConfigDict(frozen=True) - def __getattr__(self, key: str): + def __getattr__(self, key:str): return getattr(self.root, key) - def __getitem__(self, key: str): + def __getitem__(self, key:str): return self.root[key] - def __setitem__(self, key: str, value): + def __setitem__(self, key:str, value): self.root[key] = value - def __contains__(self, key: str) -> bool: + def __contains__(self, key:str) -> bool: return key in self.root -linkml_meta = LinkMLMeta( - { - "default_prefix": "https://github.com/galaxyproject/brc-analytics/blob/main/catalog/py_package/catalog_build/schema/schema.yaml#", - "description": "Combined source data schemas.", - "id": "https://github.com/galaxyproject/brc-analytics/blob/main/catalog/py_package/catalog_build/schema/schema.yaml#", - "imports": [ - "./assemblies", - "./organisms", - "./outbreaks", - "./workflow_categories", - "./workflows", - ], - "name": "schema", - "prefixes": { - "linkml": { - "prefix_prefix": "linkml", - "prefix_reference": "https://w3id.org/linkml/", - } - }, - "source_file": "/home/danielle/Documents/brc-analytics/brc-analytics/catalog/py_package/catalog_build/schema_utils/../schema/schema.yaml", - } -) - +linkml_meta = LinkMLMeta({'default_prefix': 'https://github.com/galaxyproject/brc-analytics/blob/main/catalog/py_package/catalog_build/schema/schema.yaml#', + 'description': 'Combined source data schemas.', + 'id': 'https://github.com/galaxyproject/brc-analytics/blob/main/catalog/py_package/catalog_build/schema/schema.yaml#', + 'imports': ['./assemblies', + './organisms', + './outbreaks', + './workflow_categories', + './workflows'], + 'name': 'schema', + 'prefixes': {'linkml': {'prefix_prefix': 'linkml', + 'prefix_reference': 'https://w3id.org/linkml/'}}, + 'source_file': '/home/danielle/Documents/brc-analytics/brc-analytics/catalog/py_package/catalog_build/schema_utils/../schema/schema.yaml'} ) class OrganismPloidy(str, Enum): """ Possible ploidies of an organism. """ - DIPLOID = "DIPLOID" HAPLOID = "HAPLOID" POLYPLOID = "POLYPLOID" @@ -80,7 +89,6 @@ class OutbreakPriority(str, Enum): """ Possible priorities of an outbreak. """ - HIGHEST = "HIGHEST" CRITICAL = "CRITICAL" HIGH = "HIGH" @@ -92,7 +100,6 @@ class OutbreakResourceType(str, Enum): """ Possible types of an outbreak resource. """ - PUBLICATION = "PUBLICATION" REFERENCE = "REFERENCE" NEWS = "NEWS" @@ -106,7 +113,6 @@ class WorkflowCategoryId(str, Enum): """ Set of IDs of workflow categories. """ - VARIANT_CALLING = "VARIANT_CALLING" TRANSCRIPTOMICS = "TRANSCRIPTOMICS" REGULATION = "REGULATION" @@ -120,10 +126,9 @@ class WorkflowCategoryId(str, Enum): class CollectionType(str, Enum): """ - Galaxy collection types supported for workflow parameters. - Currently only 'list' collections are supported, which represent a simple ordered list of datasets. + Galaxy collection types supported for collection_spec in workflow parameters. +Currently only 'list' collections are supported, which represent a simple ordered list of datasets. """ - # A simple ordered list of datasets. Each element in the collection is a separate dataset. list = "list" @@ -132,7 +137,6 @@ class WorkflowParameterVariable(str, Enum): """ Possible variables that can be inserted into workflow parameters. """ - ASSEMBLY_ID = "ASSEMBLY_ID" ASSEMBLY_FASTA_URL = "ASSEMBLY_FASTA_URL" FASTA_COLLECTION = "FASTA_COLLECTION" @@ -145,7 +149,6 @@ class WorkflowPloidy(str, Enum): """ Possible ploidies supported by workflows. """ - ANY = "ANY" DIPLOID = "DIPLOID" HAPLOID = "HAPLOID" @@ -156,7 +159,6 @@ class WorkflowScope(str, Enum): """ The scope level at which a workflow operates, determining its display context and required inputs. """ - # Workflow operates on a specific genome assembly and requires assembly selection as the first step. ASSEMBLY = "ASSEMBLY" # Workflow operates at the organism level, either requiring no specific assembly or working across multiple assemblies. @@ -169,7 +171,6 @@ class LibraryLayout(str, Enum): """ Enumeration of possible library layouts for sequencing data. """ - # Paired-end sequencing reads PAIRED = "PAIRED" # Single-end sequencing reads @@ -180,7 +181,6 @@ class LibrarySource(str, Enum): """ Enumeration of possible library sources for sequencing data. """ - # Genomic DNA (includes PCR products from genomic DNA) GENOMIC = "GENOMIC" # Genomic DNA from a single cell @@ -205,7 +205,6 @@ class LibraryStrategy(str, Enum): """ Enumeration of possible library strategies for sequencing data. """ - # Whole genome sequencing WGS = "WGS" # Whole genome amplification @@ -290,261 +289,100 @@ class LibraryStrategy(str, Enum): OTHER = "OTHER" + class Assemblies(ConfiguredBaseModel): """ Root object containing a collection of genomic assembly definitions for the BRC Analytics platform. """ + linkml_meta: ClassVar[LinkMLMeta] = LinkMLMeta({'from_schema': 'https://github.com/galaxyproject/brc-analytics/blob/main/catalog/py_package/catalog_build/schema/assemblies.yaml#', + 'tree_root': True}) - linkml_meta: ClassVar[LinkMLMeta] = LinkMLMeta( - { - "from_schema": "https://github.com/galaxyproject/brc-analytics/blob/main/catalog/py_package/catalog_build/schema/assemblies.yaml#", - "tree_root": True, - } - ) - - assemblies: List[Assembly] = Field( - default=..., - description="""Collection of genomic assembly entries that will be available for analysis in the BRC Analytics platform.""", - json_schema_extra={ - "linkml_meta": {"alias": "assemblies", "domain_of": ["Assemblies"]} - }, - ) + assemblies: List[Assembly] = Field(default=..., description="""Collection of genomic assembly entries that will be available for analysis in the BRC Analytics platform.""", json_schema_extra = { "linkml_meta": {'alias': 'assemblies', 'domain_of': ['Assemblies']} }) class Assembly(ConfiguredBaseModel): """ Definition of a genomic assembly with its unique identifier. """ + linkml_meta: ClassVar[LinkMLMeta] = LinkMLMeta({'from_schema': 'https://github.com/galaxyproject/brc-analytics/blob/main/catalog/py_package/catalog_build/schema/assemblies.yaml#'}) - linkml_meta: ClassVar[LinkMLMeta] = LinkMLMeta( - { - "from_schema": "https://github.com/galaxyproject/brc-analytics/blob/main/catalog/py_package/catalog_build/schema/assemblies.yaml#" - } - ) - - accession: str = Field( - default=..., - description="""The unique accession identifier for the assembly (e.g., GCA_000001405.28 for GRCh38), used to retrieve the assembly data from public repositories.""", - json_schema_extra={ - "linkml_meta": {"alias": "accession", "domain_of": ["Assembly"]} - }, - ) + accession: str = Field(default=..., description="""The unique accession identifier for the assembly (e.g., GCA_000001405.28 for GRCh38), used to retrieve the assembly data from public repositories.""", json_schema_extra = { "linkml_meta": {'alias': 'accession', 'domain_of': ['Assembly']} }) class Organisms(ConfiguredBaseModel): """ Root object containing a collection of organism definitions for the BRC Analytics platform. """ + linkml_meta: ClassVar[LinkMLMeta] = LinkMLMeta({'from_schema': 'https://github.com/galaxyproject/brc-analytics/blob/main/catalog/py_package/catalog_build/schema/organisms.yaml#', + 'tree_root': True}) - linkml_meta: ClassVar[LinkMLMeta] = LinkMLMeta( - { - "from_schema": "https://github.com/galaxyproject/brc-analytics/blob/main/catalog/py_package/catalog_build/schema/organisms.yaml#", - "tree_root": True, - } - ) - - organisms: List[Organism] = Field( - default=..., - description="""Collection of organism entries that will be available in the BRC Analytics platform.""", - json_schema_extra={ - "linkml_meta": {"alias": "organisms", "domain_of": ["Organisms"]} - }, - ) + organisms: List[Organism] = Field(default=..., description="""Collection of organism entries that will be available in the BRC Analytics platform.""", json_schema_extra = { "linkml_meta": {'alias': 'organisms', 'domain_of': ['Organisms']} }) class Organism(ConfiguredBaseModel): """ Definition of an organism with its taxonomic and genetic characteristics. """ + linkml_meta: ClassVar[LinkMLMeta] = LinkMLMeta({'from_schema': 'https://github.com/galaxyproject/brc-analytics/blob/main/catalog/py_package/catalog_build/schema/organisms.yaml#'}) - linkml_meta: ClassVar[LinkMLMeta] = LinkMLMeta( - { - "from_schema": "https://github.com/galaxyproject/brc-analytics/blob/main/catalog/py_package/catalog_build/schema/organisms.yaml#" - } - ) - - taxonomy_id: int = Field( - default=..., - description="""An NCBI Taxonomy ID at rank 'species'.""", - json_schema_extra={ - "linkml_meta": { - "alias": "taxonomy_id", - "domain_of": ["Organism", "Outbreak", "Workflow"], - } - }, - ) - ploidy: List[OrganismPloidy] = Field( - default=..., - description="""The possible ploidy states (number of chromosome sets) that the organism may have, which determines compatible workflows.""", - json_schema_extra={ - "linkml_meta": {"alias": "ploidy", "domain_of": ["Organism", "Workflow"]} - }, - ) + taxonomy_id: int = Field(default=..., description="""An NCBI Taxonomy ID at rank 'species'.""", json_schema_extra = { "linkml_meta": {'alias': 'taxonomy_id', 'domain_of': ['Organism', 'Outbreak', 'Workflow']} }) + ploidy: List[OrganismPloidy] = Field(default=..., description="""The possible ploidy states (number of chromosome sets) that the organism may have, which determines compatible workflows.""", json_schema_extra = { "linkml_meta": {'alias': 'ploidy', 'domain_of': ['Organism', 'Workflow']} }) class Outbreaks(ConfiguredBaseModel): """ Root object containing a collection of pathogen definitions for the BRC Analytics platform to highlight as outbreaks/priority pathogens. """ + linkml_meta: ClassVar[LinkMLMeta] = LinkMLMeta({'from_schema': 'https://github.com/galaxyproject/brc-analytics/blob/main/catalog/py_package/catalog_build/schema/outbreaks.yaml#', + 'tree_root': True}) - linkml_meta: ClassVar[LinkMLMeta] = LinkMLMeta( - { - "from_schema": "https://github.com/galaxyproject/brc-analytics/blob/main/catalog/py_package/catalog_build/schema/outbreaks.yaml#", - "tree_root": True, - } - ) - - outbreaks: List[Outbreak] = Field( - default=..., - description="""Collection of pathogen entries that will be displayed in the BRC Analytics platform as outbreaks/priority pathogens.""", - json_schema_extra={ - "linkml_meta": {"alias": "outbreaks", "domain_of": ["Outbreaks"]} - }, - ) + outbreaks: List[Outbreak] = Field(default=..., description="""Collection of pathogen entries that will be displayed in the BRC Analytics platform as outbreaks/priority pathogens.""", json_schema_extra = { "linkml_meta": {'alias': 'outbreaks', 'domain_of': ['Outbreaks']} }) class Outbreak(ConfiguredBaseModel): """ Definition of a priority pathogen with its taxonomic classification, priority level, and associated resources. """ + linkml_meta: ClassVar[LinkMLMeta] = LinkMLMeta({'from_schema': 'https://github.com/galaxyproject/brc-analytics/blob/main/catalog/py_package/catalog_build/schema/outbreaks.yaml#'}) - linkml_meta: ClassVar[LinkMLMeta] = LinkMLMeta( - { - "from_schema": "https://github.com/galaxyproject/brc-analytics/blob/main/catalog/py_package/catalog_build/schema/outbreaks.yaml#" - } - ) - - name: str = Field( - default=..., - description="""The display name of the pathogen as it will appear in the BRC Analytics interface.""", - json_schema_extra={ - "linkml_meta": { - "alias": "name", - "domain_of": ["Outbreak", "WorkflowCategory", "WorkflowCollectionSpec"], - } - }, - ) - taxonomy_id: int = Field( - default=..., - description="""The NCBI Taxonomy ID for the pathogen. Used to link to relevant genomic data and workflows.""", - json_schema_extra={ - "linkml_meta": { - "alias": "taxonomy_id", - "domain_of": ["Organism", "Outbreak", "Workflow"], - } - }, - ) - priority: OutbreakPriority = Field( - default=..., - description="""The priority level of the pathogen, which determines its visibility and prominence in the BRC Analytics interface.""", - json_schema_extra={ - "linkml_meta": {"alias": "priority", "domain_of": ["Outbreak"]} - }, - ) - resources: List[OutbreakResource] = Field( - default=..., - description="""Collection of external resources (references, tools, databases) related to the pathogen.""", - json_schema_extra={ - "linkml_meta": {"alias": "resources", "domain_of": ["Outbreak"]} - }, - ) - description: MarkdownFileReference = Field( - default=..., - description="""Reference to a markdown file containing detailed information about the pathogen.""", - json_schema_extra={ - "linkml_meta": { - "alias": "description", - "domain_of": [ - "Outbreak", - "WorkflowCategory", - "WorkflowDataRequirements", - ], - } - }, - ) - active: bool = Field( - default=..., - description="""Boolean flag that determines if the pathogen should be included in the BRC Analytics interface. Used to manage visibility as pathogen relevance changes over time.""", - json_schema_extra={ - "linkml_meta": {"alias": "active", "domain_of": ["Outbreak", "Workflow"]} - }, - ) - highlight_descendant_taxonomy_ids: Optional[List[int]] = Field( - default=None, - description="""List of NCBI Taxonomy IDs for descendant taxa (e.g., specific strains or serotypes) that should be highlighted within the outbreak category.""", - json_schema_extra={ - "linkml_meta": { - "alias": "highlight_descendant_taxonomy_ids", - "domain_of": ["Outbreak"], - } - }, - ) + name: str = Field(default=..., description="""The display name of the pathogen as it will appear in the BRC Analytics interface.""", json_schema_extra = { "linkml_meta": {'alias': 'name', + 'domain_of': ['Outbreak', 'WorkflowCategory', 'WorkflowCollectionSpec']} }) + taxonomy_id: int = Field(default=..., description="""The NCBI Taxonomy ID for the pathogen. Used to link to relevant genomic data and workflows.""", json_schema_extra = { "linkml_meta": {'alias': 'taxonomy_id', 'domain_of': ['Organism', 'Outbreak', 'Workflow']} }) + priority: OutbreakPriority = Field(default=..., description="""The priority level of the pathogen, which determines its visibility and prominence in the BRC Analytics interface.""", json_schema_extra = { "linkml_meta": {'alias': 'priority', 'domain_of': ['Outbreak']} }) + resources: List[OutbreakResource] = Field(default=..., description="""Collection of external resources (references, tools, databases) related to the pathogen.""", json_schema_extra = { "linkml_meta": {'alias': 'resources', 'domain_of': ['Outbreak']} }) + description: MarkdownFileReference = Field(default=..., description="""Reference to a markdown file containing detailed information about the pathogen.""", json_schema_extra = { "linkml_meta": {'alias': 'description', + 'domain_of': ['Outbreak', 'WorkflowCategory', 'WorkflowDataRequirements']} }) + active: bool = Field(default=..., description="""Boolean flag that determines if the pathogen should be included in the BRC Analytics interface. Used to manage visibility as pathogen relevance changes over time.""", json_schema_extra = { "linkml_meta": {'alias': 'active', 'domain_of': ['Outbreak', 'Workflow']} }) + highlight_descendant_taxonomy_ids: Optional[List[int]] = Field(default=None, description="""List of NCBI Taxonomy IDs for descendant taxa (e.g., specific strains or serotypes) that should be highlighted within the outbreak category.""", json_schema_extra = { "linkml_meta": {'alias': 'highlight_descendant_taxonomy_ids', 'domain_of': ['Outbreak']} }) class OutbreakResource(ConfiguredBaseModel): """ Definition of an external resource (reference, tool, database) associated with a priority pathogen. """ + linkml_meta: ClassVar[LinkMLMeta] = LinkMLMeta({'from_schema': 'https://github.com/galaxyproject/brc-analytics/blob/main/catalog/py_package/catalog_build/schema/outbreaks.yaml#'}) - linkml_meta: ClassVar[LinkMLMeta] = LinkMLMeta( - { - "from_schema": "https://github.com/galaxyproject/brc-analytics/blob/main/catalog/py_package/catalog_build/schema/outbreaks.yaml#" - } - ) - - url: str = Field( - default=..., - description="""The complete URL (including http/https protocol) to the external resource.""", - json_schema_extra={ - "linkml_meta": { - "alias": "url", - "domain_of": ["OutbreakResource", "WorkflowUrlSpec"], - } - }, - ) - title: str = Field( - default=..., - description="""The display title for the resource link as it will appear in the BRC Analytics interface.""", - json_schema_extra={ - "linkml_meta": {"alias": "title", "domain_of": ["OutbreakResource"]} - }, - ) - type: OutbreakResourceType = Field( - default=..., - description="""The category or type of the resource (e.g., REFERENCE, TOOL, DATABASE), which determines how it is displayed and organized.""", - json_schema_extra={ - "linkml_meta": {"alias": "type", "domain_of": ["OutbreakResource"]} - }, - ) + url: str = Field(default=..., description="""The complete URL (including http/https protocol) to the external resource.""", json_schema_extra = { "linkml_meta": {'alias': 'url', 'domain_of': ['OutbreakResource', 'WorkflowUrlSpec']} }) + title: str = Field(default=..., description="""The display title for the resource link as it will appear in the BRC Analytics interface.""", json_schema_extra = { "linkml_meta": {'alias': 'title', 'domain_of': ['OutbreakResource']} }) + type: OutbreakResourceType = Field(default=..., description="""The category or type of the resource (e.g., REFERENCE, TOOL, DATABASE), which determines how it is displayed and organized.""", json_schema_extra = { "linkml_meta": {'alias': 'type', 'domain_of': ['OutbreakResource']} }) class MarkdownFileReference(ConfiguredBaseModel): """ A reference to a markdown file containing detailed content about a priority pathogen. """ + linkml_meta: ClassVar[LinkMLMeta] = LinkMLMeta({'from_schema': 'https://github.com/galaxyproject/brc-analytics/blob/main/catalog/py_package/catalog_build/schema/outbreaks.yaml#'}) - linkml_meta: ClassVar[LinkMLMeta] = LinkMLMeta( - { - "from_schema": "https://github.com/galaxyproject/brc-analytics/blob/main/catalog/py_package/catalog_build/schema/outbreaks.yaml#" - } - ) - - path: str = Field( - default=..., - description="""Relative path to the markdown file from the project root. Must end with .md extension.""", - json_schema_extra={ - "linkml_meta": {"alias": "path", "domain_of": ["MarkdownFileReference"]} - }, - ) + path: str = Field(default=..., description="""Relative path to the markdown file from the project root. Must end with .md extension.""", json_schema_extra = { "linkml_meta": {'alias': 'path', 'domain_of': ['MarkdownFileReference']} }) - @field_validator("path") + @field_validator('path') def pattern_path(cls, v): - pattern = re.compile(r".*\.md$") - if isinstance(v, list): + pattern=re.compile(r".*\.md$") + if isinstance(v,list): for element in v: if isinstance(v, str) and not pattern.match(element): raise ValueError(f"Invalid path format: {element}") - elif isinstance(v, str): + elif isinstance(v,str): if not pattern.match(v): raise ValueError(f"Invalid path format: {v}") return v @@ -554,242 +392,65 @@ class WorkflowCategories(ConfiguredBaseModel): """ Root object containing a collection of workflow category definitions used to organize workflows in the BRC Analytics platform. """ + linkml_meta: ClassVar[LinkMLMeta] = LinkMLMeta({'from_schema': 'https://github.com/galaxyproject/brc-analytics/blob/main/catalog/py_package/catalog_build/schema/workflow_categories.yaml#', + 'tree_root': True}) - linkml_meta: ClassVar[LinkMLMeta] = LinkMLMeta( - { - "from_schema": "https://github.com/galaxyproject/brc-analytics/blob/main/catalog/py_package/catalog_build/schema/workflow_categories.yaml#", - "tree_root": True, - } - ) - - workflow_categories: List[WorkflowCategory] = Field( - default=..., - description="""Collection of workflow category entries that will be used to group and organize workflows in the BRC Analytics interface.""", - json_schema_extra={ - "linkml_meta": { - "alias": "workflow_categories", - "domain_of": ["WorkflowCategories"], - } - }, - ) + workflow_categories: List[WorkflowCategory] = Field(default=..., description="""Collection of workflow category entries that will be used to group and organize workflows in the BRC Analytics interface.""", json_schema_extra = { "linkml_meta": {'alias': 'workflow_categories', 'domain_of': ['WorkflowCategories']} }) class WorkflowCategory(ConfiguredBaseModel): """ Definition of a workflow category used to group related workflows for organization and display purposes. """ + linkml_meta: ClassVar[LinkMLMeta] = LinkMLMeta({'from_schema': 'https://github.com/galaxyproject/brc-analytics/blob/main/catalog/py_package/catalog_build/schema/workflow_categories.yaml#'}) - linkml_meta: ClassVar[LinkMLMeta] = LinkMLMeta( - { - "from_schema": "https://github.com/galaxyproject/brc-analytics/blob/main/catalog/py_package/catalog_build/schema/workflow_categories.yaml#" - } - ) - - category: WorkflowCategoryId = Field( - default=..., - description="""The unique identifier for the workflow category, used to link workflows to their respective categories.""", - json_schema_extra={ - "linkml_meta": {"alias": "category", "domain_of": ["WorkflowCategory"]} - }, - ) - name: str = Field( - default=..., - description="""The human-readable display name of the workflow category as it will appear in the BRC Analytics interface.""", - json_schema_extra={ - "linkml_meta": { - "alias": "name", - "domain_of": ["Outbreak", "WorkflowCategory", "WorkflowCollectionSpec"], - } - }, - ) - description: str = Field( - default=..., - description="""A detailed description of the workflow category explaining its purpose and the types of workflows it contains.""", - json_schema_extra={ - "linkml_meta": { - "alias": "description", - "domain_of": [ - "Outbreak", - "WorkflowCategory", - "WorkflowDataRequirements", - ], - } - }, - ) - show_coming_soon: bool = Field( - default=..., - description="""Boolean flag that determines whether to display a 'Coming Soon' indicator for this category in the BRC Analytics interface when workflows in this category are not yet available.""", - json_schema_extra={ - "linkml_meta": { - "alias": "show_coming_soon", - "domain_of": ["WorkflowCategory"], - } - }, - ) + category: WorkflowCategoryId = Field(default=..., description="""The unique identifier for the workflow category, used to link workflows to their respective categories.""", json_schema_extra = { "linkml_meta": {'alias': 'category', 'domain_of': ['WorkflowCategory']} }) + name: str = Field(default=..., description="""The human-readable display name of the workflow category as it will appear in the BRC Analytics interface.""", json_schema_extra = { "linkml_meta": {'alias': 'name', + 'domain_of': ['Outbreak', 'WorkflowCategory', 'WorkflowCollectionSpec']} }) + description: str = Field(default=..., description="""A detailed description of the workflow category explaining its purpose and the types of workflows it contains.""", json_schema_extra = { "linkml_meta": {'alias': 'description', + 'domain_of': ['Outbreak', 'WorkflowCategory', 'WorkflowDataRequirements']} }) + show_coming_soon: bool = Field(default=..., description="""Boolean flag that determines whether to display a 'Coming Soon' indicator for this category in the BRC Analytics interface when workflows in this category are not yet available.""", json_schema_extra = { "linkml_meta": {'alias': 'show_coming_soon', 'domain_of': ['WorkflowCategory']} }) class Workflows(ConfiguredBaseModel): """ Root object containing a collection of Galaxy workflow definitions for the BRC Analytics platform. """ + linkml_meta: ClassVar[LinkMLMeta] = LinkMLMeta({'from_schema': 'https://github.com/galaxyproject/brc-analytics/blob/main/catalog/py_package/catalog_build/schema/workflows.yaml#', + 'tree_root': True}) - linkml_meta: ClassVar[LinkMLMeta] = LinkMLMeta( - { - "from_schema": "https://github.com/galaxyproject/brc-analytics/blob/main/catalog/py_package/catalog_build/schema/workflows.yaml#", - "tree_root": True, - } - ) - - workflows: List[Workflow] = Field( - default=..., - description="""Collection of workflow entries that will be available to users in the BRC Analytics platform.""", - json_schema_extra={ - "linkml_meta": {"alias": "workflows", "domain_of": ["Workflows"]} - }, - ) + workflows: List[Workflow] = Field(default=..., description="""Collection of workflow entries that will be available to users in the BRC Analytics platform.""", json_schema_extra = { "linkml_meta": {'alias': 'workflows', 'domain_of': ['Workflows']} }) class Workflow(ConfiguredBaseModel): """ Definition of a Galaxy workflow with its metadata, parameters, and organism compatibility information. """ + linkml_meta: ClassVar[LinkMLMeta] = LinkMLMeta({'from_schema': 'https://github.com/galaxyproject/brc-analytics/blob/main/catalog/py_package/catalog_build/schema/workflows.yaml#'}) - linkml_meta: ClassVar[LinkMLMeta] = LinkMLMeta( - { - "from_schema": "https://github.com/galaxyproject/brc-analytics/blob/main/catalog/py_package/catalog_build/schema/workflows.yaml#" - } - ) - - trs_id: str = Field( - default=..., - description="""The Tool Repository Service (TRS) identifier for the workflow, used to locate and retrieve the workflow from a Galaxy server.""", - json_schema_extra={ - "linkml_meta": {"alias": "trs_id", "domain_of": ["Workflow"]} - }, - ) - categories: List[WorkflowCategoryId] = Field( - default=..., - description="""List of category identifiers that this workflow belongs to, determining how it is organized and displayed in the BRC Analytics interface.""", - json_schema_extra={ - "linkml_meta": {"alias": "categories", "domain_of": ["Workflow"]} - }, - ) - workflow_name: str = Field( - default=..., - description="""The human-readable display name of the workflow as it will appear in the BRC Analytics interface.""", - json_schema_extra={ - "linkml_meta": {"alias": "workflow_name", "domain_of": ["Workflow"]} - }, - ) - workflow_description: str = Field( - default=..., - description="""A detailed description of the workflow's purpose, functionality, and expected outputs for users.""", - json_schema_extra={ - "linkml_meta": {"alias": "workflow_description", "domain_of": ["Workflow"]} - }, - ) - ploidy: WorkflowPloidy = Field( - default=..., - description="""The ploidy state (number of chromosome sets) that this workflow is designed to work with, ensuring compatibility with organism data.""", - json_schema_extra={ - "linkml_meta": {"alias": "ploidy", "domain_of": ["Organism", "Workflow"]} - }, - ) - scope: Optional[WorkflowScope] = Field( - default=None, - description="""The scope level at which this workflow operates, determining where it is displayed in the UI and what the first configuration step should be. Defaults to ASSEMBLY for backward compatibility.""", - json_schema_extra={ - "linkml_meta": {"alias": "scope", "domain_of": ["Workflow"]} - }, - ) - taxonomy_id: Optional[int] = Field( - default=None, - description="""The NCBI Taxonomy ID of the organism this workflow is designed for. If specified, the workflow will be available for all assemblies with this ID in their taxonomic lineage.""", - json_schema_extra={ - "linkml_meta": { - "alias": "taxonomy_id", - "domain_of": ["Organism", "Outbreak", "Workflow"], - } - }, - ) - parameters: List[WorkflowParameter] = Field( - default=..., - description="""Collection of input parameters that will be passed to the workflow when it is executed, including data sources and configuration options.""", - json_schema_extra={ - "linkml_meta": {"alias": "parameters", "domain_of": ["Workflow"]} - }, - ) - active: bool = Field( - default=..., - description="""Boolean flag that determines if the workflow should be included in the BRC Analytics interface. Used to manage visibility of workflows that may be under development or deprecated.""", - json_schema_extra={ - "linkml_meta": {"alias": "active", "domain_of": ["Outbreak", "Workflow"]} - }, - ) - iwc_id: str = Field( - default=..., - description="""The Intergalactic Workflow Commission (IWC) identifier for the workflow, used to link to the workflow's page on the IWC website.""", - json_schema_extra={ - "linkml_meta": {"alias": "iwc_id", "domain_of": ["Workflow"]} - }, - ) + trs_id: str = Field(default=..., description="""The Tool Repository Service (TRS) identifier for the workflow, used to locate and retrieve the workflow from a Galaxy server.""", json_schema_extra = { "linkml_meta": {'alias': 'trs_id', 'domain_of': ['Workflow']} }) + categories: List[WorkflowCategoryId] = Field(default=..., description="""List of category identifiers that this workflow belongs to, determining how it is organized and displayed in the BRC Analytics interface.""", json_schema_extra = { "linkml_meta": {'alias': 'categories', 'domain_of': ['Workflow']} }) + workflow_name: str = Field(default=..., description="""The human-readable display name of the workflow as it will appear in the BRC Analytics interface.""", json_schema_extra = { "linkml_meta": {'alias': 'workflow_name', 'domain_of': ['Workflow']} }) + workflow_description: str = Field(default=..., description="""A detailed description of the workflow's purpose, functionality, and expected outputs for users.""", json_schema_extra = { "linkml_meta": {'alias': 'workflow_description', 'domain_of': ['Workflow']} }) + ploidy: WorkflowPloidy = Field(default=..., description="""The ploidy state (number of chromosome sets) that this workflow is designed to work with, ensuring compatibility with organism data.""", json_schema_extra = { "linkml_meta": {'alias': 'ploidy', 'domain_of': ['Organism', 'Workflow']} }) + scope: Optional[WorkflowScope] = Field(default=None, description="""The scope level at which this workflow operates, determining where it is displayed in the UI and what the first configuration step should be. Defaults to ASSEMBLY for backward compatibility.""", json_schema_extra = { "linkml_meta": {'alias': 'scope', 'domain_of': ['Workflow']} }) + taxonomy_id: Optional[int] = Field(default=None, description="""The NCBI Taxonomy ID of the organism this workflow is designed for. If specified, the workflow will be available for all assemblies with this ID in their taxonomic lineage.""", json_schema_extra = { "linkml_meta": {'alias': 'taxonomy_id', 'domain_of': ['Organism', 'Outbreak', 'Workflow']} }) + parameters: List[WorkflowParameter] = Field(default=..., description="""Collection of input parameters that will be passed to the workflow when it is executed, including data sources and configuration options.""", json_schema_extra = { "linkml_meta": {'alias': 'parameters', 'domain_of': ['Workflow']} }) + active: bool = Field(default=..., description="""Boolean flag that determines if the workflow should be included in the BRC Analytics interface. Used to manage visibility of workflows that may be under development or deprecated.""", json_schema_extra = { "linkml_meta": {'alias': 'active', 'domain_of': ['Outbreak', 'Workflow']} }) + iwc_id: str = Field(default=..., description="""The Intergalactic Workflow Commission (IWC) identifier for the workflow, used to link to the workflow's page on the IWC website.""", json_schema_extra = { "linkml_meta": {'alias': 'iwc_id', 'domain_of': ['Workflow']} }) class WorkflowDataRequirements(ConfiguredBaseModel): """ Specification of data requirements for a workflow parameter, such as library strategy and layout. """ + linkml_meta: ClassVar[LinkMLMeta] = LinkMLMeta({'from_schema': 'https://github.com/galaxyproject/brc-analytics/blob/main/catalog/py_package/catalog_build/schema/workflows.yaml#'}) - linkml_meta: ClassVar[LinkMLMeta] = LinkMLMeta( - { - "from_schema": "https://github.com/galaxyproject/brc-analytics/blob/main/catalog/py_package/catalog_build/schema/workflows.yaml#" - } - ) - - library_strategy: Optional[List[LibraryStrategy]] = Field( - default=None, - description="""The library strategy values that are acceptable for this parameter (e.g., 'WGS', 'RNA-Seq').""", - json_schema_extra={ - "linkml_meta": { - "alias": "library_strategy", - "domain_of": ["WorkflowDataRequirements"], - } - }, - ) - library_layout: Optional[LibraryLayout] = Field( - default=None, - description="""The library layout that is required for this parameter (e.g., 'PAIRED', 'SINGLE').""", - json_schema_extra={ - "linkml_meta": { - "alias": "library_layout", - "domain_of": ["WorkflowDataRequirements"], - } - }, - ) - library_source: Optional[List[LibrarySource]] = Field( - default=None, - description="""The library source values that are acceptable for this parameter (e.g., 'GENOMIC', 'TRANSCRIPTOMIC SINGLE CELL').""", - json_schema_extra={ - "linkml_meta": { - "alias": "library_source", - "domain_of": ["WorkflowDataRequirements"], - } - }, - ) - description: Optional[str] = Field( - default=None, - description="""A descriptive text to provide additional context about the data requirements, useful for non-standard library strategies like 'OTHER'.""", - json_schema_extra={ - "linkml_meta": { - "alias": "description", - "domain_of": [ - "Outbreak", - "WorkflowCategory", - "WorkflowDataRequirements", - ], - } - }, - ) + library_strategy: Optional[List[LibraryStrategy]] = Field(default=None, description="""The library strategy values that are acceptable for this parameter (e.g., 'WGS', 'RNA-Seq').""", json_schema_extra = { "linkml_meta": {'alias': 'library_strategy', 'domain_of': ['WorkflowDataRequirements']} }) + library_layout: Optional[LibraryLayout] = Field(default=None, description="""The library layout that is required for this parameter (e.g., 'PAIRED', 'SINGLE').""", json_schema_extra = { "linkml_meta": {'alias': 'library_layout', 'domain_of': ['WorkflowDataRequirements']} }) + library_source: Optional[List[LibrarySource]] = Field(default=None, description="""The library source values that are acceptable for this parameter (e.g., 'GENOMIC', 'TRANSCRIPTOMIC SINGLE CELL').""", json_schema_extra = { "linkml_meta": {'alias': 'library_source', 'domain_of': ['WorkflowDataRequirements']} }) + description: Optional[str] = Field(default=None, description="""A descriptive text to provide additional context about the data requirements, useful for non-standard library strategies like 'OTHER'.""", json_schema_extra = { "linkml_meta": {'alias': 'description', + 'domain_of': ['Outbreak', 'WorkflowCategory', 'WorkflowDataRequirements']} }) class WorkflowCollectionSpec(ConfiguredBaseModel): @@ -812,156 +473,39 @@ class WorkflowCollectionSpec(ConfiguredBaseModel): md5: def456... ``` """ + linkml_meta: ClassVar[LinkMLMeta] = LinkMLMeta({'from_schema': 'https://github.com/galaxyproject/brc-analytics/blob/main/catalog/py_package/catalog_build/schema/workflows.yaml#'}) - linkml_meta: ClassVar[LinkMLMeta] = LinkMLMeta( - { - "from_schema": "https://github.com/galaxyproject/brc-analytics/blob/main/catalog/py_package/catalog_build/schema/workflows.yaml#" - } - ) - - collection_type: CollectionType = Field( - default=..., - description="""The type of Galaxy collection to create. Currently only 'list' is supported. Determines the structure of the collection.""", - json_schema_extra={ - "linkml_meta": { - "alias": "collection_type", - "domain_of": ["WorkflowCollectionSpec"], - } - }, - ) - elements: List[WorkflowUrlSpec] = Field( - default=..., - description="""Array of URL specifications that will become elements in the collection. Each element represents a file to include in the collection. Must contain at least one element.""", - min_length=1, - json_schema_extra={ - "linkml_meta": { - "alias": "elements", - "domain_of": ["WorkflowCollectionSpec"], - } - }, - ) - name: Optional[str] = Field( - default=None, - description="""Optional identifier for the collection, used as the collection name in Galaxy. If not provided, defaults to 'Collection'.""", - json_schema_extra={ - "linkml_meta": { - "alias": "name", - "domain_of": ["Outbreak", "WorkflowCategory", "WorkflowCollectionSpec"], - } - }, - ) + collection_type: CollectionType = Field(default=..., description="""The type of Galaxy collection to create. Currently only 'list' is supported. Determines the structure of the collection.""", json_schema_extra = { "linkml_meta": {'alias': 'collection_type', 'domain_of': ['WorkflowCollectionSpec']} }) + elements: List[WorkflowUrlSpec] = Field(default=..., description="""Array of URL specifications that will become elements in the collection. Each element represents a file to include in the collection. Must contain at least one element.""", min_length=1, json_schema_extra = { "linkml_meta": {'alias': 'elements', 'domain_of': ['WorkflowCollectionSpec']} }) + name: Optional[str] = Field(default=None, description="""Optional identifier for the collection, used as the collection name in Galaxy. If not provided, defaults to 'Collection'.""", json_schema_extra = { "linkml_meta": {'alias': 'name', + 'domain_of': ['Outbreak', 'WorkflowCategory', 'WorkflowCollectionSpec']} }) class WorkflowParameter(ConfiguredBaseModel): """ Definition of an input parameter for a Galaxy workflow, specifying how the parameter value should be determined when the workflow is executed. """ + linkml_meta: ClassVar[LinkMLMeta] = LinkMLMeta({'from_schema': 'https://github.com/galaxyproject/brc-analytics/blob/main/catalog/py_package/catalog_build/schema/workflows.yaml#'}) - linkml_meta: ClassVar[LinkMLMeta] = LinkMLMeta( - { - "from_schema": "https://github.com/galaxyproject/brc-analytics/blob/main/catalog/py_package/catalog_build/schema/workflows.yaml#" - } - ) - - key: str = Field( - default=..., - description="""The identifier for the parameter as expected by the Galaxy workflow, used to map the parameter value to the correct input.""", - json_schema_extra={ - "linkml_meta": {"alias": "key", "domain_of": ["WorkflowParameter"]} - }, - ) - variable: Optional[WorkflowParameterVariable] = Field( - default=None, - description="""A predefined variable that will be substituted as the value of the parameter at runtime, such as assembly information.""", - json_schema_extra={ - "linkml_meta": {"alias": "variable", "domain_of": ["WorkflowParameter"]} - }, - ) - collection_spec: Optional[WorkflowCollectionSpec] = Field( - default=None, - description="""A collection specification for the parameter, allowing multiple files from external sources to be provided as a Galaxy collection.""", - json_schema_extra={ - "linkml_meta": { - "alias": "collection_spec", - "domain_of": ["WorkflowParameter"], - } - }, - ) - url_spec: Optional[WorkflowUrlSpec] = Field( - default=None, - description="""A direct URL specification for the parameter, allowing for external data sources to be provided to the workflow.""", - json_schema_extra={ - "linkml_meta": {"alias": "url_spec", "domain_of": ["WorkflowParameter"]} - }, - ) - data_requirements: Optional[WorkflowDataRequirements] = Field( - default=None, - description="""Specifications for the data requirements of this parameter, such as library strategy and layout.""", - json_schema_extra={ - "linkml_meta": { - "alias": "data_requirements", - "domain_of": ["WorkflowParameter"], - } - }, - ) - type_guide: Optional[Any] = Field( - default=None, - description="""Arbitrary data describing the expected type and format of the parameter, intended as a reference for catalog maintainers and not used in workflow execution.""", - json_schema_extra={ - "linkml_meta": {"alias": "type_guide", "domain_of": ["WorkflowParameter"]} - }, - ) + key: str = Field(default=..., description="""The identifier for the parameter as expected by the Galaxy workflow, used to map the parameter value to the correct input.""", json_schema_extra = { "linkml_meta": {'alias': 'key', 'domain_of': ['WorkflowParameter']} }) + variable: Optional[WorkflowParameterVariable] = Field(default=None, description="""A predefined variable that will be substituted as the value of the parameter at runtime, such as assembly information.""", json_schema_extra = { "linkml_meta": {'alias': 'variable', 'domain_of': ['WorkflowParameter']} }) + collection_spec: Optional[WorkflowCollectionSpec] = Field(default=None, description="""A collection specification for the parameter, allowing multiple files from external sources to be provided as a Galaxy collection.""", json_schema_extra = { "linkml_meta": {'alias': 'collection_spec', 'domain_of': ['WorkflowParameter']} }) + url_spec: Optional[WorkflowUrlSpec] = Field(default=None, description="""A direct URL specification for the parameter, allowing for external data sources to be provided to the workflow.""", json_schema_extra = { "linkml_meta": {'alias': 'url_spec', 'domain_of': ['WorkflowParameter']} }) + data_requirements: Optional[WorkflowDataRequirements] = Field(default=None, description="""Specifications for the data requirements of this parameter, such as library strategy and layout.""", json_schema_extra = { "linkml_meta": {'alias': 'data_requirements', 'domain_of': ['WorkflowParameter']} }) + type_guide: Optional[Any] = Field(default=None, description="""Arbitrary data describing the expected type and format of the parameter, intended as a reference for catalog maintainers and not used in workflow execution.""", json_schema_extra = { "linkml_meta": {'alias': 'type_guide', 'domain_of': ['WorkflowParameter']} }) class WorkflowUrlSpec(ConfiguredBaseModel): """ Definition of a URL-based data source for a workflow parameter, typically used for reference data or external resources. """ + linkml_meta: ClassVar[LinkMLMeta] = LinkMLMeta({'from_schema': 'https://github.com/galaxyproject/brc-analytics/blob/main/catalog/py_package/catalog_build/schema/workflows.yaml#'}) - linkml_meta: ClassVar[LinkMLMeta] = LinkMLMeta( - { - "from_schema": "https://github.com/galaxyproject/brc-analytics/blob/main/catalog/py_package/catalog_build/schema/workflows.yaml#" - } - ) - - ext: str = Field( - default=..., - description="""The file extension of the resource at the URL, which determines how Galaxy will interpret the data (e.g., 'fasta', 'gff', 'tabular').""", - json_schema_extra={ - "linkml_meta": {"alias": "ext", "domain_of": ["WorkflowUrlSpec"]} - }, - ) - src: str = Field( - default=..., - description="""The source type for the parameter, typically 'url' to indicate an external URL source rather than a Galaxy dataset or other source type.""", - json_schema_extra={ - "linkml_meta": {"alias": "src", "domain_of": ["WorkflowUrlSpec"]} - }, - ) - url: str = Field( - default=..., - description="""The complete URL (including http/https protocol) to the external resource that will be used as input to the workflow.""", - json_schema_extra={ - "linkml_meta": { - "alias": "url", - "domain_of": ["OutbreakResource", "WorkflowUrlSpec"], - } - }, - ) - db_key: Optional[str] = Field( - default=None, - description="""Optional database key (genome build) to associate with this file, used by Galaxy to link the file to a specific reference genome.""", - json_schema_extra={ - "linkml_meta": {"alias": "db_key", "domain_of": ["WorkflowUrlSpec"]} - }, - ) - md5: Optional[str] = Field( - default=None, - description="""Optional MD5 checksum hash for file integrity verification.""", - json_schema_extra={ - "linkml_meta": {"alias": "md5", "domain_of": ["WorkflowUrlSpec"]} - }, - ) + ext: str = Field(default=..., description="""The file extension of the resource at the URL, which determines how Galaxy will interpret the data (e.g., 'fasta', 'gff', 'tabular').""", json_schema_extra = { "linkml_meta": {'alias': 'ext', 'domain_of': ['WorkflowUrlSpec']} }) + src: str = Field(default=..., description="""The source type for the parameter, typically 'url' to indicate an external URL source rather than a Galaxy dataset or other source type.""", json_schema_extra = { "linkml_meta": {'alias': 'src', 'domain_of': ['WorkflowUrlSpec']} }) + url: str = Field(default=..., description="""The complete URL (including http/https protocol) to the external resource that will be used as input to the workflow.""", json_schema_extra = { "linkml_meta": {'alias': 'url', 'domain_of': ['OutbreakResource', 'WorkflowUrlSpec']} }) + db_key: Optional[str] = Field(default=None, description="""Optional database key (genome build) to associate with this file, used by Galaxy to link the file to a specific reference genome.""", json_schema_extra = { "linkml_meta": {'alias': 'db_key', 'domain_of': ['WorkflowUrlSpec']} }) + md5: Optional[str] = Field(default=None, description="""Optional MD5 checksum hash for file integrity verification.""", json_schema_extra = { "linkml_meta": {'alias': 'md5', 'domain_of': ['WorkflowUrlSpec']} }) # Model rebuild @@ -982,3 +526,4 @@ class WorkflowUrlSpec(ConfiguredBaseModel): WorkflowCollectionSpec.model_rebuild() WorkflowParameter.model_rebuild() WorkflowUrlSpec.model_rebuild() + diff --git a/catalog/schema/generated/schema.ts b/catalog/schema/generated/schema.ts index f9c54baec..2b2dc5c6c 100644 --- a/catalog/schema/generated/schema.ts +++ b/catalog/schema/generated/schema.ts @@ -47,7 +47,7 @@ export enum WorkflowCategoryId { OTHER = "OTHER", }; /** -* Galaxy collection types supported for workflow parameters. +* Galaxy collection types supported for collection_spec in workflow parameters. Currently only 'list' collections are supported, which represent a simple ordered list of datasets. */ export enum CollectionType { diff --git a/catalog/schema/generated/workflows.json b/catalog/schema/generated/workflows.json index e6fe294d4..7f49f687c 100644 --- a/catalog/schema/generated/workflows.json +++ b/catalog/schema/generated/workflows.json @@ -13,7 +13,7 @@ ] }, "CollectionType": { - "description": "Galaxy collection types supported for workflow parameters.\nCurrently only 'list' collections are supported, which represent a simple ordered list of datasets.", + "description": "Galaxy collection types supported for collection_spec in workflow parameters.\nCurrently only 'list' collections are supported, which represent a simple ordered list of datasets.", "enum": [ "list" ], diff --git a/catalog/source/workflows.yml b/catalog/source/workflows.yml index d6ebad962..55aed9a5d 100644 --- a/catalog/source/workflows.yml +++ b/catalog/source/workflows.yml @@ -902,14 +902,53 @@ workflows: This workflow performs subtyping and consensus sequence generation for batches of Illumina PE sequenced Influenza A isolates. ploidy: ANY + scope: ORGANISM + taxonomy_id: 11320 parameters: - key: References per segment collection + collection_spec: + collection_type: list + name: Influenza A Segment References + elements: + - ext: fasta + md5: 0cc350480c0ef6d2583b4764adaabb5a + src: url + url: https://zenodo.org/records/14628364/files/ref_1_pb2.fasta + - ext: fasta + md5: a8c9d6aa3c21ec24c42f480750dc4eca + src: url + url: https://zenodo.org/records/14628364/files/ref_2_pb1.fasta + - ext: fasta + md5: a5f373e913c0f84ea00cba35ea81c703 + src: url + url: https://zenodo.org/records/14628364/files/ref_3_pa.fasta + - ext: fasta + md5: 9476d2c02a0429e6b0e5a70ea2a94ef2 + src: url + url: https://zenodo.org/records/14628364/files/ref_4_ha.fasta + - ext: fasta + md5: 3d0e28d72bba2c8b352d64052524473d + src: url + url: https://zenodo.org/records/14628364/files/ref_5_np.fasta + - ext: fasta + md5: d8c21026a3defe01e020628e5b76227c + src: url + url: https://zenodo.org/records/14628364/files/ref_6_na.fasta + - ext: fasta + md5: 13b0b6900807d5e557348b0e69dc79ad + src: url + url: https://zenodo.org/records/14628364/files/ref_7_mp.fasta + - ext: fasta + md5: e98fc11ed2c825e54d8d88b295449f41 + src: url + url: https://zenodo.org/records/14628364/files/ref_8_ns.fasta type_guide: class: Collection - key: Sequenced paired-end data + variable: SANGER_READ_RUN_PAIRED type_guide: class: Collection - active: false + active: true iwc_id: influenza-isolates-consensus-and-subtyping-main - trs_id: "#workflow/github.com/iwc-workflows/lncRNAs-annotation/main/versions/v0.1" categories: From 941a3d277fb0e839a9328f2c32e07a74a8f71ea2 Mon Sep 17 00:00:00 2001 From: Danielle Callan Date: Thu, 2 Apr 2026 23:43:42 -0400 Subject: [PATCH 2/7] fix: build pages regardless of showcomingsoon workflow category flag --- pages/data/workflows/[trsId]/index.tsx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/pages/data/workflows/[trsId]/index.tsx b/pages/data/workflows/[trsId]/index.tsx index 08cbefb9d..48826a332 100644 --- a/pages/data/workflows/[trsId]/index.tsx +++ b/pages/data/workflows/[trsId]/index.tsx @@ -18,9 +18,7 @@ export interface Props { export const getStaticPaths: GetStaticPaths = async () => { const paths = workflowCategories.reduce( - (acc, { showComingSoon, workflows }) => { - // Special case, "showComingSoon", when false, should be skipped. - if (showComingSoon === false) return acc; + (acc, { workflows }) => { for (const { trsId } of workflows) { acc.push({ params: { trsId: formatTrsId(trsId) } }); } From fa87a1ec072da22af3ab8430436bac1a463d4832 Mon Sep 17 00:00:00 2001 From: Danielle Callan Date: Thu, 2 Apr 2026 23:44:53 -0400 Subject: [PATCH 3/7] feat: simple stepper-less wiring of flu workflow into app --- .../Step/hooks/UseLaunchGalaxy/types.ts | 58 +- .../hooks/UseLaunchGalaxy/useLaunchGalaxy.ts | 160 ++-- .../Step/hooks/UseLaunchGalaxy/utils.ts | 91 ++- app/views/WorkflowsView/utils.ts | 34 +- app/views/WorkflowsView/workflowsView.tsx | 11 +- .../catalog_build/generated_schema/schema.py | 725 ++++++++++++++---- pages/_app.tsx | 2 +- 7 files changed, 841 insertions(+), 240 deletions(-) diff --git a/app/components/Entity/components/ConfigureWorkflowInputs/components/Main/components/Stepper/components/Step/hooks/UseLaunchGalaxy/types.ts b/app/components/Entity/components/ConfigureWorkflowInputs/components/Main/components/Stepper/components/Step/hooks/UseLaunchGalaxy/types.ts index 94348484c..271c567e3 100644 --- a/app/components/Entity/components/ConfigureWorkflowInputs/components/Main/components/Stepper/components/Step/hooks/UseLaunchGalaxy/types.ts +++ b/app/components/Entity/components/ConfigureWorkflowInputs/components/Main/components/Stepper/components/Step/hooks/UseLaunchGalaxy/types.ts @@ -8,21 +8,67 @@ import { UcscTrack } from "../../../../../../../../../../../../utils/ucsc-tracks import { COLUMN_TYPE } from "../../SampleSheetClassificationStep/types"; import { Strandedness } from "../../StrandednessStep/types"; -export interface ConfiguredValue { +// Base configured values shared across all scopes +export interface BaseConfiguredValue { + readRunsPaired: EnaSequencingReads[] | null; + readRunsSingle: EnaSequencingReads[] | null; + tracks: UcscTrack[] | null; +} + +// ASSEMBLY scope: workflows that operate on a specific genome assembly +export interface AssemblyConfiguredValue extends BaseConfiguredValue { + _scope: "ASSEMBLY"; designFormula: string | null; geneModelUrl: string | null; - numberOfHits?: number; primaryContrasts: PrimaryContrasts | null; - readRunsPaired: EnaSequencingReads[] | null; - readRunsSingle: EnaSequencingReads[] | null; referenceAssembly: string; sampleSheet: Record[] | null; sampleSheetClassification: Record | null; - sequence?: string; strandedness: Strandedness | undefined; - tracks: UcscTrack[] | null; } +// ORGANISM scope: workflows that operate at organism level (may not require specific assembly) +// Organism scope workflows may have collection_spec (defined in workflow YAML) and variables. +// fastaCollection can be either: +// - User-selected assembly accessions (string[]) for user-defined FASTA collections +// - Auto-configured via collection_spec in workflow YAML (handled by Galaxy API) +export interface OrganismConfiguredValue extends BaseConfiguredValue { + _scope: "ORGANISM"; + fastaCollection: string[] | null; +} + +// SEQUENCE scope: workflows that operate on user-provided sequences +export interface SequenceConfiguredValue extends BaseConfiguredValue { + _scope: "SEQUENCE"; + numberOfHits?: number; + sequence?: string; +} + +// Type guards for ConfiguredValue discrimination +export function isAssemblyConfiguredValue( + value: ConfiguredValue +): value is AssemblyConfiguredValue { + return value._scope === "ASSEMBLY"; +} + +export function isOrganismConfiguredValue( + value: ConfiguredValue +): value is OrganismConfiguredValue { + return value._scope === "ORGANISM"; +} + +export function isSequenceConfiguredValue( + value: ConfiguredValue +): value is SequenceConfiguredValue { + return value._scope === "SEQUENCE"; +} + +// Union type for all configured values +export type ConfiguredValue = + | AssemblyConfiguredValue + | OrganismConfiguredValue + | SequenceConfiguredValue; + export interface Status { disabled: boolean; error: string | null; diff --git a/app/components/Entity/components/ConfigureWorkflowInputs/components/Main/components/Stepper/components/Step/hooks/UseLaunchGalaxy/useLaunchGalaxy.ts b/app/components/Entity/components/ConfigureWorkflowInputs/components/Main/components/Stepper/components/Step/hooks/UseLaunchGalaxy/useLaunchGalaxy.ts index 7e5d0bd75..25b5fc51f 100644 --- a/app/components/Entity/components/ConfigureWorkflowInputs/components/Main/components/Stepper/components/Step/hooks/UseLaunchGalaxy/useLaunchGalaxy.ts +++ b/app/components/Entity/components/ConfigureWorkflowInputs/components/Main/components/Stepper/components/Step/hooks/UseLaunchGalaxy/useLaunchGalaxy.ts @@ -11,9 +11,100 @@ import { CUSTOM_WORKFLOW } from "../../../../../../../../../../../../views/Analy import { DIFFERENTIAL_EXPRESSION_ANALYSIS } from "../../../../../../../../../../../../views/AnalyzeWorkflowsView/differentialExpressionAnalysis/constants"; import { LEXICMAP } from "../../../../../../../../../../../../views/AnalyzeWorkflowsView/lexicmap/constants"; import { LOGAN_SEARCH } from "../../../../../../../../../../../../views/AnalyzeWorkflowsView/loganSearch/constants"; -import { Props, UseLaunchGalaxy } from "./types"; +import { Workflow } from "../../../../../../../../../../../../apis/catalog/brc-analytics-catalog/common/entities"; +import { + ConfiguredValue, + isAssemblyConfiguredValue, + Props, + UseLaunchGalaxy, +} from "./types"; import { getConfiguredValues, launchGalaxy } from "./utils"; +/** + * Gets the appropriate landing URL based on workflow type. + * @param workflow - Workflow to launch. + * @param configuredValue - Configured values for the workflow. + * @param origin - Origin URL for the Galaxy instance. + * @param run - Async runner function from useAsync hook. + * @returns Promise resolving to the Galaxy workflow landing URL. + */ +async function getLandingUrlForWorkflow( + workflow: Workflow, + configuredValue: ConfiguredValue, + origin: string, + run: (promise: Promise) => Promise +): Promise { + if (workflow.trsId === CUSTOM_WORKFLOW.trsId) { + if (!isAssemblyConfiguredValue(configuredValue)) { + throw new Error("Invalid configured value for CUSTOM workflow"); + } + return run( + getDataLandingUrl( + configuredValue.referenceAssembly, + configuredValue.geneModelUrl, + configuredValue.readRunsSingle, + configuredValue.readRunsPaired, + null, + configuredValue.tracks, + origin + ) + ); + } + + if ( + workflow.trsId === LOGAN_SEARCH.trsId || + workflow.trsId === LEXICMAP.trsId + ) { + if (!workflow.workflowId) { + throw new Error("Missing workflow ID for LMLS workflow"); + } + return run(getLMLSLandingUrl(workflow.workflowId, origin)); + } + + if (workflow.trsId === DIFFERENTIAL_EXPRESSION_ANALYSIS.trsId) { + if ( + !workflow.workflowId || + !isAssemblyConfiguredValue(configuredValue) || + !configuredValue.geneModelUrl || + !configuredValue.sampleSheet || + !configuredValue.sampleSheetClassification || + !configuredValue.designFormula + ) { + throw new Error("Missing required values for DE workflow"); + } + return run( + getDeSeq2LandingUrl( + workflow.workflowId, + configuredValue.referenceAssembly, + configuredValue.geneModelUrl, + configuredValue.sampleSheet, + configuredValue.sampleSheetClassification, + configuredValue.designFormula, + configuredValue.primaryContrasts, + configuredValue.strandedness, + origin + ) + ); + } + + return run( + getWorkflowLandingUrl( + workflow.trsId, + isAssemblyConfiguredValue(configuredValue) + ? configuredValue.referenceAssembly + : "", + isAssemblyConfiguredValue(configuredValue) + ? configuredValue.geneModelUrl + : null, + configuredValue.readRunsSingle, + configuredValue.readRunsPaired, + null, + workflow.parameters, + origin + ) + ); +} + export const useLaunchGalaxy = ({ configuredInput, workflow, @@ -27,72 +118,17 @@ export const useLaunchGalaxy = ({ if (!configuredValue) return; const origin = config.browserURL || window.location.origin; - let landingUrl = ""; - - if (workflow.trsId === CUSTOM_WORKFLOW.trsId) { - landingUrl = await run( - getDataLandingUrl( - configuredValue.referenceAssembly, - configuredValue.geneModelUrl, - configuredValue.readRunsSingle, - configuredValue.readRunsPaired, - null, // fastaCollection - not yet supported in UI - configuredValue.tracks, - origin - ) - ); - } else if ( - workflow.trsId === LOGAN_SEARCH.trsId || - workflow.trsId === LEXICMAP.trsId - ) { - // LMLS workflows use stored workflow IDs with no parameters - if (!workflow.workflowId) { - throw new Error("Missing workflow ID for LMLS workflow"); - } - landingUrl = await run(getLMLSLandingUrl(workflow.workflowId, origin)); - } else if (workflow.trsId === DIFFERENTIAL_EXPRESSION_ANALYSIS.trsId) { - if ( - !workflow.workflowId || - !configuredValue.geneModelUrl || - !configuredValue.sampleSheet || - !configuredValue.sampleSheetClassification || - !configuredValue.designFormula - ) { - throw new Error("Missing required values for DE workflow"); - } - landingUrl = await run( - getDeSeq2LandingUrl( - workflow.workflowId, - configuredValue.referenceAssembly, - configuredValue.geneModelUrl, - configuredValue.sampleSheet, - configuredValue.sampleSheetClassification, - configuredValue.designFormula, - configuredValue.primaryContrasts, - configuredValue.strandedness, - origin - ) - ); - } else { - landingUrl = await run( - getWorkflowLandingUrl( - workflow.trsId, - configuredValue.referenceAssembly, - configuredValue.geneModelUrl, - configuredValue.readRunsSingle, - configuredValue.readRunsPaired, - null, // fastaCollection - not yet supported in UI - workflow.parameters, - origin - ) - ); - } + const landingUrl = await getLandingUrlForWorkflow( + workflow, + configuredValue, + origin, + run + ); if (!landingUrl) { throw new Error("Failed to retrieve Galaxy workflow launch URL."); } - // Launch the Galaxy workflow. launchGalaxy(landingUrl); }, [config, configuredValue, run, workflow]); diff --git a/app/components/Entity/components/ConfigureWorkflowInputs/components/Main/components/Stepper/components/Step/hooks/UseLaunchGalaxy/utils.ts b/app/components/Entity/components/ConfigureWorkflowInputs/components/Main/components/Stepper/components/Step/hooks/UseLaunchGalaxy/utils.ts index 84658606b..5f93133a8 100644 --- a/app/components/Entity/components/ConfigureWorkflowInputs/components/Main/components/Stepper/components/Step/hooks/UseLaunchGalaxy/utils.ts +++ b/app/components/Entity/components/ConfigureWorkflowInputs/components/Main/components/Stepper/components/Step/hooks/UseLaunchGalaxy/utils.ts @@ -54,6 +54,7 @@ function getDEConfiguredValues( } return { + _scope: "ASSEMBLY", designFormula, geneModelUrl, primaryContrasts: primaryContrasts ?? null, @@ -68,36 +69,13 @@ function getDEConfiguredValues( } /** - * Validates and returns configured values for SEQUENCE scope workflows. - * SEQUENCE scope workflows (like LMLS) have parameters for input sequence FASTA and number of hits. - * For now, return default/empty values to allow launching directly in Galaxy. - * The stepper UI will eventually populate these values from user input. - * @returns Configured values for SEQUENCE workflow. - */ -function getLMLSConfiguredValues(): ConfiguredValue { - return { - designFormula: null, - geneModelUrl: null, - numberOfHits: 10, - primaryContrasts: null, - readRunsPaired: null, - readRunsSingle: null, - referenceAssembly: "", - sampleSheet: null, - sampleSheetClassification: null, - sequence: "", - strandedness: undefined, - tracks: null, - }; -} - -/** - * Validates and returns configured values for standard workflows. + * Returns default configured values for ASSEMBLY scope workflows. + * ASSEMBLY scope workflows require assembly selection and may have additional parameters. * @param configuredInput - Configured input. * @param workflow - Workflow to check required parameters. - * @returns Configured values for standard workflow or undefined if invalid. + * @returns Configured values for ASSEMBLY workflow or undefined if invalid. */ -function getStandardConfiguredValues( +function getAssemblyScopeConfiguredValues( configuredInput: ConfiguredInput, workflow: Workflow ): ConfiguredValue | undefined { @@ -117,13 +95,12 @@ function getStandardConfiguredValues( if (requiredParams.SANGER_READ_RUN_PAIRED && !readRunsPaired) return; return { + _scope: "ASSEMBLY", designFormula: null, geneModelUrl: geneModelUrl ?? null, primaryContrasts: null, readRunsPaired: readRunsPaired ?? null, readRunsSingle: readRunsSingle ?? null, - // referenceAssembly is currently always set, but there are workflows that don't require referenceAssembly. - // xref https://github.com/galaxyproject/brc-analytics/issues/652 referenceAssembly: referenceAssembly!, sampleSheet: null, sampleSheetClassification: null, @@ -132,6 +109,46 @@ function getStandardConfiguredValues( }; } +/** + * Returns default configured values for ORGANISM scope workflows. + * ORGANISM scope workflows may have collection_spec and variables but don't require assembly-specific inputs. + * For Phase 1, return default/empty values to allow launching directly in Galaxy. + * The collection_spec will be automatically passed by the Galaxy API. + * Phase 2 will add stepper UI to populate these values from user input. + * @returns Configured values for ORGANISM workflow. + * (Phase 2): Add validation for required parameters (e.g., check if fastaCollection or + * other organism-specific inputs are required by the workflow and return undefined if missing). + */ +function getOrganismScopeConfiguredValues(): ConfiguredValue { + return { + _scope: "ORGANISM", + fastaCollection: null, + readRunsPaired: null, + readRunsSingle: null, + tracks: null, + }; +} + +/** + * Returns default configured values for SEQUENCE scope workflows. + * SEQUENCE scope workflows operate on user-provided sequences. + * For Phase 1, return default/empty values to allow launching directly in Galaxy. + * The stepper UI will eventually populate these values from user input. + * @returns Configured values for SEQUENCE workflow. + * (Phase 2): Add validation for required parameters (e.g., check if sequence input is + * required and return undefined if missing to disable launch button until user provides input). + */ +function getSequenceScopeConfiguredValues(): ConfiguredValue { + return { + _scope: "SEQUENCE", + numberOfHits: 10, + readRunsPaired: null, + readRunsSingle: null, + sequence: "", + tracks: null, + }; +} + /** * Returns the configured values from the configured input. * @param configuredInput - Configured input. @@ -142,20 +159,28 @@ export function getConfiguredValues( configuredInput: ConfiguredInput, workflow: Workflow ): ConfiguredValue | undefined { - // Handle Differential Expression Analysis workflow separately + // Handle Differential Expression Analysis workflow separately (special case - not in IWC yet) if (workflow.trsId === DIFFERENTIAL_EXPRESSION_ANALYSIS.trsId) { return getDEConfiguredValues(configuredInput); } - // Handle LMLS workflows (SEQUENCE scope with no parameters) + // Handle LMLS workflows separately (special case - not in IWC yet) if ( workflow.trsId === LOGAN_SEARCH.trsId || workflow.trsId === LEXICMAP.trsId ) { - return getLMLSConfiguredValues(); + return getSequenceScopeConfiguredValues(); } - return getStandardConfiguredValues(configuredInput, workflow); + // For all other workflows, use scope-based logic + switch (workflow.scope) { + case "ASSEMBLY": + return getAssemblyScopeConfiguredValues(configuredInput, workflow); + case "ORGANISM": + return getOrganismScopeConfiguredValues(); + case "SEQUENCE": + return getSequenceScopeConfiguredValues(); + } } /** diff --git a/app/views/WorkflowsView/utils.ts b/app/views/WorkflowsView/utils.ts index d47e53689..abfff463f 100644 --- a/app/views/WorkflowsView/utils.ts +++ b/app/views/WorkflowsView/utils.ts @@ -56,18 +56,21 @@ function getTaxonomicLevelRealm(assembly: Assembly | undefined): string { * Filters out workflows that have no compatible assemblies for the current site. * Differential Expression Analysis is always included as an interim measure. * LMLS workflows (Logan Search and Lexicmap) are included when the 'lmls' feature flag is enabled. + * Flu workflow is included when the 'flu' feature flag is enabled. * Each workflow includes the properties of the workflow itself along with the name of its category and the compatible assembly (if any). * @param workflowCategories - An array of workflow categories, each containing an array of workflows. * @param mappings - Workflow-assembly mappings for the current site. * @param organisms - Organisms. * @param isLmlsEnabled - Whether the 'lmls' feature flag is enabled. + * @param isFluEnabled - Whether the 'flu' feature flag is enabled. * @returns An array of workflows, where each workflow is a combination of a workflow and its category name. */ export function getWorkflows( workflowCategories: WorkflowCategory[], mappings: WorkflowAssemblyMapping[], organisms: Organism[], - isLmlsEnabled = false + isLmlsEnabled = false, + isFluEnabled = false ): WorkflowEntity[] { const workflows: WorkflowEntity[] = []; @@ -83,6 +86,14 @@ export function getWorkflows( for (const category of workflowCategories) { if (!category.workflows) continue; for (const workflow of category.workflows) { + // Skip flu workflow - it's handled separately with feature flag below. + if ( + workflow.trsId === + "#workflow/github.com/iwc-workflows/influenza-isolates-consensus-and-subtyping/main/versions/v0.3" + ) { + continue; + } + // Skip workflows with no compatible assemblies. if (!workflowsWithAssemblies.has(workflow.trsId)) { continue; @@ -128,6 +139,27 @@ export function getWorkflows( } as WorkflowEntity); } + // Add flu workflow if feature flag is enabled. + if (isFluEnabled) { + const fluWorkflow = workflowCategories + .flatMap((c) => c.workflows) + .find( + (w) => + w.trsId === + "#workflow/github.com/iwc-workflows/influenza-isolates-consensus-and-subtyping/main/versions/v0.3" + ); + + if (fluWorkflow) { + workflows.push({ + ...fluWorkflow, + assembly: mapAssembly(undefined), + category: "Consensus sequences", + scope: String(fluWorkflow.scope), + taxonomyId: fluWorkflow.taxonomyId ?? "Any", + } as WorkflowEntity); + } + } + return workflows; } diff --git a/app/views/WorkflowsView/workflowsView.tsx b/app/views/WorkflowsView/workflowsView.tsx index 5a04dbef1..9c613b931 100644 --- a/app/views/WorkflowsView/workflowsView.tsx +++ b/app/views/WorkflowsView/workflowsView.tsx @@ -19,6 +19,7 @@ import { Organism } from "./types"; export const WorkflowsView = (): JSX.Element => { const workflowCategories = getWorkflowCategories(); const organisms = getOrganisms(); + const isFluEnabled = useFeatureFlag("flu"); const isLmlsEnabled = useFeatureFlag("lmls"); const [mappings, setMappings] = useState( null @@ -40,9 +41,15 @@ export const WorkflowsView = (): JSX.Element => { const workflows = useMemo( () => mappings - ? getWorkflows(workflowCategories, mappings, organisms, isLmlsEnabled) + ? getWorkflows( + workflowCategories, + mappings, + organisms, + isLmlsEnabled, + isFluEnabled + ) : [], - [isLmlsEnabled, mappings, organisms, workflowCategories] + [isFluEnabled, isLmlsEnabled, mappings, organisms, workflowCategories] ); return ; diff --git a/catalog/py_package/catalog_build/generated_schema/schema.py b/catalog/py_package/catalog_build/generated_schema/schema.py index 02d0d9d1a..8eda83229 100644 --- a/catalog/py_package/catalog_build/generated_schema/schema.py +++ b/catalog/py_package/catalog_build/generated_schema/schema.py @@ -1,32 +1,13 @@ -from __future__ import annotations +from __future__ import annotations import re import sys -from datetime import ( - date, - datetime, - time -) -from decimal import Decimal -from enum import Enum -from typing import ( - Any, - ClassVar, - Dict, - List, - Literal, - Optional, - Union -) - -from pydantic import ( - BaseModel, - ConfigDict, - Field, - RootModel, - field_validator -) +from datetime import date, datetime, time +from decimal import Decimal +from enum import Enum +from typing import Any, ClassVar, Dict, List, Literal, Optional, Union +from pydantic import BaseModel, ConfigDict, Field, RootModel, field_validator metamodel_version = "None" version = "None" @@ -34,52 +15,62 @@ class ConfiguredBaseModel(BaseModel): model_config = ConfigDict( - validate_assignment = True, - validate_default = True, - extra = "forbid", - arbitrary_types_allowed = True, - use_enum_values = True, - strict = False, + validate_assignment=True, + validate_default=True, + extra="forbid", + arbitrary_types_allowed=True, + use_enum_values=True, + strict=False, ) pass - - class LinkMLMeta(RootModel): root: Dict[str, Any] = {} model_config = ConfigDict(frozen=True) - def __getattr__(self, key:str): + def __getattr__(self, key: str): return getattr(self.root, key) - def __getitem__(self, key:str): + def __getitem__(self, key: str): return self.root[key] - def __setitem__(self, key:str, value): + def __setitem__(self, key: str, value): self.root[key] = value - def __contains__(self, key:str) -> bool: + def __contains__(self, key: str) -> bool: return key in self.root -linkml_meta = LinkMLMeta({'default_prefix': 'https://github.com/galaxyproject/brc-analytics/blob/main/catalog/py_package/catalog_build/schema/schema.yaml#', - 'description': 'Combined source data schemas.', - 'id': 'https://github.com/galaxyproject/brc-analytics/blob/main/catalog/py_package/catalog_build/schema/schema.yaml#', - 'imports': ['./assemblies', - './organisms', - './outbreaks', - './workflow_categories', - './workflows'], - 'name': 'schema', - 'prefixes': {'linkml': {'prefix_prefix': 'linkml', - 'prefix_reference': 'https://w3id.org/linkml/'}}, - 'source_file': '/home/danielle/Documents/brc-analytics/brc-analytics/catalog/py_package/catalog_build/schema_utils/../schema/schema.yaml'} ) +linkml_meta = LinkMLMeta( + { + "default_prefix": "https://github.com/galaxyproject/brc-analytics/blob/main/catalog/py_package/catalog_build/schema/schema.yaml#", + "description": "Combined source data schemas.", + "id": "https://github.com/galaxyproject/brc-analytics/blob/main/catalog/py_package/catalog_build/schema/schema.yaml#", + "imports": [ + "./assemblies", + "./organisms", + "./outbreaks", + "./workflow_categories", + "./workflows", + ], + "name": "schema", + "prefixes": { + "linkml": { + "prefix_prefix": "linkml", + "prefix_reference": "https://w3id.org/linkml/", + } + }, + "source_file": "/home/danielle/Documents/brc-analytics/brc-analytics/catalog/py_package/catalog_build/schema_utils/../schema/schema.yaml", + } +) + class OrganismPloidy(str, Enum): """ Possible ploidies of an organism. """ + DIPLOID = "DIPLOID" HAPLOID = "HAPLOID" POLYPLOID = "POLYPLOID" @@ -89,6 +80,7 @@ class OutbreakPriority(str, Enum): """ Possible priorities of an outbreak. """ + HIGHEST = "HIGHEST" CRITICAL = "CRITICAL" HIGH = "HIGH" @@ -100,6 +92,7 @@ class OutbreakResourceType(str, Enum): """ Possible types of an outbreak resource. """ + PUBLICATION = "PUBLICATION" REFERENCE = "REFERENCE" NEWS = "NEWS" @@ -113,6 +106,7 @@ class WorkflowCategoryId(str, Enum): """ Set of IDs of workflow categories. """ + VARIANT_CALLING = "VARIANT_CALLING" TRANSCRIPTOMICS = "TRANSCRIPTOMICS" REGULATION = "REGULATION" @@ -126,9 +120,10 @@ class WorkflowCategoryId(str, Enum): class CollectionType(str, Enum): """ - Galaxy collection types supported for collection_spec in workflow parameters. -Currently only 'list' collections are supported, which represent a simple ordered list of datasets. + Galaxy collection types supported for collection_spec in workflow parameters. + Currently only 'list' collections are supported, which represent a simple ordered list of datasets. """ + # A simple ordered list of datasets. Each element in the collection is a separate dataset. list = "list" @@ -137,6 +132,7 @@ class WorkflowParameterVariable(str, Enum): """ Possible variables that can be inserted into workflow parameters. """ + ASSEMBLY_ID = "ASSEMBLY_ID" ASSEMBLY_FASTA_URL = "ASSEMBLY_FASTA_URL" FASTA_COLLECTION = "FASTA_COLLECTION" @@ -149,6 +145,7 @@ class WorkflowPloidy(str, Enum): """ Possible ploidies supported by workflows. """ + ANY = "ANY" DIPLOID = "DIPLOID" HAPLOID = "HAPLOID" @@ -159,6 +156,7 @@ class WorkflowScope(str, Enum): """ The scope level at which a workflow operates, determining its display context and required inputs. """ + # Workflow operates on a specific genome assembly and requires assembly selection as the first step. ASSEMBLY = "ASSEMBLY" # Workflow operates at the organism level, either requiring no specific assembly or working across multiple assemblies. @@ -171,6 +169,7 @@ class LibraryLayout(str, Enum): """ Enumeration of possible library layouts for sequencing data. """ + # Paired-end sequencing reads PAIRED = "PAIRED" # Single-end sequencing reads @@ -181,6 +180,7 @@ class LibrarySource(str, Enum): """ Enumeration of possible library sources for sequencing data. """ + # Genomic DNA (includes PCR products from genomic DNA) GENOMIC = "GENOMIC" # Genomic DNA from a single cell @@ -205,6 +205,7 @@ class LibraryStrategy(str, Enum): """ Enumeration of possible library strategies for sequencing data. """ + # Whole genome sequencing WGS = "WGS" # Whole genome amplification @@ -289,100 +290,261 @@ class LibraryStrategy(str, Enum): OTHER = "OTHER" - class Assemblies(ConfiguredBaseModel): """ Root object containing a collection of genomic assembly definitions for the BRC Analytics platform. """ - linkml_meta: ClassVar[LinkMLMeta] = LinkMLMeta({'from_schema': 'https://github.com/galaxyproject/brc-analytics/blob/main/catalog/py_package/catalog_build/schema/assemblies.yaml#', - 'tree_root': True}) - assemblies: List[Assembly] = Field(default=..., description="""Collection of genomic assembly entries that will be available for analysis in the BRC Analytics platform.""", json_schema_extra = { "linkml_meta": {'alias': 'assemblies', 'domain_of': ['Assemblies']} }) + linkml_meta: ClassVar[LinkMLMeta] = LinkMLMeta( + { + "from_schema": "https://github.com/galaxyproject/brc-analytics/blob/main/catalog/py_package/catalog_build/schema/assemblies.yaml#", + "tree_root": True, + } + ) + + assemblies: List[Assembly] = Field( + default=..., + description="""Collection of genomic assembly entries that will be available for analysis in the BRC Analytics platform.""", + json_schema_extra={ + "linkml_meta": {"alias": "assemblies", "domain_of": ["Assemblies"]} + }, + ) class Assembly(ConfiguredBaseModel): """ Definition of a genomic assembly with its unique identifier. """ - linkml_meta: ClassVar[LinkMLMeta] = LinkMLMeta({'from_schema': 'https://github.com/galaxyproject/brc-analytics/blob/main/catalog/py_package/catalog_build/schema/assemblies.yaml#'}) - accession: str = Field(default=..., description="""The unique accession identifier for the assembly (e.g., GCA_000001405.28 for GRCh38), used to retrieve the assembly data from public repositories.""", json_schema_extra = { "linkml_meta": {'alias': 'accession', 'domain_of': ['Assembly']} }) + linkml_meta: ClassVar[LinkMLMeta] = LinkMLMeta( + { + "from_schema": "https://github.com/galaxyproject/brc-analytics/blob/main/catalog/py_package/catalog_build/schema/assemblies.yaml#" + } + ) + + accession: str = Field( + default=..., + description="""The unique accession identifier for the assembly (e.g., GCA_000001405.28 for GRCh38), used to retrieve the assembly data from public repositories.""", + json_schema_extra={ + "linkml_meta": {"alias": "accession", "domain_of": ["Assembly"]} + }, + ) class Organisms(ConfiguredBaseModel): """ Root object containing a collection of organism definitions for the BRC Analytics platform. """ - linkml_meta: ClassVar[LinkMLMeta] = LinkMLMeta({'from_schema': 'https://github.com/galaxyproject/brc-analytics/blob/main/catalog/py_package/catalog_build/schema/organisms.yaml#', - 'tree_root': True}) - organisms: List[Organism] = Field(default=..., description="""Collection of organism entries that will be available in the BRC Analytics platform.""", json_schema_extra = { "linkml_meta": {'alias': 'organisms', 'domain_of': ['Organisms']} }) + linkml_meta: ClassVar[LinkMLMeta] = LinkMLMeta( + { + "from_schema": "https://github.com/galaxyproject/brc-analytics/blob/main/catalog/py_package/catalog_build/schema/organisms.yaml#", + "tree_root": True, + } + ) + + organisms: List[Organism] = Field( + default=..., + description="""Collection of organism entries that will be available in the BRC Analytics platform.""", + json_schema_extra={ + "linkml_meta": {"alias": "organisms", "domain_of": ["Organisms"]} + }, + ) class Organism(ConfiguredBaseModel): """ Definition of an organism with its taxonomic and genetic characteristics. """ - linkml_meta: ClassVar[LinkMLMeta] = LinkMLMeta({'from_schema': 'https://github.com/galaxyproject/brc-analytics/blob/main/catalog/py_package/catalog_build/schema/organisms.yaml#'}) - taxonomy_id: int = Field(default=..., description="""An NCBI Taxonomy ID at rank 'species'.""", json_schema_extra = { "linkml_meta": {'alias': 'taxonomy_id', 'domain_of': ['Organism', 'Outbreak', 'Workflow']} }) - ploidy: List[OrganismPloidy] = Field(default=..., description="""The possible ploidy states (number of chromosome sets) that the organism may have, which determines compatible workflows.""", json_schema_extra = { "linkml_meta": {'alias': 'ploidy', 'domain_of': ['Organism', 'Workflow']} }) + linkml_meta: ClassVar[LinkMLMeta] = LinkMLMeta( + { + "from_schema": "https://github.com/galaxyproject/brc-analytics/blob/main/catalog/py_package/catalog_build/schema/organisms.yaml#" + } + ) + + taxonomy_id: int = Field( + default=..., + description="""An NCBI Taxonomy ID at rank 'species'.""", + json_schema_extra={ + "linkml_meta": { + "alias": "taxonomy_id", + "domain_of": ["Organism", "Outbreak", "Workflow"], + } + }, + ) + ploidy: List[OrganismPloidy] = Field( + default=..., + description="""The possible ploidy states (number of chromosome sets) that the organism may have, which determines compatible workflows.""", + json_schema_extra={ + "linkml_meta": {"alias": "ploidy", "domain_of": ["Organism", "Workflow"]} + }, + ) class Outbreaks(ConfiguredBaseModel): """ Root object containing a collection of pathogen definitions for the BRC Analytics platform to highlight as outbreaks/priority pathogens. """ - linkml_meta: ClassVar[LinkMLMeta] = LinkMLMeta({'from_schema': 'https://github.com/galaxyproject/brc-analytics/blob/main/catalog/py_package/catalog_build/schema/outbreaks.yaml#', - 'tree_root': True}) - outbreaks: List[Outbreak] = Field(default=..., description="""Collection of pathogen entries that will be displayed in the BRC Analytics platform as outbreaks/priority pathogens.""", json_schema_extra = { "linkml_meta": {'alias': 'outbreaks', 'domain_of': ['Outbreaks']} }) + linkml_meta: ClassVar[LinkMLMeta] = LinkMLMeta( + { + "from_schema": "https://github.com/galaxyproject/brc-analytics/blob/main/catalog/py_package/catalog_build/schema/outbreaks.yaml#", + "tree_root": True, + } + ) + + outbreaks: List[Outbreak] = Field( + default=..., + description="""Collection of pathogen entries that will be displayed in the BRC Analytics platform as outbreaks/priority pathogens.""", + json_schema_extra={ + "linkml_meta": {"alias": "outbreaks", "domain_of": ["Outbreaks"]} + }, + ) class Outbreak(ConfiguredBaseModel): """ Definition of a priority pathogen with its taxonomic classification, priority level, and associated resources. """ - linkml_meta: ClassVar[LinkMLMeta] = LinkMLMeta({'from_schema': 'https://github.com/galaxyproject/brc-analytics/blob/main/catalog/py_package/catalog_build/schema/outbreaks.yaml#'}) - name: str = Field(default=..., description="""The display name of the pathogen as it will appear in the BRC Analytics interface.""", json_schema_extra = { "linkml_meta": {'alias': 'name', - 'domain_of': ['Outbreak', 'WorkflowCategory', 'WorkflowCollectionSpec']} }) - taxonomy_id: int = Field(default=..., description="""The NCBI Taxonomy ID for the pathogen. Used to link to relevant genomic data and workflows.""", json_schema_extra = { "linkml_meta": {'alias': 'taxonomy_id', 'domain_of': ['Organism', 'Outbreak', 'Workflow']} }) - priority: OutbreakPriority = Field(default=..., description="""The priority level of the pathogen, which determines its visibility and prominence in the BRC Analytics interface.""", json_schema_extra = { "linkml_meta": {'alias': 'priority', 'domain_of': ['Outbreak']} }) - resources: List[OutbreakResource] = Field(default=..., description="""Collection of external resources (references, tools, databases) related to the pathogen.""", json_schema_extra = { "linkml_meta": {'alias': 'resources', 'domain_of': ['Outbreak']} }) - description: MarkdownFileReference = Field(default=..., description="""Reference to a markdown file containing detailed information about the pathogen.""", json_schema_extra = { "linkml_meta": {'alias': 'description', - 'domain_of': ['Outbreak', 'WorkflowCategory', 'WorkflowDataRequirements']} }) - active: bool = Field(default=..., description="""Boolean flag that determines if the pathogen should be included in the BRC Analytics interface. Used to manage visibility as pathogen relevance changes over time.""", json_schema_extra = { "linkml_meta": {'alias': 'active', 'domain_of': ['Outbreak', 'Workflow']} }) - highlight_descendant_taxonomy_ids: Optional[List[int]] = Field(default=None, description="""List of NCBI Taxonomy IDs for descendant taxa (e.g., specific strains or serotypes) that should be highlighted within the outbreak category.""", json_schema_extra = { "linkml_meta": {'alias': 'highlight_descendant_taxonomy_ids', 'domain_of': ['Outbreak']} }) + linkml_meta: ClassVar[LinkMLMeta] = LinkMLMeta( + { + "from_schema": "https://github.com/galaxyproject/brc-analytics/blob/main/catalog/py_package/catalog_build/schema/outbreaks.yaml#" + } + ) + + name: str = Field( + default=..., + description="""The display name of the pathogen as it will appear in the BRC Analytics interface.""", + json_schema_extra={ + "linkml_meta": { + "alias": "name", + "domain_of": ["Outbreak", "WorkflowCategory", "WorkflowCollectionSpec"], + } + }, + ) + taxonomy_id: int = Field( + default=..., + description="""The NCBI Taxonomy ID for the pathogen. Used to link to relevant genomic data and workflows.""", + json_schema_extra={ + "linkml_meta": { + "alias": "taxonomy_id", + "domain_of": ["Organism", "Outbreak", "Workflow"], + } + }, + ) + priority: OutbreakPriority = Field( + default=..., + description="""The priority level of the pathogen, which determines its visibility and prominence in the BRC Analytics interface.""", + json_schema_extra={ + "linkml_meta": {"alias": "priority", "domain_of": ["Outbreak"]} + }, + ) + resources: List[OutbreakResource] = Field( + default=..., + description="""Collection of external resources (references, tools, databases) related to the pathogen.""", + json_schema_extra={ + "linkml_meta": {"alias": "resources", "domain_of": ["Outbreak"]} + }, + ) + description: MarkdownFileReference = Field( + default=..., + description="""Reference to a markdown file containing detailed information about the pathogen.""", + json_schema_extra={ + "linkml_meta": { + "alias": "description", + "domain_of": [ + "Outbreak", + "WorkflowCategory", + "WorkflowDataRequirements", + ], + } + }, + ) + active: bool = Field( + default=..., + description="""Boolean flag that determines if the pathogen should be included in the BRC Analytics interface. Used to manage visibility as pathogen relevance changes over time.""", + json_schema_extra={ + "linkml_meta": {"alias": "active", "domain_of": ["Outbreak", "Workflow"]} + }, + ) + highlight_descendant_taxonomy_ids: Optional[List[int]] = Field( + default=None, + description="""List of NCBI Taxonomy IDs for descendant taxa (e.g., specific strains or serotypes) that should be highlighted within the outbreak category.""", + json_schema_extra={ + "linkml_meta": { + "alias": "highlight_descendant_taxonomy_ids", + "domain_of": ["Outbreak"], + } + }, + ) class OutbreakResource(ConfiguredBaseModel): """ Definition of an external resource (reference, tool, database) associated with a priority pathogen. """ - linkml_meta: ClassVar[LinkMLMeta] = LinkMLMeta({'from_schema': 'https://github.com/galaxyproject/brc-analytics/blob/main/catalog/py_package/catalog_build/schema/outbreaks.yaml#'}) - url: str = Field(default=..., description="""The complete URL (including http/https protocol) to the external resource.""", json_schema_extra = { "linkml_meta": {'alias': 'url', 'domain_of': ['OutbreakResource', 'WorkflowUrlSpec']} }) - title: str = Field(default=..., description="""The display title for the resource link as it will appear in the BRC Analytics interface.""", json_schema_extra = { "linkml_meta": {'alias': 'title', 'domain_of': ['OutbreakResource']} }) - type: OutbreakResourceType = Field(default=..., description="""The category or type of the resource (e.g., REFERENCE, TOOL, DATABASE), which determines how it is displayed and organized.""", json_schema_extra = { "linkml_meta": {'alias': 'type', 'domain_of': ['OutbreakResource']} }) + linkml_meta: ClassVar[LinkMLMeta] = LinkMLMeta( + { + "from_schema": "https://github.com/galaxyproject/brc-analytics/blob/main/catalog/py_package/catalog_build/schema/outbreaks.yaml#" + } + ) + + url: str = Field( + default=..., + description="""The complete URL (including http/https protocol) to the external resource.""", + json_schema_extra={ + "linkml_meta": { + "alias": "url", + "domain_of": ["OutbreakResource", "WorkflowUrlSpec"], + } + }, + ) + title: str = Field( + default=..., + description="""The display title for the resource link as it will appear in the BRC Analytics interface.""", + json_schema_extra={ + "linkml_meta": {"alias": "title", "domain_of": ["OutbreakResource"]} + }, + ) + type: OutbreakResourceType = Field( + default=..., + description="""The category or type of the resource (e.g., REFERENCE, TOOL, DATABASE), which determines how it is displayed and organized.""", + json_schema_extra={ + "linkml_meta": {"alias": "type", "domain_of": ["OutbreakResource"]} + }, + ) class MarkdownFileReference(ConfiguredBaseModel): """ A reference to a markdown file containing detailed content about a priority pathogen. """ - linkml_meta: ClassVar[LinkMLMeta] = LinkMLMeta({'from_schema': 'https://github.com/galaxyproject/brc-analytics/blob/main/catalog/py_package/catalog_build/schema/outbreaks.yaml#'}) - path: str = Field(default=..., description="""Relative path to the markdown file from the project root. Must end with .md extension.""", json_schema_extra = { "linkml_meta": {'alias': 'path', 'domain_of': ['MarkdownFileReference']} }) + linkml_meta: ClassVar[LinkMLMeta] = LinkMLMeta( + { + "from_schema": "https://github.com/galaxyproject/brc-analytics/blob/main/catalog/py_package/catalog_build/schema/outbreaks.yaml#" + } + ) + + path: str = Field( + default=..., + description="""Relative path to the markdown file from the project root. Must end with .md extension.""", + json_schema_extra={ + "linkml_meta": {"alias": "path", "domain_of": ["MarkdownFileReference"]} + }, + ) - @field_validator('path') + @field_validator("path") def pattern_path(cls, v): - pattern=re.compile(r".*\.md$") - if isinstance(v,list): + pattern = re.compile(r".*\.md$") + if isinstance(v, list): for element in v: if isinstance(v, str) and not pattern.match(element): raise ValueError(f"Invalid path format: {element}") - elif isinstance(v,str): + elif isinstance(v, str): if not pattern.match(v): raise ValueError(f"Invalid path format: {v}") return v @@ -392,65 +554,242 @@ class WorkflowCategories(ConfiguredBaseModel): """ Root object containing a collection of workflow category definitions used to organize workflows in the BRC Analytics platform. """ - linkml_meta: ClassVar[LinkMLMeta] = LinkMLMeta({'from_schema': 'https://github.com/galaxyproject/brc-analytics/blob/main/catalog/py_package/catalog_build/schema/workflow_categories.yaml#', - 'tree_root': True}) - workflow_categories: List[WorkflowCategory] = Field(default=..., description="""Collection of workflow category entries that will be used to group and organize workflows in the BRC Analytics interface.""", json_schema_extra = { "linkml_meta": {'alias': 'workflow_categories', 'domain_of': ['WorkflowCategories']} }) + linkml_meta: ClassVar[LinkMLMeta] = LinkMLMeta( + { + "from_schema": "https://github.com/galaxyproject/brc-analytics/blob/main/catalog/py_package/catalog_build/schema/workflow_categories.yaml#", + "tree_root": True, + } + ) + + workflow_categories: List[WorkflowCategory] = Field( + default=..., + description="""Collection of workflow category entries that will be used to group and organize workflows in the BRC Analytics interface.""", + json_schema_extra={ + "linkml_meta": { + "alias": "workflow_categories", + "domain_of": ["WorkflowCategories"], + } + }, + ) class WorkflowCategory(ConfiguredBaseModel): """ Definition of a workflow category used to group related workflows for organization and display purposes. """ - linkml_meta: ClassVar[LinkMLMeta] = LinkMLMeta({'from_schema': 'https://github.com/galaxyproject/brc-analytics/blob/main/catalog/py_package/catalog_build/schema/workflow_categories.yaml#'}) - category: WorkflowCategoryId = Field(default=..., description="""The unique identifier for the workflow category, used to link workflows to their respective categories.""", json_schema_extra = { "linkml_meta": {'alias': 'category', 'domain_of': ['WorkflowCategory']} }) - name: str = Field(default=..., description="""The human-readable display name of the workflow category as it will appear in the BRC Analytics interface.""", json_schema_extra = { "linkml_meta": {'alias': 'name', - 'domain_of': ['Outbreak', 'WorkflowCategory', 'WorkflowCollectionSpec']} }) - description: str = Field(default=..., description="""A detailed description of the workflow category explaining its purpose and the types of workflows it contains.""", json_schema_extra = { "linkml_meta": {'alias': 'description', - 'domain_of': ['Outbreak', 'WorkflowCategory', 'WorkflowDataRequirements']} }) - show_coming_soon: bool = Field(default=..., description="""Boolean flag that determines whether to display a 'Coming Soon' indicator for this category in the BRC Analytics interface when workflows in this category are not yet available.""", json_schema_extra = { "linkml_meta": {'alias': 'show_coming_soon', 'domain_of': ['WorkflowCategory']} }) + linkml_meta: ClassVar[LinkMLMeta] = LinkMLMeta( + { + "from_schema": "https://github.com/galaxyproject/brc-analytics/blob/main/catalog/py_package/catalog_build/schema/workflow_categories.yaml#" + } + ) + + category: WorkflowCategoryId = Field( + default=..., + description="""The unique identifier for the workflow category, used to link workflows to their respective categories.""", + json_schema_extra={ + "linkml_meta": {"alias": "category", "domain_of": ["WorkflowCategory"]} + }, + ) + name: str = Field( + default=..., + description="""The human-readable display name of the workflow category as it will appear in the BRC Analytics interface.""", + json_schema_extra={ + "linkml_meta": { + "alias": "name", + "domain_of": ["Outbreak", "WorkflowCategory", "WorkflowCollectionSpec"], + } + }, + ) + description: str = Field( + default=..., + description="""A detailed description of the workflow category explaining its purpose and the types of workflows it contains.""", + json_schema_extra={ + "linkml_meta": { + "alias": "description", + "domain_of": [ + "Outbreak", + "WorkflowCategory", + "WorkflowDataRequirements", + ], + } + }, + ) + show_coming_soon: bool = Field( + default=..., + description="""Boolean flag that determines whether to display a 'Coming Soon' indicator for this category in the BRC Analytics interface when workflows in this category are not yet available.""", + json_schema_extra={ + "linkml_meta": { + "alias": "show_coming_soon", + "domain_of": ["WorkflowCategory"], + } + }, + ) class Workflows(ConfiguredBaseModel): """ Root object containing a collection of Galaxy workflow definitions for the BRC Analytics platform. """ - linkml_meta: ClassVar[LinkMLMeta] = LinkMLMeta({'from_schema': 'https://github.com/galaxyproject/brc-analytics/blob/main/catalog/py_package/catalog_build/schema/workflows.yaml#', - 'tree_root': True}) - workflows: List[Workflow] = Field(default=..., description="""Collection of workflow entries that will be available to users in the BRC Analytics platform.""", json_schema_extra = { "linkml_meta": {'alias': 'workflows', 'domain_of': ['Workflows']} }) + linkml_meta: ClassVar[LinkMLMeta] = LinkMLMeta( + { + "from_schema": "https://github.com/galaxyproject/brc-analytics/blob/main/catalog/py_package/catalog_build/schema/workflows.yaml#", + "tree_root": True, + } + ) + + workflows: List[Workflow] = Field( + default=..., + description="""Collection of workflow entries that will be available to users in the BRC Analytics platform.""", + json_schema_extra={ + "linkml_meta": {"alias": "workflows", "domain_of": ["Workflows"]} + }, + ) class Workflow(ConfiguredBaseModel): """ Definition of a Galaxy workflow with its metadata, parameters, and organism compatibility information. """ - linkml_meta: ClassVar[LinkMLMeta] = LinkMLMeta({'from_schema': 'https://github.com/galaxyproject/brc-analytics/blob/main/catalog/py_package/catalog_build/schema/workflows.yaml#'}) - trs_id: str = Field(default=..., description="""The Tool Repository Service (TRS) identifier for the workflow, used to locate and retrieve the workflow from a Galaxy server.""", json_schema_extra = { "linkml_meta": {'alias': 'trs_id', 'domain_of': ['Workflow']} }) - categories: List[WorkflowCategoryId] = Field(default=..., description="""List of category identifiers that this workflow belongs to, determining how it is organized and displayed in the BRC Analytics interface.""", json_schema_extra = { "linkml_meta": {'alias': 'categories', 'domain_of': ['Workflow']} }) - workflow_name: str = Field(default=..., description="""The human-readable display name of the workflow as it will appear in the BRC Analytics interface.""", json_schema_extra = { "linkml_meta": {'alias': 'workflow_name', 'domain_of': ['Workflow']} }) - workflow_description: str = Field(default=..., description="""A detailed description of the workflow's purpose, functionality, and expected outputs for users.""", json_schema_extra = { "linkml_meta": {'alias': 'workflow_description', 'domain_of': ['Workflow']} }) - ploidy: WorkflowPloidy = Field(default=..., description="""The ploidy state (number of chromosome sets) that this workflow is designed to work with, ensuring compatibility with organism data.""", json_schema_extra = { "linkml_meta": {'alias': 'ploidy', 'domain_of': ['Organism', 'Workflow']} }) - scope: Optional[WorkflowScope] = Field(default=None, description="""The scope level at which this workflow operates, determining where it is displayed in the UI and what the first configuration step should be. Defaults to ASSEMBLY for backward compatibility.""", json_schema_extra = { "linkml_meta": {'alias': 'scope', 'domain_of': ['Workflow']} }) - taxonomy_id: Optional[int] = Field(default=None, description="""The NCBI Taxonomy ID of the organism this workflow is designed for. If specified, the workflow will be available for all assemblies with this ID in their taxonomic lineage.""", json_schema_extra = { "linkml_meta": {'alias': 'taxonomy_id', 'domain_of': ['Organism', 'Outbreak', 'Workflow']} }) - parameters: List[WorkflowParameter] = Field(default=..., description="""Collection of input parameters that will be passed to the workflow when it is executed, including data sources and configuration options.""", json_schema_extra = { "linkml_meta": {'alias': 'parameters', 'domain_of': ['Workflow']} }) - active: bool = Field(default=..., description="""Boolean flag that determines if the workflow should be included in the BRC Analytics interface. Used to manage visibility of workflows that may be under development or deprecated.""", json_schema_extra = { "linkml_meta": {'alias': 'active', 'domain_of': ['Outbreak', 'Workflow']} }) - iwc_id: str = Field(default=..., description="""The Intergalactic Workflow Commission (IWC) identifier for the workflow, used to link to the workflow's page on the IWC website.""", json_schema_extra = { "linkml_meta": {'alias': 'iwc_id', 'domain_of': ['Workflow']} }) + linkml_meta: ClassVar[LinkMLMeta] = LinkMLMeta( + { + "from_schema": "https://github.com/galaxyproject/brc-analytics/blob/main/catalog/py_package/catalog_build/schema/workflows.yaml#" + } + ) + + trs_id: str = Field( + default=..., + description="""The Tool Repository Service (TRS) identifier for the workflow, used to locate and retrieve the workflow from a Galaxy server.""", + json_schema_extra={ + "linkml_meta": {"alias": "trs_id", "domain_of": ["Workflow"]} + }, + ) + categories: List[WorkflowCategoryId] = Field( + default=..., + description="""List of category identifiers that this workflow belongs to, determining how it is organized and displayed in the BRC Analytics interface.""", + json_schema_extra={ + "linkml_meta": {"alias": "categories", "domain_of": ["Workflow"]} + }, + ) + workflow_name: str = Field( + default=..., + description="""The human-readable display name of the workflow as it will appear in the BRC Analytics interface.""", + json_schema_extra={ + "linkml_meta": {"alias": "workflow_name", "domain_of": ["Workflow"]} + }, + ) + workflow_description: str = Field( + default=..., + description="""A detailed description of the workflow's purpose, functionality, and expected outputs for users.""", + json_schema_extra={ + "linkml_meta": {"alias": "workflow_description", "domain_of": ["Workflow"]} + }, + ) + ploidy: WorkflowPloidy = Field( + default=..., + description="""The ploidy state (number of chromosome sets) that this workflow is designed to work with, ensuring compatibility with organism data.""", + json_schema_extra={ + "linkml_meta": {"alias": "ploidy", "domain_of": ["Organism", "Workflow"]} + }, + ) + scope: Optional[WorkflowScope] = Field( + default=None, + description="""The scope level at which this workflow operates, determining where it is displayed in the UI and what the first configuration step should be. Defaults to ASSEMBLY for backward compatibility.""", + json_schema_extra={ + "linkml_meta": {"alias": "scope", "domain_of": ["Workflow"]} + }, + ) + taxonomy_id: Optional[int] = Field( + default=None, + description="""The NCBI Taxonomy ID of the organism this workflow is designed for. If specified, the workflow will be available for all assemblies with this ID in their taxonomic lineage.""", + json_schema_extra={ + "linkml_meta": { + "alias": "taxonomy_id", + "domain_of": ["Organism", "Outbreak", "Workflow"], + } + }, + ) + parameters: List[WorkflowParameter] = Field( + default=..., + description="""Collection of input parameters that will be passed to the workflow when it is executed, including data sources and configuration options.""", + json_schema_extra={ + "linkml_meta": {"alias": "parameters", "domain_of": ["Workflow"]} + }, + ) + active: bool = Field( + default=..., + description="""Boolean flag that determines if the workflow should be included in the BRC Analytics interface. Used to manage visibility of workflows that may be under development or deprecated.""", + json_schema_extra={ + "linkml_meta": {"alias": "active", "domain_of": ["Outbreak", "Workflow"]} + }, + ) + iwc_id: str = Field( + default=..., + description="""The Intergalactic Workflow Commission (IWC) identifier for the workflow, used to link to the workflow's page on the IWC website.""", + json_schema_extra={ + "linkml_meta": {"alias": "iwc_id", "domain_of": ["Workflow"]} + }, + ) class WorkflowDataRequirements(ConfiguredBaseModel): """ Specification of data requirements for a workflow parameter, such as library strategy and layout. """ - linkml_meta: ClassVar[LinkMLMeta] = LinkMLMeta({'from_schema': 'https://github.com/galaxyproject/brc-analytics/blob/main/catalog/py_package/catalog_build/schema/workflows.yaml#'}) - library_strategy: Optional[List[LibraryStrategy]] = Field(default=None, description="""The library strategy values that are acceptable for this parameter (e.g., 'WGS', 'RNA-Seq').""", json_schema_extra = { "linkml_meta": {'alias': 'library_strategy', 'domain_of': ['WorkflowDataRequirements']} }) - library_layout: Optional[LibraryLayout] = Field(default=None, description="""The library layout that is required for this parameter (e.g., 'PAIRED', 'SINGLE').""", json_schema_extra = { "linkml_meta": {'alias': 'library_layout', 'domain_of': ['WorkflowDataRequirements']} }) - library_source: Optional[List[LibrarySource]] = Field(default=None, description="""The library source values that are acceptable for this parameter (e.g., 'GENOMIC', 'TRANSCRIPTOMIC SINGLE CELL').""", json_schema_extra = { "linkml_meta": {'alias': 'library_source', 'domain_of': ['WorkflowDataRequirements']} }) - description: Optional[str] = Field(default=None, description="""A descriptive text to provide additional context about the data requirements, useful for non-standard library strategies like 'OTHER'.""", json_schema_extra = { "linkml_meta": {'alias': 'description', - 'domain_of': ['Outbreak', 'WorkflowCategory', 'WorkflowDataRequirements']} }) + linkml_meta: ClassVar[LinkMLMeta] = LinkMLMeta( + { + "from_schema": "https://github.com/galaxyproject/brc-analytics/blob/main/catalog/py_package/catalog_build/schema/workflows.yaml#" + } + ) + + library_strategy: Optional[List[LibraryStrategy]] = Field( + default=None, + description="""The library strategy values that are acceptable for this parameter (e.g., 'WGS', 'RNA-Seq').""", + json_schema_extra={ + "linkml_meta": { + "alias": "library_strategy", + "domain_of": ["WorkflowDataRequirements"], + } + }, + ) + library_layout: Optional[LibraryLayout] = Field( + default=None, + description="""The library layout that is required for this parameter (e.g., 'PAIRED', 'SINGLE').""", + json_schema_extra={ + "linkml_meta": { + "alias": "library_layout", + "domain_of": ["WorkflowDataRequirements"], + } + }, + ) + library_source: Optional[List[LibrarySource]] = Field( + default=None, + description="""The library source values that are acceptable for this parameter (e.g., 'GENOMIC', 'TRANSCRIPTOMIC SINGLE CELL').""", + json_schema_extra={ + "linkml_meta": { + "alias": "library_source", + "domain_of": ["WorkflowDataRequirements"], + } + }, + ) + description: Optional[str] = Field( + default=None, + description="""A descriptive text to provide additional context about the data requirements, useful for non-standard library strategies like 'OTHER'.""", + json_schema_extra={ + "linkml_meta": { + "alias": "description", + "domain_of": [ + "Outbreak", + "WorkflowCategory", + "WorkflowDataRequirements", + ], + } + }, + ) class WorkflowCollectionSpec(ConfiguredBaseModel): @@ -473,39 +812,156 @@ class WorkflowCollectionSpec(ConfiguredBaseModel): md5: def456... ``` """ - linkml_meta: ClassVar[LinkMLMeta] = LinkMLMeta({'from_schema': 'https://github.com/galaxyproject/brc-analytics/blob/main/catalog/py_package/catalog_build/schema/workflows.yaml#'}) - collection_type: CollectionType = Field(default=..., description="""The type of Galaxy collection to create. Currently only 'list' is supported. Determines the structure of the collection.""", json_schema_extra = { "linkml_meta": {'alias': 'collection_type', 'domain_of': ['WorkflowCollectionSpec']} }) - elements: List[WorkflowUrlSpec] = Field(default=..., description="""Array of URL specifications that will become elements in the collection. Each element represents a file to include in the collection. Must contain at least one element.""", min_length=1, json_schema_extra = { "linkml_meta": {'alias': 'elements', 'domain_of': ['WorkflowCollectionSpec']} }) - name: Optional[str] = Field(default=None, description="""Optional identifier for the collection, used as the collection name in Galaxy. If not provided, defaults to 'Collection'.""", json_schema_extra = { "linkml_meta": {'alias': 'name', - 'domain_of': ['Outbreak', 'WorkflowCategory', 'WorkflowCollectionSpec']} }) + linkml_meta: ClassVar[LinkMLMeta] = LinkMLMeta( + { + "from_schema": "https://github.com/galaxyproject/brc-analytics/blob/main/catalog/py_package/catalog_build/schema/workflows.yaml#" + } + ) + + collection_type: CollectionType = Field( + default=..., + description="""The type of Galaxy collection to create. Currently only 'list' is supported. Determines the structure of the collection.""", + json_schema_extra={ + "linkml_meta": { + "alias": "collection_type", + "domain_of": ["WorkflowCollectionSpec"], + } + }, + ) + elements: List[WorkflowUrlSpec] = Field( + default=..., + description="""Array of URL specifications that will become elements in the collection. Each element represents a file to include in the collection. Must contain at least one element.""", + min_length=1, + json_schema_extra={ + "linkml_meta": { + "alias": "elements", + "domain_of": ["WorkflowCollectionSpec"], + } + }, + ) + name: Optional[str] = Field( + default=None, + description="""Optional identifier for the collection, used as the collection name in Galaxy. If not provided, defaults to 'Collection'.""", + json_schema_extra={ + "linkml_meta": { + "alias": "name", + "domain_of": ["Outbreak", "WorkflowCategory", "WorkflowCollectionSpec"], + } + }, + ) class WorkflowParameter(ConfiguredBaseModel): """ Definition of an input parameter for a Galaxy workflow, specifying how the parameter value should be determined when the workflow is executed. """ - linkml_meta: ClassVar[LinkMLMeta] = LinkMLMeta({'from_schema': 'https://github.com/galaxyproject/brc-analytics/blob/main/catalog/py_package/catalog_build/schema/workflows.yaml#'}) - key: str = Field(default=..., description="""The identifier for the parameter as expected by the Galaxy workflow, used to map the parameter value to the correct input.""", json_schema_extra = { "linkml_meta": {'alias': 'key', 'domain_of': ['WorkflowParameter']} }) - variable: Optional[WorkflowParameterVariable] = Field(default=None, description="""A predefined variable that will be substituted as the value of the parameter at runtime, such as assembly information.""", json_schema_extra = { "linkml_meta": {'alias': 'variable', 'domain_of': ['WorkflowParameter']} }) - collection_spec: Optional[WorkflowCollectionSpec] = Field(default=None, description="""A collection specification for the parameter, allowing multiple files from external sources to be provided as a Galaxy collection.""", json_schema_extra = { "linkml_meta": {'alias': 'collection_spec', 'domain_of': ['WorkflowParameter']} }) - url_spec: Optional[WorkflowUrlSpec] = Field(default=None, description="""A direct URL specification for the parameter, allowing for external data sources to be provided to the workflow.""", json_schema_extra = { "linkml_meta": {'alias': 'url_spec', 'domain_of': ['WorkflowParameter']} }) - data_requirements: Optional[WorkflowDataRequirements] = Field(default=None, description="""Specifications for the data requirements of this parameter, such as library strategy and layout.""", json_schema_extra = { "linkml_meta": {'alias': 'data_requirements', 'domain_of': ['WorkflowParameter']} }) - type_guide: Optional[Any] = Field(default=None, description="""Arbitrary data describing the expected type and format of the parameter, intended as a reference for catalog maintainers and not used in workflow execution.""", json_schema_extra = { "linkml_meta": {'alias': 'type_guide', 'domain_of': ['WorkflowParameter']} }) + linkml_meta: ClassVar[LinkMLMeta] = LinkMLMeta( + { + "from_schema": "https://github.com/galaxyproject/brc-analytics/blob/main/catalog/py_package/catalog_build/schema/workflows.yaml#" + } + ) + + key: str = Field( + default=..., + description="""The identifier for the parameter as expected by the Galaxy workflow, used to map the parameter value to the correct input.""", + json_schema_extra={ + "linkml_meta": {"alias": "key", "domain_of": ["WorkflowParameter"]} + }, + ) + variable: Optional[WorkflowParameterVariable] = Field( + default=None, + description="""A predefined variable that will be substituted as the value of the parameter at runtime, such as assembly information.""", + json_schema_extra={ + "linkml_meta": {"alias": "variable", "domain_of": ["WorkflowParameter"]} + }, + ) + collection_spec: Optional[WorkflowCollectionSpec] = Field( + default=None, + description="""A collection specification for the parameter, allowing multiple files from external sources to be provided as a Galaxy collection.""", + json_schema_extra={ + "linkml_meta": { + "alias": "collection_spec", + "domain_of": ["WorkflowParameter"], + } + }, + ) + url_spec: Optional[WorkflowUrlSpec] = Field( + default=None, + description="""A direct URL specification for the parameter, allowing for external data sources to be provided to the workflow.""", + json_schema_extra={ + "linkml_meta": {"alias": "url_spec", "domain_of": ["WorkflowParameter"]} + }, + ) + data_requirements: Optional[WorkflowDataRequirements] = Field( + default=None, + description="""Specifications for the data requirements of this parameter, such as library strategy and layout.""", + json_schema_extra={ + "linkml_meta": { + "alias": "data_requirements", + "domain_of": ["WorkflowParameter"], + } + }, + ) + type_guide: Optional[Any] = Field( + default=None, + description="""Arbitrary data describing the expected type and format of the parameter, intended as a reference for catalog maintainers and not used in workflow execution.""", + json_schema_extra={ + "linkml_meta": {"alias": "type_guide", "domain_of": ["WorkflowParameter"]} + }, + ) class WorkflowUrlSpec(ConfiguredBaseModel): """ Definition of a URL-based data source for a workflow parameter, typically used for reference data or external resources. """ - linkml_meta: ClassVar[LinkMLMeta] = LinkMLMeta({'from_schema': 'https://github.com/galaxyproject/brc-analytics/blob/main/catalog/py_package/catalog_build/schema/workflows.yaml#'}) - ext: str = Field(default=..., description="""The file extension of the resource at the URL, which determines how Galaxy will interpret the data (e.g., 'fasta', 'gff', 'tabular').""", json_schema_extra = { "linkml_meta": {'alias': 'ext', 'domain_of': ['WorkflowUrlSpec']} }) - src: str = Field(default=..., description="""The source type for the parameter, typically 'url' to indicate an external URL source rather than a Galaxy dataset or other source type.""", json_schema_extra = { "linkml_meta": {'alias': 'src', 'domain_of': ['WorkflowUrlSpec']} }) - url: str = Field(default=..., description="""The complete URL (including http/https protocol) to the external resource that will be used as input to the workflow.""", json_schema_extra = { "linkml_meta": {'alias': 'url', 'domain_of': ['OutbreakResource', 'WorkflowUrlSpec']} }) - db_key: Optional[str] = Field(default=None, description="""Optional database key (genome build) to associate with this file, used by Galaxy to link the file to a specific reference genome.""", json_schema_extra = { "linkml_meta": {'alias': 'db_key', 'domain_of': ['WorkflowUrlSpec']} }) - md5: Optional[str] = Field(default=None, description="""Optional MD5 checksum hash for file integrity verification.""", json_schema_extra = { "linkml_meta": {'alias': 'md5', 'domain_of': ['WorkflowUrlSpec']} }) + linkml_meta: ClassVar[LinkMLMeta] = LinkMLMeta( + { + "from_schema": "https://github.com/galaxyproject/brc-analytics/blob/main/catalog/py_package/catalog_build/schema/workflows.yaml#" + } + ) + + ext: str = Field( + default=..., + description="""The file extension of the resource at the URL, which determines how Galaxy will interpret the data (e.g., 'fasta', 'gff', 'tabular').""", + json_schema_extra={ + "linkml_meta": {"alias": "ext", "domain_of": ["WorkflowUrlSpec"]} + }, + ) + src: str = Field( + default=..., + description="""The source type for the parameter, typically 'url' to indicate an external URL source rather than a Galaxy dataset or other source type.""", + json_schema_extra={ + "linkml_meta": {"alias": "src", "domain_of": ["WorkflowUrlSpec"]} + }, + ) + url: str = Field( + default=..., + description="""The complete URL (including http/https protocol) to the external resource that will be used as input to the workflow.""", + json_schema_extra={ + "linkml_meta": { + "alias": "url", + "domain_of": ["OutbreakResource", "WorkflowUrlSpec"], + } + }, + ) + db_key: Optional[str] = Field( + default=None, + description="""Optional database key (genome build) to associate with this file, used by Galaxy to link the file to a specific reference genome.""", + json_schema_extra={ + "linkml_meta": {"alias": "db_key", "domain_of": ["WorkflowUrlSpec"]} + }, + ) + md5: Optional[str] = Field( + default=None, + description="""Optional MD5 checksum hash for file integrity verification.""", + json_schema_extra={ + "linkml_meta": {"alias": "md5", "domain_of": ["WorkflowUrlSpec"]} + }, + ) # Model rebuild @@ -526,4 +982,3 @@ class WorkflowUrlSpec(ConfiguredBaseModel): WorkflowCollectionSpec.model_rebuild() WorkflowParameter.model_rebuild() WorkflowUrlSpec.model_rebuild() - diff --git a/pages/_app.tsx b/pages/_app.tsx index f9a7c43bb..3ef3918be 100644 --- a/pages/_app.tsx +++ b/pages/_app.tsx @@ -46,7 +46,7 @@ export type AppPropsWithComponent = AppProps & { pageProps: PageProps; }; -setFeatureFlags(["assistant", "lmls"]); +setFeatureFlags(["assistant", "flu", "lmls"]); const queryClient = new QueryClient(); From 1b1a75d4b6bc1ca78a9f1248ea39fb6b8ad2d646 Mon Sep 17 00:00:00 2001 From: Danielle Callan Date: Thu, 2 Apr 2026 23:45:55 -0400 Subject: [PATCH 4/7] feat: add tests for refactored getConfiguredValues --- .../getConfiguredValues.scope.test.ts | 258 ++++++++++++++++++ 1 file changed, 258 insertions(+) create mode 100644 tests/components/configureWorkflowInputs/getConfiguredValues.scope.test.ts diff --git a/tests/components/configureWorkflowInputs/getConfiguredValues.scope.test.ts b/tests/components/configureWorkflowInputs/getConfiguredValues.scope.test.ts new file mode 100644 index 000000000..9af307f80 --- /dev/null +++ b/tests/components/configureWorkflowInputs/getConfiguredValues.scope.test.ts @@ -0,0 +1,258 @@ +import type { Workflow } from "../../../app/apis/catalog/brc-analytics-catalog/common/entities"; +import { + WORKFLOW_PARAMETER_VARIABLE, + WORKFLOW_PLOIDY, + WORKFLOW_SCOPE, +} from "../../../app/apis/catalog/brc-analytics-catalog/common/schema-entities"; +import { getConfiguredValues } from "../../../app/components/Entity/components/ConfigureWorkflowInputs/components/Main/components/Stepper/components/Step/hooks/UseLaunchGalaxy/utils"; +import type { ConfiguredInput } from "../../../app/views/WorkflowInputsView/hooks/UseConfigureInputs/types"; + +// Mock workflow constants to avoid pulling in unneeded modules +jest.mock( + "../../../app/views/AnalyzeWorkflowsView/differentialExpressionAnalysis/constants", + () => ({ + DIFFERENTIAL_EXPRESSION_ANALYSIS: { + trsId: "differential-expression-analysis", + }, + }) +); + +jest.mock( + "../../../app/views/AnalyzeWorkflowsView/loganSearch/constants", + () => ({ + LOGAN_SEARCH: { + trsId: "logan-search", + }, + }) +); + +jest.mock("../../../app/views/AnalyzeWorkflowsView/lexicmap/constants", () => ({ + LEXICMAP: { + trsId: "lexicmap", + }, +})); + +describe("getConfiguredValues - scope-based logic", () => { + const BASE_WORKFLOW: Workflow = { + iwcId: "iwc-test", + parameters: [], + ploidy: WORKFLOW_PLOIDY.ANY, + scope: WORKFLOW_SCOPE.ASSEMBLY, + taxonomyId: null, + trsId: "#trs-test", + workflowDescription: "test workflow", + workflowName: "Test Workflow", + }; + + const BASE_CONFIGURED_INPUT: ConfiguredInput = { + designFormula: undefined, + geneModelUrl: null, + primaryContrasts: null, + readRunsPaired: null, + readRunsSingle: null, + referenceAssembly: undefined, + sampleSheet: undefined, + sampleSheetClassification: undefined, + strandedness: undefined, + tracks: null, + }; + + describe("ASSEMBLY scope", () => { + test("returns AssemblyConfiguredValue with _scope discriminant", () => { + const workflow: Workflow = { + ...BASE_WORKFLOW, + parameters: [], + scope: WORKFLOW_SCOPE.ASSEMBLY, + }; + + const configuredInput: ConfiguredInput = { + ...BASE_CONFIGURED_INPUT, + referenceAssembly: "GCF_000001405.40", + }; + + const result = getConfiguredValues(configuredInput, workflow); + + expect(result).toBeDefined(); + expect(result?._scope).toBe("ASSEMBLY"); + expect(result).toHaveProperty("referenceAssembly", "GCF_000001405.40"); + }); + + test("returns undefined when required ASSEMBLY_FASTA_URL param is missing", () => { + const workflow: Workflow = { + ...BASE_WORKFLOW, + parameters: [ + { + key: "Reference genome", + variable: WORKFLOW_PARAMETER_VARIABLE.ASSEMBLY_FASTA_URL, + }, + ], + scope: WORKFLOW_SCOPE.ASSEMBLY, + }; + + const configuredInput: ConfiguredInput = { + ...BASE_CONFIGURED_INPUT, + referenceAssembly: undefined, // Missing required value + }; + + const result = getConfiguredValues(configuredInput, workflow); + + expect(result).toBeUndefined(); + }); + + test("returns value when all required params are provided", () => { + const workflow: Workflow = { + ...BASE_WORKFLOW, + parameters: [ + { + key: "Reference genome", + variable: WORKFLOW_PARAMETER_VARIABLE.ASSEMBLY_FASTA_URL, + }, + { + key: "Gene model", + variable: WORKFLOW_PARAMETER_VARIABLE.GENE_MODEL_URL, + }, + ], + scope: WORKFLOW_SCOPE.ASSEMBLY, + }; + + const configuredInput: ConfiguredInput = { + ...BASE_CONFIGURED_INPUT, + geneModelUrl: "https://example.com/genes.gff", + referenceAssembly: "GCF_000001405.40", + }; + + const result = getConfiguredValues(configuredInput, workflow); + + expect(result).toBeDefined(); + expect(result?._scope).toBe("ASSEMBLY"); + }); + }); + + describe("ORGANISM scope", () => { + test("returns OrganismConfiguredValue with _scope discriminant", () => { + const workflow: Workflow = { + ...BASE_WORKFLOW, + scope: WORKFLOW_SCOPE.ORGANISM, + }; + + const result = getConfiguredValues(BASE_CONFIGURED_INPUT, workflow); + + expect(result).toBeDefined(); + expect(result?._scope).toBe("ORGANISM"); + }); + + test("returns OrganismConfiguredValue with fastaCollection property", () => { + const workflow: Workflow = { + ...BASE_WORKFLOW, + scope: WORKFLOW_SCOPE.ORGANISM, + }; + + const result = getConfiguredValues(BASE_CONFIGURED_INPUT, workflow); + + expect(result).toBeDefined(); + expect(result).toHaveProperty("fastaCollection", null); + }); + + test("always returns value regardless of configuredInput (no validation)", () => { + const workflow: Workflow = { + ...BASE_WORKFLOW, + scope: WORKFLOW_SCOPE.ORGANISM, + }; + + // Even with empty/null inputs, ORGANISM scope should return a value + const result = getConfiguredValues(BASE_CONFIGURED_INPUT, workflow); + + expect(result).toBeDefined(); + }); + }); + + describe("SEQUENCE scope", () => { + test("returns SequenceConfiguredValue with _scope discriminant", () => { + const workflow: Workflow = { + ...BASE_WORKFLOW, + scope: WORKFLOW_SCOPE.SEQUENCE, + }; + + const result = getConfiguredValues(BASE_CONFIGURED_INPUT, workflow); + + expect(result).toBeDefined(); + expect(result?._scope).toBe("SEQUENCE"); + }); + + test("returns SequenceConfiguredValue with numberOfHits and sequence", () => { + const workflow: Workflow = { + ...BASE_WORKFLOW, + scope: WORKFLOW_SCOPE.SEQUENCE, + }; + + const result = getConfiguredValues(BASE_CONFIGURED_INPUT, workflow); + + expect(result).toBeDefined(); + expect(result).toHaveProperty("numberOfHits", 10); + expect(result).toHaveProperty("sequence", ""); + }); + + test("always returns value regardless of configuredInput (no validation)", () => { + const workflow: Workflow = { + ...BASE_WORKFLOW, + scope: WORKFLOW_SCOPE.SEQUENCE, + }; + + const result = getConfiguredValues(BASE_CONFIGURED_INPUT, workflow); + + expect(result).toBeDefined(); + }); + }); + + describe("type guards", () => { + test("ASSEMBLY scope value passes isAssemblyConfiguredValue", () => { + const workflow: Workflow = { + ...BASE_WORKFLOW, + scope: WORKFLOW_SCOPE.ASSEMBLY, + }; + + const configuredInput: ConfiguredInput = { + ...BASE_CONFIGURED_INPUT, + referenceAssembly: "GCF_000001405.40", + }; + + const result = getConfiguredValues(configuredInput, workflow); + + expect(result?._scope).toBe("ASSEMBLY"); + // Type guard would narrow to AssemblyConfiguredValue + if (result && result._scope === "ASSEMBLY") { + expect(result.referenceAssembly).toBe("GCF_000001405.40"); + } + }); + + test("ORGANISM scope value passes isOrganismConfiguredValue", () => { + const workflow: Workflow = { + ...BASE_WORKFLOW, + scope: WORKFLOW_SCOPE.ORGANISM, + }; + + const result = getConfiguredValues(BASE_CONFIGURED_INPUT, workflow); + + expect(result?._scope).toBe("ORGANISM"); + // Type guard would narrow to OrganismConfiguredValue + if (result && result._scope === "ORGANISM") { + expect(result.fastaCollection).toBeNull(); + } + }); + + test("SEQUENCE scope value passes isSequenceConfiguredValue", () => { + const workflow: Workflow = { + ...BASE_WORKFLOW, + scope: WORKFLOW_SCOPE.SEQUENCE, + }; + + const result = getConfiguredValues(BASE_CONFIGURED_INPUT, workflow); + + expect(result?._scope).toBe("SEQUENCE"); + // Type guard would narrow to SequenceConfiguredValue + if (result && result._scope === "SEQUENCE") { + expect(result.numberOfHits).toBe(10); + } + }); + }); +}); From a22bc83695c0d5a7e70f848740fb14c4dbf102ff Mon Sep 17 00:00:00 2001 From: Danielle Callan Date: Mon, 20 Apr 2026 10:07:17 -0400 Subject: [PATCH 5/7] fix: update workflows json --- catalog/output/workflows.json | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/catalog/output/workflows.json b/catalog/output/workflows.json index 494375b6c..335278bb4 100644 --- a/catalog/output/workflows.json +++ b/catalog/output/workflows.json @@ -545,51 +545,51 @@ "elements": [ { "ext": "fasta", + "md5": "0cc350480c0ef6d2583b4764adaabb5a", "src": "url", - "url": "https://zenodo.org/records/14628364/files/ref_1_pb2.fasta", - "md5": "5c8e6c3e8f3a1c5e5e5e5e5e5e5e5e5e" + "url": "https://zenodo.org/records/14628364/files/ref_1_pb2.fasta" }, { "ext": "fasta", + "md5": "a8c9d6aa3c21ec24c42f480750dc4eca", "src": "url", - "url": "https://zenodo.org/records/14628364/files/ref_2_pb1.fasta", - "md5": "5c8e6c3e8f3a1c5e5e5e5e5e5e5e5e5f" + "url": "https://zenodo.org/records/14628364/files/ref_2_pb1.fasta" }, { "ext": "fasta", + "md5": "a5f373e913c0f84ea00cba35ea81c703", "src": "url", - "url": "https://zenodo.org/records/14628364/files/ref_3_pa.fasta", - "md5": "5c8e6c3e8f3a1c5e5e5e5e5e5e5e5e60" + "url": "https://zenodo.org/records/14628364/files/ref_3_pa.fasta" }, { "ext": "fasta", + "md5": "9476d2c02a0429e6b0e5a70ea2a94ef2", "src": "url", - "url": "https://zenodo.org/records/14628364/files/ref_4_ha.fasta", - "md5": "5c8e6c3e8f3a1c5e5e5e5e5e5e5e5e61" + "url": "https://zenodo.org/records/14628364/files/ref_4_ha.fasta" }, { "ext": "fasta", + "md5": "3d0e28d72bba2c8b352d64052524473d", "src": "url", - "url": "https://zenodo.org/records/14628364/files/ref_5_np.fasta", - "md5": "5c8e6c3e8f3a1c5e5e5e5e5e5e5e5e62" + "url": "https://zenodo.org/records/14628364/files/ref_5_np.fasta" }, { "ext": "fasta", + "md5": "d8c21026a3defe01e020628e5b76227c", "src": "url", - "url": "https://zenodo.org/records/14628364/files/ref_6_na.fasta", - "md5": "5c8e6c3e8f3a1c5e5e5e5e5e5e5e5e63" + "url": "https://zenodo.org/records/14628364/files/ref_6_na.fasta" }, { "ext": "fasta", + "md5": "13b0b6900807d5e557348b0e69dc79ad", "src": "url", - "url": "https://zenodo.org/records/14628364/files/ref_7_mp.fasta", - "md5": "5c8e6c3e8f3a1c5e5e5e5e5e5e5e5e64" + "url": "https://zenodo.org/records/14628364/files/ref_7_mp.fasta" }, { "ext": "fasta", + "md5": "e98fc11ed2c825e54d8d88b295449f41", "src": "url", - "url": "https://zenodo.org/records/14628364/files/ref_8_ns.fasta", - "md5": "5c8e6c3e8f3a1c5e5e5e5e5e5e5e5e65" + "url": "https://zenodo.org/records/14628364/files/ref_8_ns.fasta" } ] } From 77e66d4d638f8a9df7696d0332e52083cda6622b Mon Sep 17 00:00:00 2001 From: Danielle Callan Date: Mon, 20 Apr 2026 10:35:27 -0400 Subject: [PATCH 6/7] fix: properly validate assembly scope wf inputs --- .../Stepper/components/Step/hooks/UseLaunchGalaxy/utils.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/app/components/Entity/components/ConfigureWorkflowInputs/components/Main/components/Stepper/components/Step/hooks/UseLaunchGalaxy/utils.ts b/app/components/Entity/components/ConfigureWorkflowInputs/components/Main/components/Stepper/components/Step/hooks/UseLaunchGalaxy/utils.ts index 0cacad514..12bc1d61b 100644 --- a/app/components/Entity/components/ConfigureWorkflowInputs/components/Main/components/Stepper/components/Step/hooks/UseLaunchGalaxy/utils.ts +++ b/app/components/Entity/components/ConfigureWorkflowInputs/components/Main/components/Stepper/components/Step/hooks/UseLaunchGalaxy/utils.ts @@ -81,11 +81,12 @@ function getAssemblyScopeConfiguredValues( // If workflow is not available yet, return undefined if (!workflow?.parameters) return; + // ASSEMBLY-scope workflows always require referenceAssembly + if (!referenceAssembly) return; + // Check which parameters are required by the workflow const requiredParams = getRequiredParameterTypes(workflow); - // Only check for required values - if (requiredParams.ASSEMBLY_FASTA_URL && !referenceAssembly) return; // For geneModelUrl, treat empty string as valid (user skipped or will upload manually) if (requiredParams.GENE_MODEL_URL && geneModelUrl === null) return; if (requiredParams.SANGER_READ_RUN_SINGLE && !readRunsSingle) return; @@ -98,7 +99,7 @@ function getAssemblyScopeConfiguredValues( primaryContrasts: null, readRunsPaired: readRunsPaired ?? null, readRunsSingle: readRunsSingle ?? null, - referenceAssembly: referenceAssembly!, + referenceAssembly, sampleSheet: null, sampleSheetClassification: null, strandedness: undefined, From 159ab92efa1b1852a9dbc901888468c4d6c07cf5 Mon Sep 17 00:00:00 2001 From: Danielle Callan Date: Mon, 20 Apr 2026 10:36:22 -0400 Subject: [PATCH 7/7] fix: update configuredvalue tests for sequence scope workflows --- .../getConfiguredValues.scope.test.ts | 55 ++++++++++++++++--- 1 file changed, 48 insertions(+), 7 deletions(-) diff --git a/tests/components/configureWorkflowInputs/getConfiguredValues.scope.test.ts b/tests/components/configureWorkflowInputs/getConfiguredValues.scope.test.ts index 9af307f80..dd4ef5030 100644 --- a/tests/components/configureWorkflowInputs/getConfiguredValues.scope.test.ts +++ b/tests/components/configureWorkflowInputs/getConfiguredValues.scope.test.ts @@ -173,7 +173,13 @@ describe("getConfiguredValues - scope-based logic", () => { scope: WORKFLOW_SCOPE.SEQUENCE, }; - const result = getConfiguredValues(BASE_CONFIGURED_INPUT, workflow); + const configuredInput: ConfiguredInput = { + ...BASE_CONFIGURED_INPUT, + numberOfHits: 10, + sequence: ">test\nATCG", + }; + + const result = getConfiguredValues(configuredInput, workflow); expect(result).toBeDefined(); expect(result?._scope).toBe("SEQUENCE"); @@ -185,22 +191,51 @@ describe("getConfiguredValues - scope-based logic", () => { scope: WORKFLOW_SCOPE.SEQUENCE, }; - const result = getConfiguredValues(BASE_CONFIGURED_INPUT, workflow); + const configuredInput: ConfiguredInput = { + ...BASE_CONFIGURED_INPUT, + numberOfHits: 10, + sequence: ">test\nATCG", + }; + + const result = getConfiguredValues(configuredInput, workflow); expect(result).toBeDefined(); expect(result).toHaveProperty("numberOfHits", 10); - expect(result).toHaveProperty("sequence", ""); + expect(result).toHaveProperty("sequence", ">test\nATCG"); }); - test("always returns value regardless of configuredInput (no validation)", () => { + test("returns undefined when required sequence is missing", () => { const workflow: Workflow = { ...BASE_WORKFLOW, scope: WORKFLOW_SCOPE.SEQUENCE, }; - const result = getConfiguredValues(BASE_CONFIGURED_INPUT, workflow); + const configuredInput: ConfiguredInput = { + ...BASE_CONFIGURED_INPUT, + numberOfHits: 10, + // sequence is missing + }; - expect(result).toBeDefined(); + const result = getConfiguredValues(configuredInput, workflow); + + expect(result).toBeUndefined(); + }); + + test("returns undefined when required numberOfHits is missing", () => { + const workflow: Workflow = { + ...BASE_WORKFLOW, + scope: WORKFLOW_SCOPE.SEQUENCE, + }; + + const configuredInput: ConfiguredInput = { + ...BASE_CONFIGURED_INPUT, + sequence: ">test\nATCG", + // numberOfHits is missing + }; + + const result = getConfiguredValues(configuredInput, workflow); + + expect(result).toBeUndefined(); }); }); @@ -246,7 +281,13 @@ describe("getConfiguredValues - scope-based logic", () => { scope: WORKFLOW_SCOPE.SEQUENCE, }; - const result = getConfiguredValues(BASE_CONFIGURED_INPUT, workflow); + const configuredInput: ConfiguredInput = { + ...BASE_CONFIGURED_INPUT, + numberOfHits: 10, + sequence: ">test\nATCG", + }; + + const result = getConfiguredValues(configuredInput, workflow); expect(result?._scope).toBe("SEQUENCE"); // Type guard would narrow to SequenceConfiguredValue