From 81a36aabf86fabacdc569224c8a324c36467bf3e Mon Sep 17 00:00:00 2001 From: Remi PLANEL <rplanel@pasteur.fr> Date: Thu, 21 Mar 2024 14:24:28 +0100 Subject: [PATCH] try add matrix-pdock auto --- components/ServerDbTable.vue | 25 ------ components/content/MatrixPdock.vue | 132 ++++++++++++++++++++++++++++ content/3.defense-systems/dazbog.md | 1 + content/3.defense-systems/pago.md | 2 + nuxt.config.ts | 1 + server/plugins/content.ts | 15 ++++ 6 files changed, 151 insertions(+), 25 deletions(-) create mode 100644 components/content/MatrixPdock.vue diff --git a/components/ServerDbTable.vue b/components/ServerDbTable.vue index 14eebd3e..306f2ee9 100644 --- a/components/ServerDbTable.vue +++ b/components/ServerDbTable.vue @@ -126,32 +126,7 @@ onBeforeMount(async () => { const msFilterCompo = ref<FilterItem[] | undefined>(undefined) -const computedFilterStr = computed(() => { - const toValFilters = toValue(msFilterCompo) - let filtersStr: string | undefined = undefined - if (toValFilters !== undefined && toValFilters.length > 0) { - const tmpFilterItems = [...toValFilters] - if (tmpFilterItems.length % 4 === 0) { - tmpFilterItems.splice(-1) - } - filtersStr = "(" + tmpFilterItems.map((it, index) => { - const sanitizedValue = it.value.split("-").slice(0, -1).join("-") - if ((index + 1) % 4 === 3) { - return `"${sanitizedValue}"` - } else if ((index + 1) % 4 === 0) { - return ` ${sanitizedValue} ` - } - else { - return `${sanitizedValue}` - } - - }).join("") + ")" - } - - return [filtersStr, props.numericalFilters].filter(f => f !== undefined && f !== null).join(" AND ") - -}) const computedF = computed(() => toValue(props.numericalFilters)) diff --git a/components/content/MatrixPdock.vue b/components/content/MatrixPdock.vue new file mode 100644 index 00000000..b2761110 --- /dev/null +++ b/components/content/MatrixPdock.vue @@ -0,0 +1,132 @@ +<script setup lang="ts"> +import * as d3 from "d3"; +import * as Plot from "@observablehq/plot"; +import PlotFigure from "~/components/PlotFigure"; + + + +export interface Props { + system?: MaybeRef<string | null> +} +const { page } = useContent(); +const { system } = withDefaults(defineProps<Props>(), { system: null }) +const dbName = "structure" +const filterBase = ref<string[]>([ + "prediction_type='multimer(dimer)'", + "completed='true'" +]) + +export interface PlotMargin { + marginTop: number, + marginRight: number, + marginBottom: number, + marginLeft: number +} + +const margin = ref<PlotMargin>({ + marginTop: 100, + marginRight: 50, + marginBottom: 0, + marginLeft: 150 +}) + +const computedSystem = computed(() => { + const toValPage = toValue(page) + const toValSystem = toValue(system) + if (toValSystem === null) { + return toValPage?.title?.toLowerCase() ?? null + } + else { + return toValSystem + } +}) + + +const groupedPdocks = computed(() => { + const toValData = toValue(data) + return d3.groups(toValData.hits.flatMap(({ System_name_ok, pDockQ, pdb, nb_sys, proteins_in_the_prediction, system_genes }) => { + + + if (proteins_in_the_prediction.length === 2) { + const sanitizedSystemGenes = system_genes.map(d => d.split("__")[1]) + const sanitizedProteins = proteins_in_the_prediction.map(d => d.split("__")[1]) + const setProteins = new Set(sanitizedProteins) + + + if (setProteins.size === 2) { + + return sanitizedProteins.map((prot, i) => { + if (i === 0) { + return { System_name_ok, system_genes: sanitizedSystemGenes, pDockQ, pdb, nb_sys, proteins_in_the_prediction: sanitizedProteins, protX: prot, protY: sanitizedProteins[i + 1] } + } + else { + return { System_name_ok, system_genes: sanitizedSystemGenes, pDockQ, pdb, nb_sys, proteins_in_the_prediction: sanitizedProteins, protX: prot, protY: sanitizedProteins[i - 1] } + } + + }) + } else { + return { System_name_ok, system_genes: sanitizedSystemGenes, pDockQ, pdb, nb_sys, proteins_in_the_prediction: sanitizedProteins, protX: sanitizedProteins[0], protY: sanitizedProteins[1] } + } + } else { + throw createError(`More than 2 proteins in a dimer structure for system ${computedSystem.value} !`) + } + }), d => d.system_genes.join("--")) +}) + + +const computedPDocksMatrixPlotOptions = computed(() => { + const { marginBottom, marginLeft, marginRight, marginTop } = toValue(margin) + + return toValue(groupedPdocks).map((matrix) => { + return { + width: matrix[1][0].system_genes.length * 75 + marginLeft + marginRight, + height: matrix[1][0].system_genes.length * 75 + marginTop + marginBottom, + title: matrix[0], + padding: 0, + marginTop, + marginLeft, + marginRight, + marginBottom, + grid: true, + + x: { axis: "top", label: "Proteins", tickRotate: 45 }, + y: { label: "Proteins" }, + legend: { label: matrix[0] }, + color: { scheme: "plasma", legend: true, reverse: true }, + marks: [ + Plot.frame(), + Plot.cell(toValue(matrix[1]), { + x: (d) => d.protX, + y: (d) => d.protY, + fill: "pDockQ", + inset: 0.5, + tip: true, + sort: { x: "x", y: "y" } + }) + ] + } + }) +}) + +const { data, error } = await useAsyncMeiliSearch({ + index: toValue(dbName), query: "", params: { + facets: ["*"], + filter: [ + `System='${toValue(computedSystem)}'`, + ...toValue(filterBase) + ], + } +}) + +if (error.value) { + throw createError("Error while getting structure pdocks") +} +</script> +<template> + <v-card flat color="transparent"> + <v-card-text v-if="computedSystem !== null" v-for="option in computedPDocksMatrixPlotOptions" + :key="option.legend.label"> + <PlotFigure :options="unref(option)" defer></PlotFigure> + </v-card-text> + </v-card> +</template> \ No newline at end of file diff --git a/content/3.defense-systems/dazbog.md b/content/3.defense-systems/dazbog.md index 09c89773..b8b0edd3 100644 --- a/content/3.defense-systems/dazbog.md +++ b/content/3.defense-systems/dazbog.md @@ -59,6 +59,7 @@ dataUrls: --- :: + ##### Example 2 ::molstar-pdbe-plugin diff --git a/content/3.defense-systems/pago.md b/content/3.defense-systems/pago.md index e3f7358f..5f012c98 100644 --- a/content/3.defense-systems/pago.md +++ b/content/3.defense-systems/pago.md @@ -100,7 +100,9 @@ Proportion of genome encoding the pAgo system for the 14 phyla with more than 50 ## Structure + ### pAgo + ##### Example 1 ::molstar-pdbe-plugin diff --git a/nuxt.config.ts b/nuxt.config.ts index 3701ae9f..7e0d8d3e 100644 --- a/nuxt.config.ts +++ b/nuxt.config.ts @@ -1,6 +1,7 @@ import { md3 } from 'vuetify/blueprints' // https://v3.nuxtjs.org/api/configuration/nuxt.config export default defineNuxtConfig({ + ssr: true, modules: [ '@unocss/nuxt', '@nuxt/content', diff --git a/server/plugins/content.ts b/server/plugins/content.ts index 52a9870f..c89054e6 100644 --- a/server/plugins/content.ts +++ b/server/plugins/content.ts @@ -69,6 +69,21 @@ export default defineNitroPlugin((nitroApp) => { } + + // add pdock matrix + + // find structure + + const index = file.body.children.findIndex(child => child.tag === "h2" && child.props.id === "structure") + console.log(index) + if (index !== -1) { + file.body.children.splice(index, 0, { + type: "element", + tag: 'matrix-pdock', + props: {}, + children: [] + }) + } } }) }) \ No newline at end of file -- GitLab