Skip to content
Snippets Groups Projects
RefseqDb.vue 6.82 KiB
<script setup lang="ts">
import { useFacetsStore } from '~~/stores/facets'
import * as Plot from "@observablehq/plot";
import PlotFigure from "~/components/PlotFigure";
import { useDisplay } from "vuetify";
import type { SortItem } from "@/components/ServerDbTable.vue"
import { ServerDbTable } from "#components"

const facetStore = useFacetsStore()

const sortBy: Ref<SortItem[]> = ref([{ key: 'type', order: "asc" }])
const itemValue = ref("id");
const { width } = useDisplay();
const distriTool: Ref<string[]> = ref([])

const facets = ref([
    "replicon",
    "type",
    "subtype",
    "Superkingdom",
    "phylum",
    "order",
    "family",
    "genus",
    "species",
])
const availableTaxo: Ref<string[]> = ref([
    "species",
    "genus",
    "family",
    "order",
    "phylum",
    "Superkingdom"
]);
const selectedTaxoRank = ref("phylum");

const headers = ref([
    { title: "Replicon", key: "replicon" },
    {
        title: "Type",
        key: "type",
    },
    {
        title: "Subtype",
        key: "subtype",
    },
    {
        title: "Accessions",
        key: "accession_in_sys",
        sortable: false
    }
])
const logTransform = computed(() => {
    return distriTool.value.includes('log')
})
const fullWidth = computed(() => {
    return distriTool.value.includes('fullwidth')
})
const computedHeaders = computed(() => {
    return [...headers.value, ...availableTaxo.value.map(taxo => {
        return {
            title: capitalize(taxo),
            key: taxo
        }
    })]
})

const computedWidth = computed(() => {
    const currentWidth = fullWidth.value ? width.value : width.value / 2
    return Math.max(currentWidth, 550);
});

const plotHeight = computed(() => {
    return computedWidth.value / 3;
    // return 500
});

const defaultDataTableServerProps = ref({
    showExpand: false
})

const dataTableServerProps = computed(() => {
    return {
        ...defaultDataTableServerProps.value,
        headers: computedHeaders.value,
        itemValue: itemValue.value
    }
})
const defaultBarPlotOptions = computed(() => {
    const y = logTransform.value ? { nice: true, grid: true, type: 'symlog' } : { nice: true, grid: true, type: "linear" }
    // const y = { nice: true, grid: true }
    return {
        x: { label: null, tickRotate: 45, ticks: 10 },
        y,
        color: { legend: true },
        width: computedWidth.value,
        height: plotHeight.value + 100,
    }
})

const computedSystemDistribution = computed(() => {
    if (facetStore.facets?.facetDistribution?.type) {
        return Object.entries(facetStore.facets.facetDistribution.type).map(([key, value]) => {
            return {
                type: key,
                // count: logTransform.value ? Math.log(value) : value 
                count: value
            }
        }).sort()
    } else { return [] }

})
const computedDistriSystemOptions = computed(() => {
    return {
        ...defaultBarPlotOptions.value,
        marginBottom: 100,
        marks: [
            // Plot.frame(),
            Plot.barY(
                toValue(computedSystemDistribution),
                {
                    y: "count", x: 'type', tip: true,
                    fill: "#6750a4",
                    sort: { x: "-y" },
                },

            ),
        ],
    };
});
const computedTaxonomyDistribution = computed(() => {
    if (facetStore.facets?.facetDistribution?.[selectedTaxoRank.value]) {
        return Object.entries(facetStore.facets.facetDistribution[selectedTaxoRank.value]).map(([key, value]) => {
            return {
                [selectedTaxoRank.value]: key,
                count: value
            }
        }).sort()
    } else { return [] }

})

const computedDistriTaxoOptions = computed(() => {
    return {
        ...defaultBarPlotOptions.value,
        marginBottom: 100,
        marks: [
            Plot.barY(
                toValue(computedTaxonomyDistribution),
                {
                    y: "count",
                    x: selectedTaxoRank.value,
                    tip: true,
                    fill: "#6750a4",
                    sort: { x: "-y" },
                }
            ),
        ],
    };
});
function capitalize(name: string) {
    const [first, ...rest] = name
    return first.toUpperCase() + rest.join('').toLowerCase();
}

function namesToCollapsibleChips(names: string[]) {
    return names.filter((it) => it !== "").map(it => ({ title: it }))
}

function namesToAccessionChips(names: string[]) {
    return namesToCollapsibleChips(names).map(it => {
        return { ...it, href: new URL(it.title, "http://toto.pasteur.cloud").toString() }
    })
}



</script>

<template>
    <v-card flat class="mb-2" color="transparent">
        <v-toolbar density="compact">
            <v-toolbar-title>Distributions</v-toolbar-title>
            <v-btn-toggle v-model="distriTool" multiple density="compact" rounded="false" variant="text" color="primary"
                class="mx-2">
                <v-btn icon="md:fullscreen" value="fullwidth"></v-btn>
                <v-btn icon="mdi-math-log" value="log"></v-btn>
            </v-btn-toggle>
        </v-toolbar>
        <v-row align="start" class="my-2">

            <v-col :cols="fullWidth ? 12 : 6">

                <v-card color="transparent" flat>
                    <v-expansion-panels>
                        <v-expansion-panel elevation="3">
                            <v-expansion-panel-title color="grey-lighten-4">Systems</v-expansion-panel-title>
                            <v-expansion-panel-text>
                                <PlotFigure :options="unref(computedDistriSystemOptions)" defer></PlotFigure>
                            </v-expansion-panel-text>
                        </v-expansion-panel>
                    </v-expansion-panels>
                </v-card>
            </v-col>
            <v-col :cols="fullWidth ? 12 : 6">
                <v-card flat color="transparent">
                    <v-expansion-panels>
                        <v-expansion-panel elevation="3">
                            <v-expansion-panel-title color="grey-lighten-4">
                                Taxonomic


                            </v-expansion-panel-title>
                            <v-expansion-panel-text>

                                <PlotFigure defer :options="unref(computedDistriTaxoOptions)"></PlotFigure>

                            </v-expansion-panel-text>
                        </v-expansion-panel>
                    </v-expansion-panels>
                </v-card>
            </v-col>
        </v-row>
    </v-card>
    <ServerDbTable title="RefSeq" db="refseq" :sortBy="sortBy" :facets="facets"
        :data-table-server-props="dataTableServerProps">
        <template #[`item.accession_in_sys`]="{ item }">
            <CollapsibleChips :items="namesToAccessionChips(item.accession_in_sys)"></CollapsibleChips>
        </template>
    </ServerDbTable>
</template>