一、背景
接收公司特定蛋白检测项目后,原项目中log5p算法是C#实现的,拟合曲线不稳定,每次拟合出来的数据都偏差比较大,且逻辑异常繁杂,和多个同事一起修改仍达不到满意效果。于是想对该部分功能进行重构。通过调研python支持曲线拟合功能,但是C#对python的接入并不友好,只能通过开放web访问的功能,供其他语言调用。目前该功能稳定的运行在产品中
二、实现
拟合公式采用Log5P的公式,样本数据至少要5组才能拟合成功。该脚本运行起来后,可以get方法访问。通过浏览器就可以进行测试。getargs接口返回通过样本数据拟合出来的5个参数,getpotency接口是通过5参数和测试数据y值推算x值,getrange接口是通过5参数和测试数据x值推算y值。
# This is a sample Python script.
# Press Shift+F10 to execute it or replace it with your code.
# Press Double Shift to search everywhere for classes, files, tool windows, actions, and settings.
# def print_hi(name):
# # Use a breakpoint in the code line below to debug your script.
# print(f'Hi, {name}') # Press Ctrl+F8 to toggle the breakpoint.
#
#
# # Press the green button in the gutter to run the script.
# if __name__ == '__main__':
# print_hi('PyCharm')
# See PyCharm help at https://www.jetbrains.com/help/pycharm/
#from bottle import route, run, get, request
import numpy as np
from scipy.optimize import curve_fit
def func(x, a, b, c, d, e):
# result=a/(1+b*np.exp(-c*x))
result = (d - c) / pow([1 + pow((x / a), b)], e) + c;
return result[0]
def func2(x, a, b, c, d, e):
# result=a/(1+b*np.exp(-c*x))
result = (d - c) / pow((1 + pow((x / a), b)), e) + c;
return result
def funcrev(y, a, b, c, d, e):
# result=a/(1+b*np.exp(-c*x))
result2 = pow(pow((d - c) / (y - c), 1 / e) - 1, 1 / b) * a
return result2
@route('/getargs')
def getargs():
xstr=request.query.x
print(xstr)
xstr=xstr.replace('[','')
xstr = xstr.replace(']', '')
xstrarray = xstr.split(',')
x=[]
for i in range(len(xstrarray)):
x.append(float(xstrarray[i]))
# x=np.array(x)
# x=x.astype(np.float)
ystr=request.query.y
print(ystr)
ystr = ystr.replace('[', '')
ystr = ystr.replace(']', '')
ystrarray = ystr.split(',')
y = []
for i in range(len(ystrarray)):
y.append(float(ystrarray[i]))
# y = np.array(y)
print('xxxxxxxxxxxxxxxxxxxxxx')
print(x)
print(y)
# y = x.astype(np.float)
c0 = np.array([205.0, 1.05, max(y) * 1.1, min(y) * 0.8, 0.001]) # 一组初值
p_est, err_est = curve_fit(func, x, y, c0, maxfev=100000000)
print("sssssssssssssssss")
list = ','.join(str(i) for i in p_est)
return list
@route('/getpotency')
def getpotency():
y =(float)(request.query.y)
a = (float)(request.query.a)
b = (float)(request.query.b)
c = (float)(request.query.c)
d = (float)(request.query.d)
e = (float)(request.query.e)
print('yyyyyyyy')
print(y)
print(a)
print(b)
print(c)
print(d)
print(e)
vv= funcrev(y, a, b, c, d, e)
print('vv')
print(vv)
return str(vv)
@route('/getrange')
def getrange():
x = (float)(request.query.x)
a = (float)(request.query.a)
b = (float)(request.query.b)
c = (float)(request.query.c)
d = (float)(request.query.d)
e = (float)(request.query.e)
print('xxxxx')
print(x)
print(a)
print(b)
print(c)
print(d)
print(e)
print(type(x))
print(type(x))
print(type(x))
print(type(x))
print(type(x))
print(type(x))
ss = func2(x, a, b, c, d, e)
print('vv')
print(ss)
return str(ss)
run(host='localhost',port=9527,debug=True)