From d68176e464004e87e9f2456fd2179a99eb027150 Mon Sep 17 00:00:00 2001 From: Miguel C Date: Wed, 15 Jan 2020 16:24:08 +0000 Subject: [PATCH] wip: include new table to show the locus to gene setting a study and a locus --- app/models/Backend.scala | 101 ++++++++++++++++++++++++++++++++++++- app/models/Entities.scala | 29 +++++++++-- app/models/GQLSchema.scala | 32 +++++++++++- build.sbt | 31 +++++++++++- production.conf | 2 +- project/build.properties | 2 +- project/plugins.sbt | 2 +- 7 files changed, 186 insertions(+), 13 deletions(-) diff --git a/app/models/Backend.scala b/app/models/Backend.scala index f075eed..4ea1437 100644 --- a/app/models/Backend.scala +++ b/app/models/Backend.scala @@ -579,7 +579,7 @@ class Backend @Inject()(@NamedDatabase("default") protected val dbConfigProvider val topLociEnrich = sql""" |SELECT * - |FROM ot.manhattan + |FROM ot.manhattan_with_l2g |WHERE study = $studyId |#$limitClause """.stripMargin.as[V2DByStudy] @@ -592,7 +592,7 @@ class Backend @Inject()(@NamedDatabase("default") protected val dbConfigProvider ManhattanAssociation(el.variantId, el.pval, el.pval_mantissa, el.pval_exponent, el.v2dOdds, el.v2dBeta, - el.topGenes, el.topColocGenes, + el.topGenes, el.topColocGenes, el.topL2Genes, el.credibleSetSize, el.ldSetSize, el.totalSetSize) }) ) @@ -602,6 +602,103 @@ class Backend @Inject()(@NamedDatabase("default") protected val dbConfigProvider } } + def buildSLGTable(studyId: String, variantId: String, pageIndex: Option[Int], pageSize: Option[Int]): + Future[Entities.SLGTable] = { + val limitClause = parsePaginationTokens(pageIndex, pageSize) + val variant = Variant.fromString(variantId) + + variant match { + case Right(v) => + val slgQ = + sql""" + |SELECT + | gene_id, + | y_proba_logi_distance, + | y_proba_logi_interaction, + | y_proba_logi_interlocus, + | y_proba_logi_molecularQTL, + | y_proba_logi_pathogenicity, + | y_proba_full_model, + | has_coloc, + | d AS distance_to_locus + |FROM + |( + | SELECT + | study_id, + | chrom, + | CAST(chrom, 'Enum8(\'1\' = 1, \'2\' = 2, \'3\' = 3, \'4\' = 4, \'5\' = 5, \'6\' = 6, \'7\' = 7, \'8\' = 8, \'9\' = 9, \'10\' = 10, \'11\' = 11, \'12\' + |= 12, \'13\' = 13, \'14\' = 14, \'15\' = 15, \'16\' = 16, \'17\' = 17, \'18\' = 18, \'19\' = 19, \'20\' = 20, \'21\' = 21, \'22\' = 22, \'X\' = 23, \'Y\' = 24, + | \'MT\' = 25)') AS enumChrom, + | pos, + | ref, + | alt, + | gene_id, + | y_proba_logi_distance, + | y_proba_logi_interaction, + | y_proba_logi_interlocus, + | y_proba_logi_molecularQTL, + | y_proba_logi_pathogenicity, + | y_proba_full_model, + | C.has_coloc AS has_coloc + | FROM ot.l2g_by_slg AS L + | ANY LEFT JOIN + | ( + | SELECT + | left_study AS study_id, + | right_gene_id AS gene_id, + | left_chrom as enumChrom, + | left_pos as pos, + | left_ref as ref, + | left_alt as alt, + | count() > 0 AS has_coloc + | FROM ot.v2d_coloc + | PREWHERE coloc_h4 > 0.8 + | GROUP BY + | left_study, + | left_chrom, + | left_pos, + | left_ref, + | left_alt, + | right_gene_id + | ) AS C USING (study_id, enumChrom, pos, ref, alt, gene_id) + | PREWHERE (study_id = $studyId) AND + | (chrom = ${v.chromosome}) AND + | (pos = ${v.position}) AND + | (ref = ${v.refAllele}) AND + | (alt = ${v.altAllele}) + |) AS LL + |ANY LEFT JOIN + |( + | SELECT + | chr_id AS chrom, + | position AS pos, + | ref_allele AS ref, + | alt_allele AS alt, + | gene_id, + | d + | FROM ot.v2g + | PREWHERE (type_id = 'distance') AND + | (source_id = 'canonical_tss') AND + | (chrom = ${v.chromosome}) AND + | (pos = ${v.position}) AND + | (ref = ${v.refAllele}) AND + | (alt = ${v.altAllele}) + |) AS G ON (LL.enumChrom = G.chrom) AND (LL.pos = G.pos) AND (LL.ref = G.ref) AND (LL.alt = G.alt) AND (LL.gene_id = G.gene_id) + |#$limitClause + """.stripMargin.as[SLGRow] + + // WHERE (study_id = $studyId) AND (chrom = '20') AND (pos = 35437976) AND (ref = 'A') AND (alt = 'G') + db.run(slgQ.asTry).map { + case Success(v) => SLGTable(studyId, variant.right.get.id, v) + case Failure(ex) => + logger.error(ex.getMessage) + SLGTable(studyId, variant.right.get.id, Vector.empty) + } + case Left(violation) => + Future.failed(InputParameterCheckError(Vector(violation))) + } + } + def buildIndexVariantAssocTable(variantID: String, pageIndex: Option[Int], pageSize: Option[Int]): Future[VariantToDiseaseTable] = { val limitPair = parsePaginationTokensForSlick(pageIndex, pageSize) diff --git a/app/models/Entities.scala b/app/models/Entities.scala index e935b37..3e86bc5 100644 --- a/app/models/Entities.scala +++ b/app/models/Entities.scala @@ -70,6 +70,7 @@ object Entities { v2dOdds: V2DOdds, v2dBeta: V2DBeta, bestGenes: Seq[(String, Double)], bestColocGenes: Seq[(String, Double)], + bestL2Genes: Seq[(String, Double)], crediblbeSetSize: Option[Long], ldSetSize: Option[Long], totalSetSize: Long) @@ -77,10 +78,21 @@ object Entities { sourceId: String, bioFeatureSet: Seq[String]) + case class SLGRow(geneId: String, + yProbaDistance: Double, + yProbaInteraction: Double, + yProbaInterlocus: Double, + yProbaMolecularQTL: Double, + yProbaPathogenicity: Double, + yProbaModel: Double, + hasColoc: Boolean, + distanceToLocus: Long) + case class SLGTable(studyId: String, variantId: String, rows: Seq[SLGRow]) case class V2DByStudy(studyId: String, variantId: String, pval: Double, pval_mantissa: Double, pval_exponent: Long, v2dOdds: V2DOdds, v2dBeta: V2DBeta, credibleSetSize: Option[Long], ldSetSize: Option[Long], totalSetSize: Long, - topGenes: Seq[(String, Double)], topColocGenes: Seq[(String, Double)]) + topGenes: Seq[(String, Double)], topColocGenes: Seq[(String, Double)], + topL2Genes: Seq[(String, Double)]) case class StudyInfo(study: Option[Study]) @@ -359,8 +371,12 @@ object Entities { } object DBImplicits { + implicit val getSLGRow: GetResult[SLGRow] = { + GetResult(r => SLGRow(r.<<, r.<<, r.<<, r.<<, r.<<, r.<<, r.<<, r.<<, r.<<)) + } + implicit val getV2DByStudy: GetResult[V2DByStudy] = { - def toGeneScoreTuple(geneIds: Seq[String], geneScores: Seq[Double]): Seq[(String, Double)] = { + def toGeneScoreTupleWithDuplicates(geneIds: Seq[String], geneScores: Seq[Double]): Seq[(String, Double)] = { val ordScored = geneIds zip geneScores if (ordScored.isEmpty) @@ -369,7 +385,7 @@ object Entities { ordScored.takeWhile(_._2 == ordScored.head._2) } - def toGeneScoreTupleColoc(geneIds: Seq[String], geneScores: Seq[Double]): Seq[(String, Double)] = { + def toGeneScoreTuple(geneIds: Seq[String], geneScores: Seq[Double]): Seq[(String, Double)] = { val ordScored = geneIds zip geneScores if (ordScored.isEmpty) @@ -393,11 +409,14 @@ object Entities { val aggTop10RawScores = DSeqRep(r.<<) val aggTop10ColocIds = StrSeqRep(r.<<) val aggTop10ColocScores = DSeqRep(r.<<) + val aggTop10L2GIds = StrSeqRep(r.<<) + val aggTop10L2GScores = DSeqRep(r.<<) V2DByStudy(studyId, svID, pval, pvalMantissa, pvalExponent, odds, beta, credSetSize, ldSetSize, totalSize, - toGeneScoreTuple(aggTop10RawIds, aggTop10RawScores), - toGeneScoreTupleColoc(aggTop10ColocIds, aggTop10ColocScores)) + toGeneScoreTupleWithDuplicates(aggTop10RawIds, aggTop10RawScores), + toGeneScoreTuple(aggTop10ColocIds, aggTop10ColocScores), + toGeneScoreTuple(aggTop10L2GIds, aggTop10L2GScores)) }) } } diff --git a/app/models/GQLSchema.scala b/app/models/GQLSchema.scala index 82a4cad..38ff6d5 100644 --- a/app/models/GQLSchema.scala +++ b/app/models/GQLSchema.scala @@ -2,6 +2,10 @@ package models import sangria.execution.deferred._ import sangria.schema._ +import sangria.macros._ +import sangria.macros.derive._ +import sangria.ast +import sangria.execution._ import Entities._ import Functions._ import models.DNA.{Gene, SimpleVariant, Variant} @@ -461,6 +465,9 @@ trait GQLManhattanAssociation { Field("bestColocGenes", ListType(scoredGene), Some("A list of best genes associated"), resolve = _.value.bestColocGenes), + Field("bestLocus2Genes", ListType(scoredGene), + Some("A list of best L2G scored genes associated"), + resolve = _.value.bestL2Genes), Field("credibleSetSize", OptionType(LongType), Some("The cardinal of the set defined as tag variants for an index variant coming from crediblesets"), resolve = _.value.crediblbeSetSize), @@ -1105,6 +1112,27 @@ object GQLSchema extends GQLGene with GQLVariant with GQLStudy with GQLIndexVari resolve = _.value.hs.log2h4h3) )) + implicit val slgRowImp = deriveObjectType[Backend, SLGRow]( + AddFields( + Field("gene", gene, + description = Some("Gene"), + resolve = ctx => genesFetcher.defer(ctx.value.geneId)) + ), + ExcludeFields("geneId") + ) + + implicit val slgTableImp = deriveObjectType[Backend, SLGTable]( + AddFields( + Field("study", OptionType(study), + description = Some("Study"), + resolve = ctx => studiesFetcher.deferOpt(ctx.value.studyId)), + Field("variant", OptionType(variant), + description = Some("Variant"), + resolve = ctx => variantsFetcher.deferOpt(ctx.value.variantId)) + ), + ExcludeFields("studyId", "variantId") + ) + val query = ObjectType( "Query", fields[Backend, Unit]( Field("search", searchResult, @@ -1126,6 +1154,9 @@ object GQLSchema extends GQLGene with GQLVariant with GQLStudy with GQLIndexVari Field("studiesForGene", ListType(studyForGene), arguments = geneId :: Nil, resolve = ctx => ctx.ctx.getStudiesForGene(ctx.arg(geneId))), + Field("studyLocus2GeneTable", slgTableImp, + arguments = studyId :: variantId :: pageIndex :: pageSize :: Nil, + resolve = ctx => ctx.ctx.buildSLGTable(ctx.arg(studyId), ctx.arg(variantId), ctx.arg(pageIndex), ctx.arg(pageSize))), Field("manhattan", manhattan, arguments = studyId :: pageIndex :: pageSize :: Nil, resolve = ctx => ctx.ctx.buildManhattanTable(ctx.arg(studyId), ctx.arg(pageIndex), ctx.arg(pageSize))), @@ -1184,7 +1215,6 @@ object GQLSchema extends GQLGene with GQLVariant with GQLStudy with GQLIndexVari arguments = studyId :: variantId :: Nil, resolve = ctx => ctx.ctx.qtlColocalisation(ctx.arg(studyId), ctx.arg(variantId))), - Field("studiesAndLeadVariantsForGene", ListType(studiesAndLeadVariantsForGene), arguments = geneId :: Nil, resolve = ctx => ctx.ctx.getStudiesAndLeadVariantsForGene(ctx.arg(geneId))) diff --git a/build.sbt b/build.sbt index de61020..818183b 100644 --- a/build.sbt +++ b/build.sbt @@ -7,7 +7,7 @@ version := "latest" lazy val root = (project in file(".")).enablePlugins(PlayScala) -scalaVersion := "2.12.8" +scalaVersion := "2.12.10" maintainer := "ops@opentargets.org" javacOptions ++= Seq( "-encoding", "UTF-8" ) @@ -18,7 +18,34 @@ scalacOptions in ThisBuild ++= Seq( "-Xfatal-warnings" ) +/* +// include resources into the unversal zipped package +mappings in Universal ++= directory(baseDirectory.value / "resources") + +resolvers += Resolver.sonatypeRepo("releases") + +libraryDependencies += guice +libraryDependencies += "com.github.pathikrit" %% "better-files" % "3.8.0" +libraryDependencies += "com.typesafe.slick" %% "slick" % "3.3.2" +libraryDependencies += "org.scalatestplus.play" %% "scalatestplus-play" % "4.0.3" % Test +val playVersion = "2.7.3" +libraryDependencies += "com.typesafe.play" %% "play" % playVersion +libraryDependencies += "com.typesafe.play" %% "filters-helpers" % playVersion +libraryDependencies += "com.typesafe.play" %% "play-logback" % playVersion +libraryDependencies += "com.typesafe.play" %% "play-json" % playVersion +libraryDependencies += "com.typesafe.play" %% "play-slick" % "4.0.2" +libraryDependencies += "ru.yandex.clickhouse" % "clickhouse-jdbc" % "0.2" +libraryDependencies += "org.sangria-graphql" %% "sangria" % "2.0.0-M1" +libraryDependencies += "org.sangria-graphql" %% "sangria-play-json" % "2.0.0" + +val s4sVersion = "7.3.1" +libraryDependencies ++= Seq( + "com.sksamuel.elastic4s" %% "elastic4s-core" % s4sVersion, + "com.sksamuel.elastic4s" %% "elastic4s-client-esjava" % s4sVersion, + "com.sksamuel.elastic4s" %% "elastic4s-json-play" % s4sVersion +) + */ // include resources into the unversal zipped package mappings in Universal ++= directory(baseDirectory.value / "resources") @@ -34,7 +61,7 @@ libraryDependencies += "com.typesafe.play" %% "play" % "2.6.23" libraryDependencies += "com.typesafe.play" %% "play-logback" % "2.6.23" libraryDependencies += "com.typesafe.play" %% "play-json" % "2.6.13" libraryDependencies += "com.typesafe.play" %% "play-slick" % "3.0.3" -libraryDependencies += "ru.yandex.clickhouse" % "clickhouse-jdbc" % "0.1.54" +libraryDependencies += "ru.yandex.clickhouse" % "clickhouse-jdbc" % "0.2.3" libraryDependencies += "org.sangria-graphql" %% "sangria" % "1.4.2" libraryDependencies += "org.sangria-graphql" %% "sangria-play-json" % "1.0.5" libraryDependencies += "com.nrinaudo" %% "kantan.csv" % "0.4.0" diff --git a/production.conf b/production.conf index 787858e..f97df0b 100644 --- a/production.conf +++ b/production.conf @@ -2,7 +2,7 @@ include "application.conf" # https://www.playframework.com/documentation/latest/Configuration http.port = 8080 http.port = ${?PLAY_PORT} -play.http.secret.key = "changeme" +play.http.secret.key = "@t/PB4rK]zIFsMcFLMMSimE`1bG0Gf^:B`u^=3zh7cBjDoX>[PcNG/y4sSwn]hUZ" play.http.secret.key = ${?PLAY_SECRET} # Root logger: diff --git a/project/build.properties b/project/build.properties index c0bab04..00b48d9 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.2.8 +sbt.version=1.3.6 diff --git a/project/plugins.sbt b/project/plugins.sbt index 9f629d1..528733b 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,2 +1,2 @@ addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.6.23") -addSbtPlugin("org.scoverage" % "sbt-scoverage" % "1.5.1") +addSbtPlugin("org.scoverage" % "sbt-scoverage" % "1.6.0")