Blast+ 网页实现

1.前端发送表单

表单数据包括

  • 序列信息

  • blast database

  • 其他可选的参数

  • 选择blastn或者blastp

      formInline: {
        sequence: '',
        database: '',
        evalue: '-evalue 1.0e-5 -num_alignments 10 -max_hsps 10',
        blastType: ''
      },

1.1提交表单数据前进行数据校验

  • 表单校验不成功,不能够提交

  • 校验成功后使用FormData封装表单数据

  • 打开遮罩层,阻止多次提交

  • 使用axios获取响应数据后,关闭遮罩层

    onSubmit () {
      this.$refs.blastForm.validate((valid) => {
        if (valid) {
          const formData = new FormData()
          for (var key in this.formInline) {
            formData.append(key, this.formInline[key])
          }
          this.showProcess = true
          request.post('/test', formData).then(
            (reponse) => {
              this.reponseData = reponse.data
              this.showProcess = false
            }
          )
        } else {
          return false
        }
      })
    }

2.响应数据渲染

封装一个show.vue子组件,子组件中使用props获取父组件传递的响应数据,子组件中reponseData初始化值为空

在渲染序列比对情况时候,遇到对不齐的情况;主要是由于没有使用等宽字体

  props: {
    reponseData: {
      default: () => {
        return [{
          query: 'CYP78A7',
          queryLength: '559',
          alignments: []
        }]
      }
    }

使用计算属性,将父组件的响应数据转换成需要渲染的数据

 computed: {
    ValidateReponse () {
      var newDataArray = []
      this.reponseData.forEach((item) => {
        var queryName = item.query
        var queryLength = item.queryLength
        var summaryTable = []
        var singleTable = []
        var AlignmentIf = ''
        if (item.alignments.length > 0) {
          AlignmentIf = true
          item.alignments.forEach((subject, index) => {
            summaryTable.push(
              {
                id: index + 1,
                subjectName: subject.subjectName,
                score: subject.score,
                evalue: subject.eValue,
                length: subject.subjectLength,
                identities: subject.identities,
                pairSequence: subject.pairSequence

              }
            )
            singleTable.push([{
              id: index + 1,
              subjectName: subject.subjectName,
              score: subject.score,
              evalue: subject.eValue,
              length: subject.subjectLength,
              identities: subject.identities,
              pairSequence: subject.pairSequence
            }])
          })
        } else {
          AlignmentIf = false
        }
        newDataArray.push({
          queryName,
          queryLength,
          summaryTable,
          AlignmentIf,
          singleTable
        })
      })
      return newDataArray
    }
  }

3.后端node运行blast+

使用node运行系统命令,来执行blast+

3.1创建两个临时文件,用于存储序列信息和blast运行结果

  • 使用tmp模块

  var tmp = require('tmp')
  var queryFile = tmp.fileSync()
  var BlastOutFile = tmp.fileSync()
  //程序结束后,可以选择删除临时文件;或系统自动处理
  BlastOutFile.removeCallback()
  queryFile.removeCallback()

3.2运行系统命令

使用child_process模块运行子进程,调用execFile函数执行系统脚本

execFile函数参数:

  • 系统脚本所在绝对路径

  • 传递参数的数组

  • 回调函数,判断脚本是否执行成功

var callfile = require('child_process')
  callfile.execFile(
    '使用系统脚本的绝对路径',
    [
      queryFile.name,
      BlastOutFile.name,
      req.body.blastType,
      req.body.database,
      req.body.evalue
    ],  (error, stdout, stderr) => {
      if (error) {
        console.log(error)
        rep.send('error')
        return
      }
      //读取blast结果
      BlastText = fs.readFileSync(BlastOutFile.name, 'utf-8')
      //解析blast outfmt 0 格式文件
      BlastJson = parseBlastText(BlastText)
      BlastOutFile.removeCallback()
      queryFile.removeCallback()
      rep.send(BlastJson)
    })

3.3解析Blast+ outfmt 0格式文件

  • 利用关键字Query=获取查询序列所在行号

  • 关键字>获取匹配序列所在行号

  • 匹配序列之间,间隔行数是固定的

脚本地址

4.演示地址

http://cotton.hzau.edu.cn/web/test#/blast/query

参考

  1. 转换Blast输出文件

Last updated