From 1a1b61d077a8afa360a40b8a763aafbe282f5541 Mon Sep 17 00:00:00 2001 From: Katie Stahl Date: Tue, 30 Jul 2024 15:12:33 -0400 Subject: [PATCH] bug fixes --- .../components/Pages/Summary/Main/Summary.tsx | 7 +- client/src/services/ResponseModels.ts | 121 ++++++++++++++---- client/src/services/main.tsx | 18 ++- server/src/curfu/routers/nomenclature.py | 5 +- server/src/curfu/schemas.py | 33 ++++- 5 files changed, 145 insertions(+), 39 deletions(-) diff --git a/client/src/components/Pages/Summary/Main/Summary.tsx b/client/src/components/Pages/Summary/Main/Summary.tsx index 8f2e6392..d50ed62d 100644 --- a/client/src/components/Pages/Summary/Main/Summary.tsx +++ b/client/src/components/Pages/Summary/Main/Summary.tsx @@ -36,9 +36,6 @@ export const Summary: React.FC = ({ setVisibleTab }) => { const [validatedFusion, setValidatedFusion] = useState< AssayedFusion | CategoricalFusion | null >(null); - const [formattedFusion, setFormattedFusion] = useState< - FormattedAssayedFusion | FormattedCategoricalFusion | null - >(null); const [validationErrors, setValidationErrors] = useState([]); const { fusion } = useContext(FusionContext); @@ -113,11 +110,9 @@ export const Summary: React.FC = ({ setVisibleTab }) => { } } else { setValidationErrors([]); - console.log(response.fusion); setValidatedFusion( response.fusion as CategoricalFusion | AssayedFusion ); - setFormattedFusion(formattedFusion); } }); }; @@ -161,6 +156,8 @@ export const Summary: React.FC = ({ setVisibleTab }) => { requestValidatedFusion(formattedFusion); }, [fusion]); + console.log(validatedFusion); + return ( <> {(!validationErrors || validationErrors.length === 0) && diff --git a/client/src/services/ResponseModels.ts b/client/src/services/ResponseModels.ts index fdaf995d..23a00384 100644 --- a/client/src/services/ResponseModels.ts +++ b/client/src/services/ResponseModels.ts @@ -6,9 +6,9 @@ */ /** - * Form of evidence supporting identification of the fusion. + * Specify possible Fusion types. */ -export type Evidence = "observed" | "inferred"; +export type FusionType = "CategoricalFusion" | "AssayedFusion"; /** * Define possible classes of Regulatory Elements. Options are the possible values * for /regulatory_class value property in the INSDC controlled vocabulary: @@ -66,6 +66,20 @@ export type Range = [number | null, number | null]; * A character string of Residues that represents a biological sequence using the conventional sequence order (5'-to-3' for nucleic acid sequences, and amino-to-carboxyl for amino acid sequences). IUPAC ambiguity codes are permitted in Sequence Strings. */ export type SequenceString = string; +/** + * Define possible structural element type values. + */ +export type StructuralElementType = + | "TranscriptSegmentElement" + | "TemplatedSequenceElement" + | "LinkerSequenceElement" + | "GeneElement" + | "UnknownGeneElement" + | "MultiplePossibleGenesElement"; +/** + * Form of evidence supporting identification of the fusion. + */ +export type Evidence = "observed" | "inferred"; /** * Create enum for positive and negative strand */ @@ -81,34 +95,13 @@ export type EventType = "rearrangement" | "read-through" | "trans-splicing"; export type DomainStatus = "lost" | "preserved"; /** - * Information pertaining to the assay used in identifying the fusion. - */ -export interface Assay { - type?: "Assay"; - assayName?: string | null; - assayId?: string | null; - methodUri?: string | null; - fusionDetection?: Evidence | null; -} -/** - * Assayed gene fusions from biological specimens are directly detected using - * RNA-based gene fusion assays, or alternatively may be inferred from genomic - * rearrangements detected by whole genome sequencing or by coarser-scale cytogenomic - * assays. Example: an EWSR1 fusion inferred from a breakapart FISH assay. + * Define Fusion class */ -export interface AssayedFusion { - type?: "AssayedFusion"; +export interface AbstractFusion { + type: FusionType; regulatoryElement?: RegulatoryElement | null; - structure: ( - | TranscriptSegmentElement - | GeneElement - | TemplatedSequenceElement - | LinkerElement - | UnknownGeneElement - )[]; + structure: BaseStructuralElement[]; readingFramePreserved?: boolean | null; - causativeEvent?: CausativeEvent | null; - assay?: Assay | null; } /** * Define RegulatoryElement class. @@ -325,6 +318,43 @@ export interface SequenceReference { circular?: boolean | null; [k: string]: unknown; } +/** + * Define base structural element class. + */ +export interface BaseStructuralElement { + type: StructuralElementType; + [k: string]: unknown; +} +/** + * Information pertaining to the assay used in identifying the fusion. + */ +export interface Assay { + type?: "Assay"; + assayName?: string | null; + assayId?: string | null; + methodUri?: string | null; + fusionDetection?: Evidence | null; +} +/** + * Assayed gene fusions from biological specimens are directly detected using + * RNA-based gene fusion assays, or alternatively may be inferred from genomic + * rearrangements detected by whole genome sequencing or by coarser-scale cytogenomic + * assays. Example: an EWSR1 fusion inferred from a breakapart FISH assay. + */ +export interface AssayedFusion { + type?: "AssayedFusion"; + regulatoryElement?: RegulatoryElement | null; + structure: ( + | TranscriptSegmentElement + | GeneElement + | TemplatedSequenceElement + | LinkerElement + | UnknownGeneElement + )[]; + readingFramePreserved?: boolean | null; + causativeEvent?: CausativeEvent | null; + assay?: Assay | null; +} /** * Define TranscriptSegment class */ @@ -664,6 +694,41 @@ export interface ExonCoordsRequest { exonEnd?: number | null; exonEndOffset?: number | null; } +/** + * Assayed fusion with parameters defined as expected in fusor assayed_fusion function + * validate attempts to validate a fusion by constructing it by sending kwargs. In the models and frontend, these are camelCase, + * but the assayed_fusion and categorical_fusion constructors expect snake_case + */ +export interface FormattedAssayedFusion { + structure: ( + | TranscriptSegmentElement + | GeneElement + | TemplatedSequenceElement + | LinkerElement + | UnknownGeneElement + )[]; + causative_event?: CausativeEvent | null; + assay?: Assay | null; + regulatory_element?: RegulatoryElement | null; + reading_frame_preserved?: boolean | null; +} +/** + * Categorical fusion with parameters defined as expected in fusor categorical_fusion function + * validate attempts to validate a fusion by constructing it by sending kwargs. In the models and frontend, these are camelCase, + * but the assayed_fusion and categorical_fusion constructors expect snake_case + */ +export interface FormattedCategoricalFusion { + structure: ( + | TranscriptSegmentElement + | GeneElement + | TemplatedSequenceElement + | LinkerElement + | MultiplePossibleGenesElement + )[]; + regulatory_element?: RegulatoryElement | null; + critical_functional_domains?: FunctionalDomain[] | null; + reading_frame_preserved?: boolean | null; +} /** * Response model for gene element construction endoint. */ @@ -784,5 +849,5 @@ export interface TxSegmentElementResponse { */ export interface ValidateFusionResponse { warnings?: string[] | null; - fusion: CategoricalFusion | AssayedFusion | null; + fusion: AbstractFusion | null; } diff --git a/client/src/services/main.tsx b/client/src/services/main.tsx index 719245b0..ee3c29cd 100644 --- a/client/src/services/main.tsx +++ b/client/src/services/main.tsx @@ -37,6 +37,8 @@ import { RegulatoryClass, RegulatoryElementResponse, ClientRegulatoryElement, + FormattedAssayedFusion, + FormattedCategoricalFusion, } from "./ResponseModels"; export enum ElementType { @@ -67,6 +69,20 @@ export type ElementUnion = | TemplatedSequenceElement | TranscriptSegmentElement; +export type AssayedFusionElements = + | GeneElement + | LinkerElement + | UnknownGeneElement + | TemplatedSequenceElement + | TranscriptSegmentElement; + +export type CategoricalFusionElements = + | MultiplePossibleGenesElement + | GeneElement + | LinkerElement + | TemplatedSequenceElement + | TranscriptSegmentElement; + export type ClientFusion = ClientCategoricalFusion | ClientAssayedFusion; /** @@ -387,7 +403,7 @@ export const getGeneNomenclature = async ( * @returns nomenclature if successful */ export const getFusionNomenclature = async ( - fusion: AssayedFusion | CategoricalFusion + fusion: FormattedAssayedFusion | FormattedCategoricalFusion ): Promise => { const response = await fetch("/api/nomenclature/fusion", { method: "POST", diff --git a/server/src/curfu/routers/nomenclature.py b/server/src/curfu/routers/nomenclature.py index 55b83743..7fb4fbf0 100644 --- a/server/src/curfu/routers/nomenclature.py +++ b/server/src/curfu/routers/nomenclature.py @@ -186,8 +186,7 @@ def generate_fusion_nomenclature( :return: response with fusion nomenclature """ try: - valid_fusion = request.app.state.fusor.fusion(**fusion) + nomenclature = request.app.state.fusor.generate_nomenclature(fusion) + return {"nomenclature": nomenclature} except FUSORParametersException as e: return {"warnings": [str(e)]} - nomenclature = request.app.state.fusor.generate_nomenclature(valid_fusion) - return {"nomenclature": nomenclature} diff --git a/server/src/curfu/schemas.py b/server/src/curfu/schemas.py index 0c67c924..5a699131 100644 --- a/server/src/curfu/schemas.py +++ b/server/src/curfu/schemas.py @@ -5,10 +5,14 @@ from cool_seq_tool.schemas import GenomicData from fusor.models import ( + AbstractFusion, + Assay, AssayedFusion, + AssayedFusionElements, CategoricalFusion, + CategoricalFusionElements, + CausativeEvent, FunctionalDomain, - Fusion, GeneElement, LinkerElement, MultiplePossibleGenesElement, @@ -176,7 +180,7 @@ class AssociatedDomainResponse(Response): class ValidateFusionResponse(Response): """Response model for Fusion validation endpoint.""" - fusion: Fusion | None + fusion: AbstractFusion | None class ExonCoordsRequest(BaseModel): @@ -288,6 +292,31 @@ class ClientAssayedFusion(AssayedFusion): ] +class FormattedAssayedFusion(BaseModel): + """Assayed fusion with parameters defined as expected in fusor assayed_fusion function + validate attempts to validate a fusion by constructing it by sending kwargs. In the models and frontend, these are camelCase, + but the assayed_fusion and categorical_fusion constructors expect snake_case + """ + + structure: AssayedFusionElements + causative_event: CausativeEvent | None = None + assay: Assay | None = None + regulatory_element: RegulatoryElement | None = None + reading_frame_preserved: bool | None = None + + +class FormattedCategoricalFusion(BaseModel): + """Categorical fusion with parameters defined as expected in fusor categorical_fusion function + validate attempts to validate a fusion by constructing it by sending kwargs. In the models and frontend, these are camelCase, + but the assayed_fusion and categorical_fusion constructors expect snake_case + """ + + structure: CategoricalFusionElements + regulatory_element: RegulatoryElement | None = None + critical_functional_domains: list[FunctionalDomain] | None = None + reading_frame_preserved: bool | None = None + + class NomenclatureResponse(Response): """Response model for regulatory element nomenclature endpoint."""