parent
304a758053
commit
d48fc6ebe8
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,389 @@ |
||||
|
||||
from dataclasses import dataclass |
||||
from pathlib import Path |
||||
from typing import List, Any, Callable |
||||
from pubsub import pub |
||||
import numpy as np |
||||
from enum import Enum |
||||
import struct |
||||
import math |
||||
import time |
||||
|
||||
from myconfig import TOKEN, DATA_DIR, FILE_MARK, OUTPUT_DIR, CAL_DIR |
||||
from myconfig import PURE_WATER_FNAME, SAVE_EXT_NAME |
||||
from myexception import MyException |
||||
from mypath import MyDir |
||||
|
||||
class WorkMode(Enum): |
||||
FILEMODE=1 |
||||
DEVICEMODE=2 |
||||
|
||||
class AlgorithMode(Enum): |
||||
A720=1 |
||||
PureWater=2 |
||||
|
||||
class PureWaterData: |
||||
wavelength=[360.0, 365.0, 370.0, 375.0, 380.0, 385.0, 390.0, 395.0, 400.0, 405.0, 410.0, 415.0, 420.0, 425.0, 430.0, 435.0, 440.0, 445.0, 450.0, 455.0, 460.0, 465.0, 470.0, 475.0, 480.0, 485.0, 490.0, 495.0, 500.0, 505.0, 510.0, 515.0, 520.0, 525.0, 530.0, 535.0, 540.0, 545.0, 550.0, 555.0, 560.0, 565.0, 570.0, 575.0, 580.0, 585.0, 590.0, 595.0, 600.0, 605.0, 610.0, 615.0, 620.0, 625.0, 630.0, 635.0, 640.0, 645.0, 650.0, 655.0, 660.0, 665.0, 670.0, 675.0, 680.0, 685.0, 690.0, 695.0, 700.0, 705.0, 710.0, 715.0, 720.0, 725.0] |
||||
coeff=[0.0158, 0.0149, 0.0142, 0.0133, 0.0125, 0.0119, 0.0114, 0.0108, 0.0104, 0.0101, 0.0098, 0.0096, 0.00924, 0.00928, 0.00925, 0.0094, 0.01025, 0.01121, 0.01272, 0.01292, 0.01299, 0.01311, 0.0135, 0.0142, 0.0154, 0.0161, 0.0174, 0.0196, 0.0226, 0.0277, 0.0345, 0.0416, 0.0428, 0.0435, 0.0451, 0.0469, 0.049, 0.0526, 0.058, 0.061, 0.0632, 0.0655, 0.0708, 0.0784, 0.0908, 0.1111, 0.1362, 0.1682, 0.2234, 0.2587, 0.2653, 0.2687, 0.2764, 0.2842, 0.2924, 0.302, 0.3116, 0.3257, 0.3407, 0.3717, 0.4107, 0.4296, 0.4396, 0.4486, 0.4656, 0.4866, 0.5166, 0.5595, 0.6245, 0.7045, 0.8275, 1.0075, 1.2315, 1.4894] |
||||
|
||||
@dataclass |
||||
class SerialPort : |
||||
port: str = None |
||||
baudrate: int = None |
||||
bytesize: int = None |
||||
parity: str =None |
||||
stopbit: int =None |
||||
|
||||
def __post_init__(self): |
||||
pass |
||||
|
||||
def set_serial_port_(self, sp:dict): |
||||
self.port = sp['port'] |
||||
self.baudrate = sp['baudrate'] |
||||
self.bytesize = sp['bytesize'] |
||||
self.parity = sp['parity'] |
||||
self.stopbit = sp['stopbit'] |
||||
pass |
||||
|
||||
|
||||
@dataclass |
||||
class Registers : |
||||
slaveaddress: int |
||||
functioncode: int |
||||
DataBeginAddress: int |
||||
SNAddress: int |
||||
SNLen: int |
||||
WLBeginAddress: int |
||||
count: int |
||||
wavelengthBuf: bytes |
||||
intensityBuf: bytes |
||||
|
||||
def __post_init__(self): |
||||
pass |
||||
|
||||
def set_register(self, rg:dict): |
||||
self.DataBeginAddress = rg['DataBeginAddress'] |
||||
self.SNAddress = rg['SNAddress'] |
||||
self.SNLen = rg['SNLen'] |
||||
self.WLBeginAddress = rg['WLBeginAddress'] |
||||
self.count = rg['count'] |
||||
self.functioncode = rg['functioncode'] |
||||
self.slaveaddress = rg['slaveaddress'] |
||||
|
||||
pass |
||||
|
||||
@dataclass |
||||
class LogSetting : |
||||
LogInterval: int =None |
||||
RefreshInterval: int =None |
||||
def set_log_setting(self, dct:dict): |
||||
self.LogInterval = dct['LogInterval'] |
||||
self.RefreshInterval = dct['RefreshInterval'] |
||||
|
||||
|
||||
@dataclass |
||||
class PlotSetting : |
||||
LineBegin: int =None |
||||
LineInterval: int =None |
||||
def set_plot_setting(self, dct:dict): |
||||
self.LineBegin = dct['LineBegin'] |
||||
self.LineInterval = dct['LineInterval'] |
||||
|
||||
@dataclass |
||||
class Retrieve : |
||||
beginWL: int =None |
||||
endWL: int=None |
||||
interval: int=None |
||||
def set_retrieve(self, dct:dict): |
||||
self.beginWL = dct['beginWL'] |
||||
self.endWL = dct['endWL'] |
||||
self.interval = dct['interval'] |
||||
|
||||
@dataclass |
||||
class Algorithm : |
||||
A720: int =None |
||||
PureWater: int =None |
||||
def set_algorithm(self, dct:dict): |
||||
self.A720 = dct['A720'] |
||||
self.PureWater = dct['PureWater'] |
||||
|
||||
@dataclass |
||||
class ConfigViper : |
||||
SN: str = None |
||||
lightPath: float = None |
||||
mode:WorkMode = None |
||||
filePath: Path = None |
||||
rawWavelength: list = None |
||||
rawIntensity: list = None |
||||
Wavelength: list = None |
||||
Intensity: list = None |
||||
# raw_wavelength_np = np.array([]) |
||||
purewaterWavelength: list = None |
||||
purewaterAttenuation: list = None |
||||
purewaterAttAfterInterp: np.ndarray = None |
||||
outputWavelength: list = None |
||||
beginSite:int =None |
||||
endsite:int = None |
||||
measureTime:str =None |
||||
retrieve: Retrieve = None |
||||
algorithm: Algorithm = None |
||||
serailPort: SerialPort = None |
||||
register: Registers = None |
||||
logSetting: LogSetting = None |
||||
plotSetting: PlotSetting = None |
||||
absorptionCoef:list =None |
||||
|
||||
def __post_init__(self): |
||||
self.retrieve = Retrieve() |
||||
self.algorithm = Algorithm() |
||||
pass |
||||
|
||||
|
||||
class MyViper(object): |
||||
def __init__(self, sn: str = None): |
||||
self.viper = ConfigViper(SN=sn) |
||||
self.cfg= None |
||||
self.file_lst =[] |
||||
self.mydir = MyDir() |
||||
pass |
||||
|
||||
def set_SN(self, sn :str): |
||||
self.viper.SN = sn |
||||
self.__prepare_for_save() |
||||
|
||||
def set_mode(self, mode:WorkMode=WorkMode.FILEMODE): |
||||
self.viper.mode = mode |
||||
if self.viper.mode == WorkMode.FILEMODE: |
||||
pass |
||||
if self.viper.mode == WorkMode.DEVICEMODE: |
||||
self.viper.serailPort =SerialPort() |
||||
self.viper.serailPort.set_serial_port_( self.cfg['comsetting']) |
||||
self.viper.register =Registers() |
||||
self.viper.register.set_register( self.cfg['register']) |
||||
pass |
||||
|
||||
def set_cfg_viper(self, cfg: dict): |
||||
''' cfg 从config.yaml 读出来的数据 ''' |
||||
self.cfg = cfg |
||||
if self.viper.SN != cfg['device']['UISN']: |
||||
raise Exception(f" 波长 不匹配") |
||||
self.viper.lightPath= cfg['device']['UIPath'] |
||||
self.viper.algorithm.set_algorithm( cfg['algorithm'] ) |
||||
self.viper.retrieve.set_retrieve(cfg['retrieve'] ) |
||||
self.viper.logSetting =LogSetting() |
||||
self.viper.logSetting.set_log_setting(cfg['logsetting'] ) |
||||
self.viper.plotSetting =PlotSetting() |
||||
self.viper.plotSetting.set_plot_setting(cfg['plotsetting'] ) |
||||
# if self.viper.mode == WorkMode.FILEMODE: |
||||
# pass |
||||
# if self.viper.mode == WorkMode.DEVICEMODE: |
||||
# self.viper.serailPort =SerialPort() |
||||
# self.viper.serailPort.set_serial_port_( cfg['comsetting']) |
||||
# self.viper.register =Registers() |
||||
# self.viper.register.set_register( cfg['register']) |
||||
# pass |
||||
pass |
||||
|
||||
def set_retrieve(self, rtv:dict ): |
||||
self.viper.retrieve.set_retrieve(rtv ) |
||||
pass |
||||
|
||||
def set_raw_wavelength(self, raw_wavelength ): |
||||
if self.viper.retrieve is None: |
||||
return |
||||
self.viper.rawWavelength = [float(i) for i in raw_wavelength] |
||||
self.get_begin_end() |
||||
|
||||
pass |
||||
|
||||
def set_raw_intensity(self, sn, time_str, intensity): |
||||
if self.viper.retrieve is None: |
||||
return |
||||
if sn != self.viper.SN : |
||||
raise MyException(f" 数据的波长 [{sn}] 与系统波长 [{self.viper.SN}] 不匹配 ") |
||||
|
||||
# 取有效波长范围数据 ,因为浊度校正须在720nm左右,去掉720以后波长 |
||||
intensity = intensity[self.viper.beginSite:self.viper.endsite] |
||||
|
||||
# 赋值,并转为浮点 |
||||
self.viper.rawIntensity = [float(i) for i in intensity ] |
||||
|
||||
# 浊度校正 |
||||
data = self.correction_turbidity( np.array(self.viper.rawIntensity) ) |
||||
|
||||
|
||||
# 计算 吸收系数 |
||||
data = data * (1000 * math.log(10,math.e) / self.viper.lightPath ) |
||||
|
||||
|
||||
# 对纯水系数系数进行校正 |
||||
data = self.correction_pure_water( data ) |
||||
|
||||
data = data.tolist() |
||||
self.viper.measureTime = time_str |
||||
self.viper.absorptionCoef = data |
||||
|
||||
# 分发数据 |
||||
self.distribute_data(self.viper.measureTime,self.viper.absorptionCoef) |
||||
|
||||
pass |
||||
|
||||
def set_pure_water(self,wavelength, atten): |
||||
self.viper.purewaterWavelength = [float(i) for i in wavelength] |
||||
self.viper.purewaterAttenuation = [float(i) for i in atten] |
||||
print(f"== {self.viper.purewaterWavelength}") |
||||
print(f"== {self.viper.purewaterAttenuation}") |
||||
if self.viper.rawWavelength is None: |
||||
raise MyException(f" 没有波长数据。") |
||||
self.interpo_pure_water() |
||||
self.__prepare_for_save() |
||||
|
||||
def interpo_pure_water(self): |
||||
self.viper.purewaterAttAfterInterp = np.interp( |
||||
np.array(self.viper.outputWavelength), |
||||
np.array(self.viper.purewaterWavelength), |
||||
np.array(self.viper.purewaterAttenuation)) |
||||
pass |
||||
|
||||
def get_begin_end(self,) -> list: |
||||
# 读取配置文件 |
||||
for i in range(len(self.viper.rawWavelength)): |
||||
# print(f"i {i} {self.viper.rawWavelength[i]}") |
||||
if self.viper.rawWavelength[i] < self.viper.retrieve.beginWL \ |
||||
and self.viper.rawWavelength[i+1] > self.viper.retrieve.beginWL: |
||||
self.viper.beginSite = i+1 |
||||
pass |
||||
if self.viper.rawWavelength[i] < self.viper.retrieve.endWL \ |
||||
and self.viper.rawWavelength[i+1] > self.viper.retrieve.endWL: |
||||
self.viper.endsite = i+2 |
||||
break |
||||
self.get_output_wavelength() |
||||
msg = "起始波长 : " + \ |
||||
str(self.viper.outputWavelength[0]) + \ |
||||
" , 结束波长 : " + str(self.viper.outputWavelength[-1]) |
||||
self.__set_msg("notice", msg) |
||||
pub.sendMessage(self.msg) |
||||
|
||||
def get_output_wavelength(self,): |
||||
self.viper.outputWavelength = self.viper.rawWavelength[self.viper.beginSite:self.viper.endsite] |
||||
pass |
||||
pass |
||||
|
||||
# def deal_sn_time_data(self, sn, time_str, data): |
||||
# if sn!= self.viper.SN: |
||||
# raise Exception(f" wrong SN file") |
||||
|
||||
# # 浊度校正 |
||||
# data = self.correction_turbidity( np.array(data) ) |
||||
|
||||
# # 取有效波长范围数据 |
||||
# data = data[self.viper.beginSite:self.viper.endsite] |
||||
|
||||
# # 计算 吸收系数 |
||||
# data = data * (1000 * math.log(10,math.e) / self.viper.lightPath ) |
||||
|
||||
# # 对纯水系数系数进行校正 |
||||
# data = self.correction_pure_water( data ) |
||||
|
||||
# data = data.tolist() |
||||
# self.viper.measureTime = time_str |
||||
# self.viper.absorptionCoef = data |
||||
|
||||
# self.__set_msg( "data", {"time":time_str, "data":data } ) |
||||
# pub.sendMessage("update", msg=self.msg) |
||||
|
||||
# # 保存数据 ??? |
||||
# self.mydir.setContent(self.viper.absorptionCoef,TOKEN,self.viper.measureTime) |
||||
# self.mydir.writeContent() |
||||
|
||||
def distribute_data(self, time_str, data, mode =0): |
||||
self.__set_msg( "data", {"time":time_str, "data":data } ) |
||||
pub.sendMessage("update", msg=self.msg) |
||||
|
||||
# 保存数据 ??? |
||||
self.mydir.setContent(self.viper.absorptionCoef,TOKEN,self.viper.measureTime) |
||||
self.mydir.writeContent() |
||||
if mode == 1: |
||||
print(f" \ |
||||
wavelenght : {self.viper.outputWavelength[0]} \ |
||||
coef : {self.viper.absorptionCoef[0]} \ |
||||
purewater : {self.viper.purewaterAttAfterInterp[0]} \ |
||||
rawInt : {self.viper.rawIntensity[self.viper.beginSite]} \ |
||||
") |
||||
|
||||
def deal_measure_time_data(self, sn, res_time, res_data): |
||||
''' |
||||
# res_time ['2011-01-28 00:00:32', '2011-01-28 00:01:04', '2011-01-28 00:04:05', '2011-01-28 00:04:17'] |
||||
# res_data [ [[,,,]], [[,,,]], [[,,,]], [[,,,]]] 取 res_data[0] |
||||
''' |
||||
# log.info(f" -> time : {res_time}",__name__, "deal_one_measure_time_data") |
||||
# log.info(f" -> datalen : {len(res_data)} ",__name__, "deal_one_measure_time_data") |
||||
if sn != self.viper.SN: |
||||
raise MyException(f" wrong SN file {sn} !! [SN={self.viper.SN}]") |
||||
for i in range(len(res_time)): |
||||
self.set_raw_intensity( sn,res_time[i], res_data[i][0] ) |
||||
self.__set_msg( "notice", "文件处理完毕" ) |
||||
pub.sendMessage( "update", msg = self.msg ) |
||||
|
||||
def correction_turbidity(self, data:np.ndarray ): |
||||
'''浊度校正, 吸光度 |
||||
0 : 默认11项平均 |
||||
1 : 720 |
||||
2 : 不浊度校正 |
||||
''' |
||||
# log.debug( "correction_turbidity .....",__name__, 'correction_turbidity' ) |
||||
if self.viper.algorithm.A720 == 0: |
||||
count = data.shape[0] |
||||
tmp = 0.0 |
||||
for i in range(count-11,count,1): |
||||
tmp = tmp + data[i] |
||||
tmp = tmp/11 |
||||
# print(f"tmp ....{tmp}") |
||||
return data - tmp |
||||
pass |
||||
if self.viper.algorithm.A720 == 1: |
||||
count = data.shape[0] |
||||
tmp = data[count] - (self.viper.outputWavelength[count]-720) * (data[count] -data[count-1]) \ |
||||
/ (self.viper.outputWavelength[count]-self.viper.outputWavelength[count-1]) |
||||
# print(f"tmp .... {tmp}") |
||||
return data-tmp |
||||
pass |
||||
if self.viper.algorithm.A720 == 2: |
||||
return data |
||||
return data |
||||
pass |
||||
|
||||
def correction_pure_water(self, data:np.ndarray ): |
||||
'''纯水校正 |
||||
0 : 不变 |
||||
1 : 加纯水衰减系数 |
||||
''' |
||||
# log.info(f"... {self.cfg['algorithm']['PureWater']}",__name__,'correction_pure_water') |
||||
# print( self.purewater_after_interp ) |
||||
if self.viper.algorithm.PureWater == 0: |
||||
return data |
||||
pass |
||||
if self.viper.algorithm.PureWater == 1: |
||||
return data + self.viper.purewaterAttAfterInterp |
||||
pass |
||||
return data |
||||
pass |
||||
|
||||
def __prepare_for_save(self,) -> bool: |
||||
dir = Path().joinpath(DATA_DIR, OUTPUT_DIR) |
||||
self.mydir.setBaseDir(dir) |
||||
self.mydir.newDirIfNot() |
||||
self.mydir.newFileIfNot(self.viper.SN+SAVE_EXT_NAME) |
||||
|
||||
self.mydir.setHeader(self.viper.outputWavelength, TOKEN, self.viper.SN) |
||||
if self.mydir.checkHeader() == 0: |
||||
self.mydir.writeHeader() |
||||
if self.mydir.checkHeader() == -1: |
||||
# self.popDialog(" 文件头不一致, 请备份到其他目录,并在该目录下删除") |
||||
raise MyException(" 文件头不一致, 请备份到其他目录,并在该目录下删除") |
||||
|
||||
def __set_msg(self, typ, d): |
||||
self.msg = {} |
||||
self.msg.update( {"type":typ} ) |
||||
self.msg.update( {"data":d} ) |
||||
pass |
Loading…
Reference in new issue