From 5c1e9b1f31f8edab1bee22fc33da94be11789352 Mon Sep 17 00:00:00 2001 From: Daniel Suveges Date: Fri, 30 Jan 2026 20:08:56 +0000 Subject: [PATCH] feat: exposing transcripts in the target index --- app/models/entities/Target.scala | 15 ++++++++++++++- app/models/gql/Objects.scala | 17 +++++++++++++++++ test/controllers/GqlTest.scala | 3 +++ .../gqlQueries/TargetPage_Transcripts.gql | 14 ++++++++++++++ 4 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 test/resources/gqlQueries/TargetPage_Transcripts.gql diff --git a/app/models/entities/Target.scala b/app/models/entities/Target.scala index bcd411da..e33da5f3 100644 --- a/app/models/entities/Target.scala +++ b/app/models/entities/Target.scala @@ -124,6 +124,17 @@ case class Constraint( case class ReactomePathway(pathway: String, pathwayId: String, topLevelTerm: String) +case class Transcript( + transcriptId: String, + biotype: String, + isEnsemblCanonical: Boolean, + uniprotId: Option[String], + isUniprotReviewed: Option[Boolean], + translationId: Option[String], + alphafoldId: Option[String], + uniprotIsoformId: Option[String] +) + case class Target( id: String, alternativeGenes: Seq[String] = Seq.empty, @@ -152,7 +163,8 @@ case class Target( targetClass: Seq[TargetClass] = Seq.empty, tep: Option[Tep], tractability: Seq[Tractability] = Seq.empty, - transcriptIds: Seq[String] = Seq.empty + transcriptIds: Seq[String] = Seq.empty, + transcripts: Seq[Transcript] = Seq.empty ) object Target extends OTLogging { @@ -202,6 +214,7 @@ object Target extends OTLogging { implicit val hallmarkAttributeImpF: OFormat[HallmarkAttribute] = Json.format[models.entities.HallmarkAttribute] implicit val hallmarksImpF: OFormat[Hallmarks] = Json.format[models.entities.Hallmarks] + implicit val transcriptImpF: OFormat[Transcript] = Json.format[models.entities.Transcript] implicit val targetImpF: OFormat[Target] = Json.format[Target] } diff --git a/app/models/gql/Objects.scala b/app/models/gql/Objects.scala index f745b054..c0d80c3a 100644 --- a/app/models/gql/Objects.scala +++ b/app/models/gql/Objects.scala @@ -137,6 +137,19 @@ object Objects extends OTLogging { ) ) + implicit val transcriptImp: ObjectType[Backend, Transcript] = + deriveObjectType[Backend, Transcript]( + ObjectTypeDescription("Transcript annotation for a target gene"), + DocumentField("transcriptId", "Ensembl transcript identifier"), + DocumentField("biotype", "Biotype classification of the transcript"), + DocumentField("isEnsemblCanonical", "Whether this is the Ensembl canonical transcript"), + DocumentField("uniprotId", "UniProt accession mapped to the transcript"), + DocumentField("isUniprotReviewed", "Whether the UniProt entry is reviewed (Swiss-Prot)"), + DocumentField("translationId", "Ensembl translation identifier"), + DocumentField("alphafoldId", "AlphaFold structure prediction identifier"), + DocumentField("uniprotIsoformId", "UniProt isoform identifier") + ) + implicit lazy val targetImp: ObjectType[Backend, Target] = deriveObjectType( ObjectTypeDescription( "Core annotation for drug targets (gene/proteins). Targets are defined based on EMBL-EBI Ensembl database and uses the Ensembl gene ID as the primary identifier. An Ensembl gene ID is considered potential drug target if included in the canonical assembly or if present alternative assemblies but encoding for a reviewed protein product according to the UniProt database." @@ -191,6 +204,10 @@ object Objects extends OTLogging { DocumentField("transcriptIds", "List of Ensembl transcript identifiers associated with the target" ), + DocumentField( + "transcripts", + "List of transcripts associated with the target including protein and structure annotations" + ), DocumentField("pathways", "Pathway annotations for the target"), RenameField("go", "geneOntology"), RenameField("constraint", "geneticConstraint"), diff --git a/test/controllers/GqlTest.scala b/test/controllers/GqlTest.scala index 36c17655..2605a99b 100644 --- a/test/controllers/GqlTest.scala +++ b/test/controllers/GqlTest.scala @@ -555,6 +555,9 @@ class GqlTest "return valid response for subcellular location fragment" taggedAs IntegrationTestTag in { testQueryAgainstGqlEndpoint(TargetFragment("SubcellularLocation_SubcellularLocationFragment")) } + "return valid response for target transcripts query" taggedAs IntegrationTestTag in { + testQueryAgainstGqlEndpoint(Target("TargetPage_Transcripts"))(ensgTransform) + } "return a valid response for genetic contraint query" taggedAs IntegrationTestTag in { testQueryAgainstGqlEndpoint(Target("GeneticConstraint_GeneticConstraint"))(ensgTransform) } diff --git a/test/resources/gqlQueries/TargetPage_Transcripts.gql b/test/resources/gqlQueries/TargetPage_Transcripts.gql new file mode 100644 index 00000000..b32d5cfc --- /dev/null +++ b/test/resources/gqlQueries/TargetPage_Transcripts.gql @@ -0,0 +1,14 @@ +query TargetTranscriptsQuery($ensgId: String!) { + target(ensemblId: $ensgId) { + transcripts { + transcriptId + biotype + isEnsemblCanonical + uniprotId + isUniprotReviewed + translationId + alphafoldId + uniprotIsoformId + } + } +}