Skip to content
Snippets Groups Projects
Forked from Statistical-Genetics / jass
61 commits behind the upstream repository.
gwas.vue 5.66 KiB
<template>
  <div>
    <div class="header">
      <h1>Genome-wide analysis parameters</h1>
      <p>
        Please select the phenotypes you want to analyze jointly with the Omnibus test. A research box bellow allows you to query our current database. The maximum number of trait that can be analyzed jointly is 64 phenotypes. Computation time for a large number of trait can take up to half an hour.
      </p>
    </div>

    <section>
      <h2>Select an ancestry:</h2>
      <div class="init-table-card-list">
        <v-card
          v-for="table in initTables"
          :key="table.tableName"
          class="init-table-card"
          :class="{ 'selected-table': selectedInitTable === table.tableName }"
          :color="selectedInitTable === table.tableName ? 'blue lighten-4' : ''">
          <v-card-title>{{ table.name }}</v-card-title>
          <v-card-text class="row">
            <div
              v-sanitized-html="$md.render(table.desc)"
              class="col-12 pt-0 pb-0"
            ></div>
            <div class="col-12 col-md-6 pt-0">
              <strong>{{ table.nb_snps.toLocaleString() }}</strong>
              SNPS
            </div>
            <div class="col-12 col-md-6 pt-0 order-2">
              <strong>{{ table.nb_phenotypes.toLocaleString() }}</strong>
              phenotypes
            </div>
            <div class="col-12 col-md-6 pt-0 order-1">
              assembly: <strong>{{ table.assembly.toLocaleString() }}</strong>
            </div>
            <div class="col-12 col-md-6 pt-0 order-2">
              ancestry: <strong>{{ table.ancestry.toLocaleString() }}</strong>
            </div>
          </v-card-text>
          <v-card-actions class="card-buttons">
            <v-btn class="button" color="primary" @click="selectAncestry(table.tableName)">
              Select this ancestry
            </v-btn>
          </v-card-actions>
        </v-card>
      </div>
    </section>

    <section id="phenotypes-section" v-show="phenotypes.length">
      <h2>Select at least two GWASs to be analyzed jointly:</h2>
      <v-data-table
        v-model="selectedRows"
        :headers="headers"
        :items="phenotypes"
        :items-per-page="10"
        item-key="id"
        class="elevation-1"
        :search="search"
        show-select
        checkbox-color="primary"
        unselectable
        @current-items="current = $event"
        @item-selected="bulkSelect">
        <template #top>
          <v-text-field
            v-model="search"
            label="Search"
            class="mx-4">
          </v-text-field>
        </template>

        <template v-slot:item.ref="{ item }">
          <a class="ref-link" :href="item.ref_link" target="_blank" rel="noreferrer">{{ item.ref }}</a>
        </template>
      </v-data-table>
      <div class="start-button">
        <v-btn class="button" color="primary" :disabled="selectedRows.length <= 1" @click="runAnalysis()">
          Start analysis
        </v-btn>
      </div>
    </section>
  </div>
</template>

<script>
export default {
  data() {
    return {
      selectedInitTable: '',
      headers: [
        { text: 'Outcome', value: 'outcome' },
        { text: 'Full name', value: 'full_name' },
        { text: 'Consortium', value: 'consortium' },
        { text: 'Type', value: 'typ' },
        { text: 'Ref', value: 'ref' },
      ],
      search: '',
      phenotypes: [],
      selectedRows: [],
    }
  },
  computed: {
    initTables() { return this.$store.state.initTables }
  },
  methods: {
    selectAncestry(initTableName) {
      if (this.selectedInitTable === initTableName) return
      this.selectedInitTable = initTableName
      this.$axios.$post('/phenotypes', { initTableName })
        .then(phenotypes => {
          this.phenotypes = phenotypes
        })
        .then(() => {
          // Scroll to the phenotype table after it appeared
          document
            .getElementById("phenotypes-section")
            .scrollIntoView({
              behavior: 'smooth',
              block: 'start',
              inline: 'nearest'
            })
        })
    },
    bulkSelect({ item: b, value }) {
      const { selectedRows, current, shiftKeyOn } = this;
      if (selectedRows.length === 1 && value === true && shiftKeyOn) {
        const [a] = selectedRows;
        let start = current.findIndex((item) => item === a);
        let end = current.findIndex((item) => item === b);
        if (start - end > 0) {
          const temp = start;
          start = end;
          end = temp;
        }
        for (let i = start; i <= end; i++) {
          selectedRows.push(current[i]);
        }
      }
    },
    runAnalysis() {
      const { selectedRows, $axios } = this;
      const phenotypeIds = {
        phenotypeID: selectedRows.map((phenotype) => { return phenotype.id }),
        initTableName: this.selectedInitTable
      };

      $axios.$post('/projects', phenotypeIds).then(response => {
        this.$router.push('/projects/' + response.id)
      })
    },
  }
}
</script>

<style scoped>
.header {
  display: flex;
  flex-flow: column wrap;
  align-items: center;
  margin: 30px;
}

.header h1 {
  text-align: center;
}

.header p {
  max-width: 80%;
  text-align: center;
}

section {
  margin: 40px 0;
}

section h2 {
  margin-bottom: 20px;
  text-align: center;
}

.init-table-card-list {
  display: flex;
  flex-flow: row wrap;
  gap: 20px;
  justify-content: center;
}

.init-table-card {
  width: 600px;
}

.init-table-card .v-card__title {
  word-break: normal;
}

.init-table-card .v-card__text {
  font-size: 16px;
}

.card-buttons {
  justify-content: end;
}

.button {
  text-transform: none;
}

.start-button {
  text-align: center;
  margin-top: 20px;
}

.ref-link {
  font-size: inherit;
}
</style>