如何利用vue实现波谱拟合详解


Posted in Javascript onNovember 05, 2020

主页面-功能介绍

小白初入职场第一篇总结,废话比较多,求轻喷~

如何利用vue实现波谱拟合详解

波谱拟合用来对某种材料或物质的谱图进行识别和分析,每种物质可以有多种成分,每种成分用component1、component2...表示,用Add another component和Remove component来控制每种成分的增加和删除,每种成分由多种原子核构成,即nuclei,用Add nucleus和Remove nucleus来控制每种成分内原子核数量,每新增一个原子核,波谱就会分裂一次,谱峰数量由(1->2->4->8...)依次分裂。另外可以通过更改默认参数,改变波谱形态,成分参数中:Relative amount表示每种成分占绘图分量的百分比,百分比之和不超过100,giso用来计算分裂的中心位置,LineWidth用来控设置谱峰到谱谷的宽度,%Lorentzian表示谱峰形态,一共两种形态,高斯和洛伦兹,两者之和为100;原子核参数:No of equivalent nuclei用来改变原子核个数,如果一种成分内包含很多个一模一样的参数时,就可以通过改变这个参数实现,Nuclear spin用来改变原子核种类,Hyperfine用来设置分裂后两峰之间的宽度。

再来一张图:

如何利用vue实现波谱拟合详解

每种成分数量和参数、每种成分内每种原子核数量和参数设置好后,对数据进行处理,由三种结果,卷积、积分、二重积分,那就来看看数据的处理逻辑吧~

如何利用vue实现波谱拟合详解

从数据流角度,主要进行三步处理:数据->数据裂变->光谱计算->绘图,左边是算法实现所需的参数、右边是对数据及每个步骤的描述。

代码实现

遇到一个坑,一开始写demo的时候用的vue+Ant design of vue,在select等其他组件的使用上都是正常的,但是在input number中就很变态了,给input number绑定的change事件,用户在输入两位以上数据的时候,change事件会触发两次!!!想避免这个问题,于是用blur事件,问题又来了,因为这个页面中组件的生成和删除需要动态渲染,并且根据前面的介绍很容易知道组件的渲染是有两层结构的,那么在用户进行点击或输入操作的时候,就需要传递一个参数(用来定位是哪个component以及每个component下面对应的某一个nucle等等),能力有限( ?□? )目前我没有找到解决办法,于是转elementUI框架。

组件的动态渲染用了一个比较巧妙的办法,一开始我打算用render来写,后来从部门大神那里学到通过遍历列表进行渲染,脑子之间还是有差距的。。。

<div v-for="(Con, i) in componentList" :key="Con[i]"><strong>Component {{i+1}}.</div>

同理原子核的动态渲染也是这么实现的:

<div v-for="(li, j) in nucleusList[i]" :key="li[j]">{{j+1}}. No of equivalent nuclei:</div>

然后每次增加和删除只需要操作数组列表的长度即可~

各参数的绑定:component中参数均使用一维数组,chenge事件需传递一维数组的下标,component内的nucleui均使用二维数组,change事件需传递二维数组的下标。

以上介绍参数定义,接下来是数据处理:

// 首先计算裂变数据
stickspectrum (w) {
   // console.log('组件信息', w)
   const stick = new Array(2) // 返回包含stick[0]的stick光谱数组,stick[1]是位置
   stick[0] = new Array()// 光谱强度
   stick[1] = new Array()// 光谱位置
   stick[1][0] = this.h * this.frequency / (this.r[w].g * this.mu)

   for (var j = 0; j < this.r[w].equiv.length; j++) {
    // console.log('stick[0].length', stick[0].length) //分裂后的光谱数据长度
    for (var i = stick[0].length - 1; i >= 0; i--) {
     stick[0][i] /= Math.pow((2 * this.r[w].spin[j] + 1), this.r[w].equiv[j])
     stick[1][i] -= this.r[w].equiv[j] * this.r[w].spin[j] * this.r[w].hfc[j]

     for (var k = 0; k < 2 * this.r[w].equiv[j] * this.r[w].spin[j]; k++) {
      stick[1].splice(i + k + 1, 0, stick[1][i] + this.r[w].hfc[j] * (k + 1))
      stick[0].splice(i + k + 1, 0, 0)
     }
     for (var k = 0; k < this.r[w].equiv[j]; k++) {
      for (var m = i + 2 * this.r[w].spin[j] * k; m >= i; m--) {
       for (var ii = 0; ii < 2 * this.r[w].spin[j]; ii++) {
        stick[0][m + ii + 1] += stick[0][m]
       }
      }
     }
    }
   }
   return stick
  },
// 再对裂变后的数据进行光谱计算
spectrum (stick) {
   let xmin = Infinity; let xmax = 0
   for (var k = 0; k < this.r.length; k++) {
    xmin = Math.min(Math.min.apply(Math, stick[k][1]) - 10 * this.r[k].width, xmin)
    xmax = Math.max(Math.max.apply(Math, stick[k][1]) + 10 * this.r[k].width, xmax)
   }
   const tmp = xmax - xmin
   xmax += tmp * 0.05
   xmin -= tmp * 0.05
   const step = (xmax - xmin) / (this.No_integers - 1)
   for (let i = 0; i < this.No_integers; i++) {
    this.XY[0][i][0] = xmin + step * i
    this.XY[0][i][1] = 0
    this.XYint[0][i][0] = this.XY[0][i][0]
    this.XYint[0][i][1] = 0
    this.XYdoubleint[0][i][0] = this.XY[0][i][0]
    this.XYdoubleint[0][i][1] = 0
   }

   for (let k = 0; k < this.r.length; k++) { // 分量累加
    const sticks = new Array(this.No_integers)
    for (var i = 0; i < stick[k][0].length; i++) {
     var j = Math.round((stick[k][1][i] - xmin) / step)
     sticks[j] = sticks[j] ? sticks[j] + stick[k][0][i] : stick[k][0][i]
    }

    const tmp = new Array(this.No_integers)// 第一种光谱绘图位置数据
    let ind = 0
    for (var i = 0; i < this.No_integers; i++) {
     if (sticks[i]) { // 建立峰值索引——sticks[i]===1即峰值所在。
      tmp[ind] = i
      ind++
     }
    }
    const tmpint = new Array(this.No_integers) // 用来保存每个分量的积分
    const tmpdoubleint = new Array(this.No_integers) // 用来保存每个分量的二重积分
    for (var i = 0; i < this.No_integers; i++) tmpint[i] = 0
    tmpdoubleint[0] = 0
    const rwid = Number(this.r[k].width)
    const rwid2 = Math.pow(rwid, 2)
    const lortmp = Number(this.r[k].percent) * Number(this.r[k].lor) / 100 * Math.sqrt(3) / Math.PI // 洛伦兹线乘积
    const gaustmp = Number(this.r[k].percent) * (100 - Number(this.r[k].lor)) / 100 * Math.sqrt(2 / Math.PI) // 高斯线乘法器

    for (let i = 0; i < this.No_integers; i++) {
     for (let j = 0; j < ind; j++) {
      const delta = this.XY[0][i][0] - this.XY[0][tmp[j]][0]
      const delta2 = Math.pow(delta, 2)
      if ((rwid > step && Math.abs(-0.5 * rwid - delta) < 0.5 * step) || (rwid < step && -0.5 * rwid - delta > 0 && -0.5 * rwid - delta < step)) {
       this.XY[0][i][1] += sticks[tmp[j]] * (lortmp * 0.5 / rwid2 + gaustmp * 2 / Math.sqrt(Math.E) / rwid2)
      } else if ((rwid > step && Math.abs(0.5 * rwid - delta) < 0.5 * step) || (rwid < step && delta - 0.5 * rwid > 0 && delta - 0.5 * rwid < step)) {
       this.XY[0][i][1] -= sticks[tmp[j]] * (lortmp * 0.5 / rwid2 + gaustmp * 2 / Math.sqrt(Math.E) / rwid2)
      } else {
       this.XY[0][i][1] += sticks[tmp[j]] * (gaustmp * (-4) / rwid / rwid2 * delta * Math.exp(-2 * delta2 / rwid2) + lortmp * (-delta) * rwid / Math.pow((delta2 + 3 / 4 * rwid2), 2)) // 其他情况下的正常计算,高斯+洛伦兹
      }
      this.dataarray = [this.XY, this.XYint, this.XYdoubleint]
      tmpint[i] += sticks[tmp[j]] * (gaustmp * Math.exp(-2 * delta2 / rwid2) / rwid + lortmp / 2 / rwid / (0.75 + delta2 / rwid2)) // 高斯+洛伦兹积分-明确计算以避免积分误差
     }
    }
    for (let j = 1; j < this.No_integers; j++) {
     tmpdoubleint[j] = tmpdoubleint[j - 1] + step * (tmpint[j] + tmpint[j - 1]) / 2
    } // 二重积分
    // console.log('二重积分', tmpdoubleint)

    const mm = tmpdoubleint[this.No_integers - 1] / Number(this.r[k].percent) // 有多少积分高于理论(只发生在非常尖锐的线)
    for (let j = 1; j < this.No_integers; j++) {
     this.XYdoubleint[0][j][1] += mm > 1 ? tmpdoubleint[j] / mm : tmpdoubleint[j] // 第三种频谱数据 如果二重积分高于理论,将其标准化
     this.XYint[0][j][1] += tmpint[j] // 第二种频谱数据
    }
   }
   // console.log('XYint', this.XYint[0])
  },

计算完成的光谱,返回三种数据XY、XYint、XYdouble,然后就是绘图~

到此这篇关于如何利用vue实现波谱拟合的文章就介绍到这了,更多相关vue实现波谱拟合内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Javascript 相关文章推荐
HTML中Select不用Disabled实现ReadOnly的效果
Apr 07 Javascript
疯狂Jquery第一天(Jquery学习笔记)
May 11 Javascript
jquery 关于event.target使用的几点说明介绍
Apr 26 Javascript
理解javascript定时器中的单线程
Feb 23 Javascript
深入理解在JS中通过四种设置事件处理程序的方法
Mar 02 Javascript
基于AGS JS开发自定义贴图图层
Mar 31 Javascript
基于Vue生产环境部署详解
Sep 15 Javascript
搭建vue开发环境
Jul 19 Javascript
layDate日期控件使用方法详解
Nov 15 Javascript
vue 之 css module的使用方法
Dec 04 Javascript
layer父页获取弹出层输入框里面的值方法
Sep 02 Javascript
解决vue单页面多个组件嵌套监听浏览器窗口变化问题
Jul 30 Javascript
关于Vue中$refs的探索浅析
Nov 05 #Javascript
JavaScript 实现轮播图特效的示例
Nov 05 #Javascript
nuxt 服务器渲染动态设置 title和seo关键字的操作
Nov 05 #Javascript
nuxt 每个页面head标签内容设置方式
Nov 05 #Javascript
JavaScript TAB栏切换效果的示例
Nov 05 #Javascript
nuxt 页面路由配置,主页轮播组件开发操作
Nov 05 #Javascript
JS时间戳与日期格式互相转换的简单方法示例
Jan 30 #Javascript
You might like
PHP中基于ts与nts版本- vc6和vc9编译版本的区别详解
2013/04/26 PHP
解析PHP无限级分类方法及代码
2013/06/21 PHP
10 个经典PHP函数
2013/10/17 PHP
ThinkPHP3.2框架使用addAll()批量插入数据的方法
2017/03/16 PHP
Laravel框架路由和控制器的绑定操作方法
2018/06/12 PHP
java解析json方法总结
2019/05/16 PHP
javascript 一些用法小结
2009/09/11 Javascript
Extjs4 消息框去掉关闭按钮(类似Ext.Msg.alert)
2013/04/02 Javascript
jquery实现带复选框的表格行选中删除时高亮显示
2013/08/01 Javascript
Javascript中的回调函数和匿名函数的回调示例介绍
2014/05/12 Javascript
jquery 实现input输入什么div图层显示什么
2014/06/15 Javascript
使用JQuery实现Ctrl+Enter提交表单的方法
2015/10/22 Javascript
JS实现的手机端精简幻灯片效果
2016/09/05 Javascript
js仿淘宝评价评分功能
2017/02/28 Javascript
Node.js常用工具之util模块
2017/03/09 Javascript
JavaScript中附件预览功能实现详解(推荐)
2017/08/15 Javascript
vue实现Excel文件的上传与下载功能的两种方式
2019/06/28 Javascript
如何在项目中使用log4.js的方法步骤
2019/07/16 Javascript
layer.msg()去掉默认时间,实现手动关闭的方法
2019/09/12 Javascript
JavaScript实现抖音罗盘时钟
2019/10/11 Javascript
Python面向对象特殊成员
2017/04/24 Python
对python中的高效迭代器函数详解
2018/10/18 Python
pycharm访问mysql数据库的方法步骤
2019/06/18 Python
Python调用jar包方法实现过程解析
2020/08/11 Python
丝芙兰中国官方商城:SEPHORA中国
2018/01/10 全球购物
飞利浦法国官网:Philips法国
2019/07/10 全球购物
新东网科技Java笔试题
2012/07/13 面试题
总结表彰大会主持词
2014/03/26 职场文书
勤俭节约演讲稿
2014/05/08 职场文书
会计求职自荐信
2014/06/20 职场文书
中华在我心中演讲稿
2014/09/13 职场文书
结婚保证书(三从四德)
2015/02/26 职场文书
求职自我推荐信
2015/03/24 职场文书
法定代表人免职证明
2015/06/24 职场文书
庆七一主持词
2015/06/29 职场文书
vue 实现弹窗关闭后刷新效果
2022/04/08 Vue.js