Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

3379 cred set #196

Merged
merged 13 commits into from
Aug 2, 2024
6 changes: 6 additions & 0 deletions app/models/Backend.scala
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,12 @@ class Backend @Inject() (implicit
esRetriever.getByIds(indexName, ids, fromJsValue[VariantIndex])
}

def getCredSet(ids: Seq[String]): Future[IndexedSeq[JsValue]] = {
val indexName = getIndexOrDefault("credible_set")

esRetriever.getByIds(indexName, ids, fromJsValue[JsValue])
}

def getGwasIndexes(ids: Seq[String]): Future[IndexedSeq[JsValue]] = {
val indexName = getIndexOrDefault("gwas_index")

Expand Down
11 changes: 10 additions & 1 deletion app/models/GQLSchema.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import play.api.Logging
import play.api.libs.json._
import sangria.schema._
import entities._
import models.entities.CredibleSet.credibleSetImp
import models.entities.GwasIndex.gwasImp
import sangria.execution.deferred._

Expand All @@ -28,7 +29,8 @@ object GQLSchema {
indicationFetcher,
goFetcher,
variantFetcher,
gwasFetcher
gwasFetcher,
credSetFetcher
)

val query: ObjectType[Backend, Unit] = ObjectType(
Expand Down Expand Up @@ -149,6 +151,13 @@ object GQLSchema {
description = Some("Return a Gwas Index Study"),
arguments = studyId :: Nil,
resolve = ctx => gwasFetcher.deferOpt(ctx.arg(studyId))
),
Field(
"credibleSet",
OptionType(credibleSetImp),
description = None,
arguments = credibleSetId :: Nil,
resolve = ctx => credSetFetcher.deferOpt(ctx.arg(credibleSetId))
)
)
)
Expand Down
288 changes: 288 additions & 0 deletions app/models/entities/CredibleSet.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,288 @@
package models.entities

import models.Backend
import models.entities.GwasIndex.gwasImp
import models.gql.Fetchers.{gwasFetcher, targetsFetcher, variantFetcher}
import models.gql.Objects.{logger, targetImp, variantIndexImp}
import play.api.Logging
import play.api.libs.json.{JsValue, Json, OFormat, OWrites}
import sangria.schema.{
Field,
FloatType,
IntType,
ListType,
ObjectType,
OptionType,
StringType,
fields
}

case class Locus(
variantId: Option[String],
posteriorProbability: Option[Double],
pValueMantissa: Option[Double],
pValueExponent: Option[Int],
logBF: Option[Double],
beta: Option[Double],
standardError: Option[Double],
is95CredibleSet: Option[Boolean],
is99CredibleSet: Option[Boolean],
r2Overall: Option[Double]
)

case class LdSet(
tagVariantId: Option[String],
r2Overall: Option[Double]
)

case class StrongestLocus2gene(geneId: String, score: Double)

case class CredibleSet(studyLocusId: String,
variantId: Option[String],
chromosome: Option[String],
position: Option[Int],
region: Option[String],
studyId: Option[String],
beta: Option[Double],
zScore: Option[Double],
pValueMantissa: Option[Double],
pValueExponent: Option[Int],
effectAlleleFrequencyFromSource: Option[Double],
standardError: Option[Double],
subStudyDescription: Option[String],
qualityControls: Option[Seq[String]],
finemappingMethod: Option[String],
credibleSetIndex: Option[Int],
credibleSetlog10BF: Option[Double],
purityMeanR2: Option[Double],
purityMinR2: Option[Double],
locusStart: Option[Int],
locusEnd: Option[Int],
locus: Option[Seq[Locus]],
sampleSize: Option[Int],
strongestLocus2gene: Option[StrongestLocus2gene],
ldSet: Option[Seq[LdSet]],
studyType: Option[String],
traitFromSourceMappedIds: Option[Seq[String]],
qtlGeneId: Option[String]
)

object CredibleSet extends Logging {
import sangria.macros.derive._

implicit val strongestLocus2geneImp: ObjectType[Backend, StrongestLocus2gene] =
deriveObjectType[Backend, StrongestLocus2gene](
ReplaceField(
"geneId",
Field(
"target",
OptionType(targetImp),
Some("Target"),
resolve = r => targetsFetcher.deferOpt(r.value.geneId)
)
)
)
implicit val ldSetImp: ObjectType[Backend, LdSet] =
deriveObjectType[Backend, LdSet]()
implicit val locusImp: ObjectType[Backend, Locus] = deriveObjectType[Backend, Locus](
ReplaceField(
"variantId",
Field(
"variant",
OptionType(variantIndexImp),
description = None,
resolve = r => {
val variantId = (r.value.variantId)
logger.debug(s"Finding variant index: $variantId")
variantFetcher.deferOpt(variantId)
}
)
)
)

implicit val ldSetF: OFormat[LdSet] = Json.format[LdSet]
implicit val locusF: OFormat[Locus] = Json.format[Locus]
implicit val strongestLocus2geneF: OFormat[StrongestLocus2gene] = Json.format[StrongestLocus2gene]
val credibleSetImp: ObjectType[Backend, JsValue] = ObjectType(
"credibleSet",
"",
fields[Backend, JsValue](
Field(
"studyLocusId",
StringType,
description = None,
resolve = js => (js.value \ "studyLocusId").as[String]
),
Field(
"variant",
OptionType(variantIndexImp),
description = None,
resolve = js => {
val id = (js.value \ "variantId").asOpt[String]
logger.debug(s"Finding variant for id: $id")
variantFetcher.deferOpt(id)
}
),
Field(
"chromosome",
OptionType(StringType),
description = None,
resolve = js => (js.value \ "chromosome").asOpt[String]
),
Field(
"position",
OptionType(IntType),
description = None,
resolve = js => (js.value \ "position").asOpt[Int]
),
Field(
"region",
OptionType(StringType),
description = None,
resolve = js => (js.value \ "region").asOpt[String]
),
Field(
"study",
OptionType(gwasImp),
description = Some("Gwas study"),
resolve = js => {
val studyId = (js.value \ "studyId").asOpt[String]
logger.debug(s"Finding gwas study: $studyId")
gwasFetcher.deferOpt(studyId)
}
),
Field(
"beta",
OptionType(FloatType),
description = None,
resolve = js => (js.value \ "beta").asOpt[Double]
),
Field(
"zScore",
OptionType(FloatType),
description = None,
resolve = js => (js.value \ "zScore").asOpt[Double]
),
Field(
"pValueMantissa",
OptionType(FloatType),
description = None,
resolve = js => (js.value \ "pValueMantissa").asOpt[Double]
),
Field(
"pValueExponent",
OptionType(IntType),
description = None,
resolve = js => (js.value \ "pValueExponent").asOpt[Int]
),
Field(
"effectAlleleFrequencyFromSource",
OptionType(FloatType),
description = None,
resolve = js => (js.value \ "effectAlleleFrequencyFromSource").asOpt[Double]
),
Field(
"standardError",
OptionType(FloatType),
description = None,
resolve = js => (js.value \ "standardError").asOpt[Double]
),
Field(
"subStudyDescription",
OptionType(StringType),
description = None,
resolve = js => (js.value \ "subStudyDescription").asOpt[String]
),
Field(
"qualityControls",
OptionType(ListType(StringType)),
description = None,
resolve = js => (js.value \ "qualityControls").asOpt[Seq[String]]
),
Field(
"finemappingMethod",
OptionType(StringType),
description = None,
resolve = js => (js.value \ "finemappingMethod").asOpt[String]
),
Field(
"credibleSetIndex",
OptionType(IntType),
description = None,
resolve = js => (js.value \ "credibleSetIndex").asOpt[Int]
),
Field(
"credibleSetlog10BF",
OptionType(FloatType),
description = None,
resolve = js => (js.value \ "credibleSetlog10BF").asOpt[Double]
),
Field(
"purityMeanR2",
OptionType(FloatType),
description = None,
resolve = js => (js.value \ "purityMeanR2").asOpt[Double]
),
Field(
"purityMinR2",
OptionType(FloatType),
description = None,
resolve = js => (js.value \ "purityMinR2").asOpt[Double]
),
Field(
"locusStart",
OptionType(IntType),
description = None,
resolve = js => (js.value \ "locusStart").asOpt[Int]
),
Field(
"locusEnd",
OptionType(IntType),
description = None,
resolve = js => (js.value \ "locusEnd").asOpt[Int]
),
Field(
"locus",
OptionType(ListType(locusImp)),
description = None,
resolve = js => (js.value \ "locus").asOpt[Seq[Locus]]
),
Field(
"sampleSize",
OptionType(IntType),
description = None,
resolve = js => (js.value \ "sampleSize").asOpt[Int]
),
Field(
"strongestLocus2gene",
OptionType(strongestLocus2geneImp),
description = None,
resolve = js => (js.value \ "strongestLocus2gene").asOpt[StrongestLocus2gene]
),
Field(
"ldSet",
OptionType(ListType(ldSetImp)),
description = None,
resolve = js => (js.value \ "ldSet").asOpt[Seq[LdSet]]
),
Field(
"studyType",
OptionType(StringType),
description = None,
resolve = js => (js.value \ "studyType").asOpt[String]
),
Field(
"traitFromSourceMappedIds",
OptionType(ListType(StringType)),
description = None,
resolve = js => (js.value \ "traitFromSourceMappedIds").asOpt[Seq[String]]
),
Field(
"qtlGeneId",
OptionType(StringType),
description = None,
resolve = js => (js.value \ "qtlGeneId").asOpt[String]
)
)
)
}
2 changes: 2 additions & 0 deletions app/models/gql/Arguments.scala
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ object Arguments {
Argument("goIds", ListInputType(StringType), description = "List of GO IDs, eg. GO:0005515")
val variantId: Argument[String] = Argument("variantId", StringType, description = "Variant ID")
val studyId: Argument[String] = Argument("studyId", StringType, description = "Study ID")
val credibleSetId: Argument[String] =
Argument("credibleSetId", StringType, description = "Credible Set ID")

val indirectEvidences: Argument[Option[Boolean]] = Argument(
"enableIndirect",
Expand Down
17 changes: 16 additions & 1 deletion app/models/gql/Fetchers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package models.gql

import models.Helpers.fromJsValue
import models.entities.{
CredibleSet,
Disease,
Drug,
Expressions,
Expand Down Expand Up @@ -128,6 +129,19 @@ object Fetchers extends Logging {
}
)

val credSetFetcherCache = FetcherCache.simple
val credSetFetcher: Fetcher[Backend, JsValue, JsValue, String] = {
implicit val credSetFetcherId: HasId[JsValue, String] =
HasId[JsValue, String](js => (js \ "studyLocusId").as[String])
Fetcher(
config =
FetcherConfig.maxBatchSize(entities.Configuration.batchSize).caching(credSetFetcherCache),
fetch = (ctx: Backend, ids: Seq[String]) => {
ctx.getCredSet(ids)
}
)
}

val gwasFetcherCache = FetcherCache.simple
val gwasFetcher: Fetcher[Backend, JsValue, JsValue, String] = {
implicit val gwasFetcherId: HasId[JsValue, String] =
Expand Down Expand Up @@ -166,7 +180,8 @@ object Fetchers extends Logging {
reactomeFetcherCache,
expressionFetcherCache,
otarProjectsFetcherCache,
soTermsFetcherCache
soTermsFetcherCache,
credSetFetcherCache
)
fetchers.foreach(_.clear())
}
Expand Down
1 change: 1 addition & 0 deletions app/models/gql/Objects.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import models._
import models.entities.Configuration._
import models.entities.Evidence.sequenceOntologyTermImp
import models.entities.Evidences._
import models.entities.GwasIndex.gwasImp
import models.entities.Interactions._
import models.entities.Publications.publicationsImp
import models.entities._
Expand Down