optimize_data_process

desktop
esea_info 3 years ago
parent 8d58729f21
commit 3e60a77696
  1. 6
      app.py
  2. 198
      awrams.py
  3. 1
      config.yml
  4. 1
      configuration.py
  5. 237
      dataplot.py
  6. 107
      mypanel.py
  7. 126
      mythread.py
  8. 2
      retrieve.yml
  9. 100
      uiconfig/ui_plot_setting.py
  10. 178
      yiwinframe.py

@ -16,7 +16,7 @@ from myconfig import VERSION,LASTDATE,COMPANY
class YiwinApp(wx.App): class YiwinApp(wx.App):
def OnInit(self): def OnInit(self):
self.myframe = YiwinFrame( u'Handheld Offline Software', parent=None) self.myframe = YiwinFrame( u'AWRAMS Offline Software', parent=None)
self.myframe.statusBar.SetStatusText( u" 版权所有 " + COMPANY self.myframe.statusBar.SetStatusText( u" 版权所有 " + COMPANY
+" Version "+ VERSION +" Version "+ VERSION
+ " "+ LASTDATE, 1 ) #给状态栏设文字 + " "+ LASTDATE, 1 ) #给状态栏设文字
@ -24,7 +24,7 @@ class YiwinApp(wx.App):
return True return True
if __name__ == "__main__": if __name__ == "__main__":
log.info(f"******** Shanghai Yiwin Instrument@Equipment Company *********", __name__, "", "") log.info(f"******** Shanghai Yiwin Instrument&Equipment Company *********", __name__, "", "")
log.info(f"******** Handheld Software for Dealing RAMSES Raw data *********", __name__, "", "") log.info(f"******** AWRAMS Software for Dealing RAMSES Raw data *********", __name__, "", "")
app = YiwinApp( ) app = YiwinApp( )
app.MainLoop() app.MainLoop()

@ -14,6 +14,7 @@ import time
import locale import locale
import struct import struct
import numpy as np import numpy as np
from pubsub import pub
from pathlib import PurePath,Path from pathlib import PurePath,Path
from myconfig import CURRENT_DIR,DATA_DIR,OUTPUT_DIR,NEWLINE,ROWFACTOR,SAVE_EXT_NAME,TOKEN from myconfig import CURRENT_DIR,DATA_DIR,OUTPUT_DIR,NEWLINE,ROWFACTOR,SAVE_EXT_NAME,TOKEN
from myconfig import DeviceType,RamsesSURFACE,RamsesAWRAMS,RamsesPROFILE from myconfig import DeviceType,RamsesSURFACE,RamsesAWRAMS,RamsesPROFILE
@ -349,6 +350,10 @@ class AWRAMS(object):
def __init__(self, ): def __init__(self, ):
""" """
@description : 手持数据初始化 @description : 手持数据初始化
处理入口 dealAllMeasurements()
每个文件调用 dealOneMeasurement()
读取buf :decode_sensor_buf() 数值截取 转光强
dealOneGroup()平均 插值 追加保存
""" """
self.device_type = DeviceType.AWRAMS.name self.device_type = DeviceType.AWRAMS.name
self.device_enum = None self.device_enum = None
@ -384,6 +389,7 @@ class AWRAMS(object):
self.ramses = Ramses() self.ramses = Ramses()
self.info_dict = {} self.info_dict = {}
self.res = {} # 最终结果{lsky: esky: lwater: Lw: Rs:} self.res = {} # 最终结果{lsky: esky: lwater: Lw: Rs:}
self.msg ={}
# 方法 # 方法
self.setDeviceEnum() self.setDeviceEnum()
@ -407,6 +413,12 @@ class AWRAMS(object):
if self.device_type == DeviceType.PROFILE.name: if self.device_type == DeviceType.PROFILE.name:
self.device_enum = RamsesPROFILE self.device_enum = RamsesPROFILE
def __set_msg(self, flag, d):
self.msg = {}
self.msg.update( {"flag":flag} )
self.msg.update( {"data":d} )
pass
def getDataFileList(self, ): def getDataFileList(self, ):
self.hhp.getDataFileList() self.hhp.getDataFileList()
self.filelist = self.hhp.getFilelist() self.filelist = self.hhp.getFilelist()
@ -434,7 +446,7 @@ class AWRAMS(object):
pass pass
try: # awrams每次只有一组数据 try: # awrams每次只有一组数据
self.dealOneMeasurement(self.sensor_path_fname ) self.dealOneMeasurement( self.sensor_path_fname )
# self.measurement_interval = int(self.info_dict['Measure_Interval']) # self.measurement_interval = int(self.info_dict['Measure_Interval'])
# self.measurement_repeat = int(self.info_dict['Measure_Repeat']) # self.measurement_repeat = int(self.info_dict['Measure_Repeat'])
# self.dealOneHandheldMeasurement(self.sensor_path_fname ) # self.dealOneHandheldMeasurement(self.sensor_path_fname )
@ -442,14 +454,16 @@ class AWRAMS(object):
log.error( "处理传感器文件" + self.sensor_path_fname.name + " 出现错误",__name__,"dealAllMeasurements") log.error( "处理传感器文件" + self.sensor_path_fname.name + " 出现错误",__name__,"dealAllMeasurements")
raise MyException( "处理传感器文件" + self.sensor_path_fname.name + " 出现错误" ) raise MyException( "处理传感器文件" + self.sensor_path_fname.name + " 出现错误" )
pass pass
self.__set_msg('notice', '处理文件完成')
pub.sendMessage('update' , msg=self.msg)
log.info(f"Finished !! ", __name__, "dealAllMeasurements") log.info(f"Finished !! ", __name__, "dealAllMeasurements")
return True,self.error_result # return True,self.error_result
pass pass
def dealOneHandheldMeasurement(self, fpath:Path): def dealOneMeasurement(self, fpath:Path):
'''handheld一次测量包含多组数据''' '''handheld一次测量包含多组数据'''
# 调用handheldbuf 处理,将一组数据提交出来 # 调用handheldbuf 处理,将一组数据提交出来
log.info(f" 手持个文件,多组测量数据", __name__, "dealOneHandheldMeasurement") log.info(f"dealOneMeasurement: 一组测量数据", __name__, "dealOneMeasurement")
if len(self.filelist)<1: if len(self.filelist)<1:
pass pass
@ -464,87 +478,35 @@ class AWRAMS(object):
+ str(self.info_dict['minute']) + '_' \ + str(self.info_dict['minute']) + '_' \
+ str(self.info_dict['second']) + str(self.info_dict['second'])
self.output_path = self.output_path.joinpath( self.ymdhms ) self.output_path = self.output_path.joinpath( self.ymdhms )
log.debug(f"current_measure_time: {self.current_measure_time}", __name__, "dealOneHandheldMeasurement") log.debug(f"current_measure_time: {self.current_measure_time}", __name__, "dealOneMeasurement")
# 读取buf
self.hhb.readFile2Buf(fpath) self.hhb.readFile2Buf(fpath)
log.debug(f"buf: {self.hhb.get_buf_size()}", __name__, "dealOneHandheldMeasurement") # 将buf 处理成光强值 self.intensity_before_avg
self.decode_sensor_buf() self.decode_sensor_buf()
# 获得真实波长 self.real_wavelength
# 解析Buf, 对buf分组,获得[{lsky: esky : lwater} .... ] self.getRealWavelenthDict()
len_total = len(self.intensity_before_avg) # 多组数据平均 self.intensity_after_avg
if len_total%self.measurement_repeat != 0: self.getAvg( self.intensity_before_avg )
self.res = {} # 波长插值 self.res esky lsky lw
return # 返回退出 self.__do_sensor_dict_interpo()
group_num = int(len_total/self.measurement_repeat) # 获得输出目录路径 self.ymdhms self.output_path
self.get_ymdhms()
log.info(f"group_num...: {group_num}", __name__, "dealOneHandheldMeasurement") # 追加保存
self.real_wavelength = self.getWavelenthDict() self.appendSave()
if group_num == 1: # 通知ui
self.dealOneGroup() # self.intensity_before_avg self.__set_msg("data", {"tm":self.ymdhms, "res":self.res} )
return pub.sendMessage("update" , msg=self.msg)
self.dealMultiGroup(group_num) def get_ymdhms(self, ):
def dealMultiGroup(self, group_num:int ):
log.info(f"group_num: {group_num}", __name__, "dealMultiGroup")
# 分组进行处理
for i in range(group_num):
self.current_group_num = i
# 重设当前测量时间
self.current_measure_time = ""
self.res = {}
tmp_before_avg = []
for j in range( self.measurement_repeat ):
tmp_before_avg.append( self.intensity_before_avg[j+i*self.measurement_repeat] )
pass
self.getAvg(tmp_before_avg)
self.__do_sensor_dict_interpo()
self.appendSave( )
def dealOneGroup(self, ):
# 分组,并获得平均值, 255个未插值结果 (依据 measurement_interval measurement_repeat)
self.getAvg( self.intensity_before_avg )
# 插值
self.real_wavelength = self.getWavelenthDict()
self.__do_sensor_dict_interpo()
self.ymdhms = "20"+ str(self.info_dict['year']) + '_' \
+ str(self.info_dict['month']) + '_' \
+ str(self.info_dict['day']) + '_' \
+ str(self.info_dict['hour']) + '_' \
+ str(self.info_dict['minute']) + '_' \
+ str(self.info_dict['second'])
self.output_path = self.output_path.joinpath( self.ymdhms )
self.appendSave()
def dealOneMeasurement(self, fpath:Path):
'''handheld一次测量包含多组数据'''
# 调用handheldbuf 处理,将一组数据提交出来
log.info(f"dealOneMeasurement: 一组测量数据", __name__, "dealOneMeasurement")
if len(self.filelist)<1:
pass
# 当前文件名
self.output_path = OUTPUT_DIR
self.current_filepath = fpath
self.current_measure_time = self.hhp.getCurrentMeasureTimeFromPath(fpath)
self.ymdhms = "20"+ str(self.info_dict['year']) + '_' \ self.ymdhms = "20"+ str(self.info_dict['year']) + '_' \
+ str(self.info_dict['month']) + '_' \ + str(self.info_dict['month']) + '_' \
+ str(self.info_dict['day']) + '_' \ + str(self.info_dict['day']) + '_' \
+ str(self.info_dict['hour']) + '_' \ + str(self.info_dict['hour']) + '_' \
+ str(self.info_dict['minute']) + '_' \ + str(self.info_dict['minute']) + '_' \
+ str(self.info_dict['second']) + str(self.info_dict['second'])
self.output_path = self.output_path.joinpath( self.ymdhms ) # self.output_path = self.output_path.joinpath( self.ymdhms )
log.debug(f"current_measure_time: {self.current_measure_time}", __name__, "dealOneHandheldMeasurement") # print(self.output_path)
# time.sleep(30)
self.hhb.readFile2Buf(fpath)
self.decode_sensor_buf()
self.real_wavelength = self.getWavelenthDict()
self.dealOneGroup()
def decode_sensor_buf(self,) : def decode_sensor_buf(self,) :
# 处理Buf,对多组数据取平均 # 处理Buf,对多组数据取平均
@ -597,6 +559,61 @@ class AWRAMS(object):
log.debug(f"getAvg: {self.intensity_after_avg}", __name__, "getAvg") log.debug(f"getAvg: {self.intensity_after_avg}", __name__, "getAvg")
pass pass
# def dealOneHandheldMeasurement(self, fpath:Path):
# '''handheld一次测量包含多组数据'''
# # 调用handheldbuf 处理,将一组数据提交出来
# log.info(f" 手持一个文件,多组测量数据", __name__, "dealOneHandheldMeasurement")
# if len(self.filelist)<1:
# pass
# # 当前文件名
# self.output_path = OUTPUT_DIR
# self.current_filepath = fpath
# self.current_measure_time = self.hhp.getCurrentMeasureTimeFromPath(fpath)
# self.ymdhms = "20"+ str(self.info_dict['year']) + '_' \
# + str(self.info_dict['month']) + '_' \
# + str(self.info_dict['day']) + '_' \
# + str(self.info_dict['hour']) + '_' \
# + str(self.info_dict['minute']) + '_' \
# + str(self.info_dict['second'])
# self.output_path = self.output_path.joinpath( self.ymdhms )
# log.debug(f"current_measure_time: {self.current_measure_time}", __name__, "dealOneHandheldMeasurement")
# self.hhb.readFile2Buf(fpath)
# log.debug(f"buf: {self.hhb.get_buf_size()}", __name__, "dealOneHandheldMeasurement")
# self.decode_sensor_buf()
# # 解析Buf, 对buf分组,获得[{lsky: esky : lwater} .... ]
# len_total = len(self.intensity_before_avg)
# if len_total%self.measurement_repeat != 0:
# self.res = {}
# return # 返回退出
# group_num = int(len_total/self.measurement_repeat)
# log.info(f"group_num...: {group_num}", __name__, "dealOneHandheldMeasurement")
# self.real_wavelength = self.getWavelenthDict()
# if group_num == 1:
# self.dealOneGroup() # self.intensity_before_avg
# return
# self.dealMultiGroup(group_num)
# def dealMultiGroup(self, group_num:int ):
# log.info(f"group_num: {group_num}", __name__, "dealMultiGroup")
# # 分组进行处理
# for i in range(group_num):
# self.current_group_num = i
# # 重设当前测量时间
# self.current_measure_time = ""
# self.res = {}
# tmp_before_avg = []
# for j in range( self.measurement_repeat ):
# tmp_before_avg.append( self.intensity_before_avg[j+i*self.measurement_repeat] )
# pass
# self.getAvg(tmp_before_avg)
# self.__do_sensor_dict_interpo()
# self.appendSave( )
def getRetDict(self,) : def getRetDict(self,) :
ret_dict = { } ret_dict = { }
ret_dict.update( {self.device_enum(1).name:np.array([])} ) ret_dict.update( {self.device_enum(1).name:np.array([])} )
@ -613,7 +630,7 @@ class AWRAMS(object):
self.res.update( { k : tmp } ) self.res.update( { k : tmp } )
def getCfgByDid(self, func:str) : def getCfgByDid(self, func:str) :
cfg_id:dict = self.cfg.get(int(self.device_id)) cfg_id:dict = self.syscfg.get(int(self.device_id))
cfg_sensor = cfg_id.get( func) cfg_sensor = cfg_id.get( func)
return cfg_sensor return cfg_sensor
pass pass
@ -835,6 +852,14 @@ class AWRAMS(object):
ret_dict.update({ k : tmp }) ret_dict.update({ k : tmp })
return ret_dict return ret_dict
def getRealWavelenthDict( self, ) -> dict:
ret_dict = self.getRetDict()
cfg_id:dict = self.syscfg.get( int(self.device_id))
for k in ret_dict.keys():
tmp = self.getWavelength( cfg_id.get(k) )
ret_dict.update({ k : tmp })
self.real_wavelength = ret_dict
def getWavelength(self,ramsesdict:dict) -> np.ndarray: def getWavelength(self,ramsesdict:dict) -> np.ndarray:
ret = [] ret = []
for i in range(1,256): for i in range(1,256):
@ -904,3 +929,20 @@ if __name__ == "__main__":
pass pass
# def dealOneGroup(self, ):
# # 分组,并获得平均值, 255个未插值结果 (依据 measurement_interval measurement_repeat)
# self.getAvg( self.intensity_before_avg )
# # 插值
# self.real_wavelength = self.getWavelenthDict()
# self.__do_sensor_dict_interpo()
# self.ymdhms = "20"+ str(self.info_dict['year']) + '_' \
# + str(self.info_dict['month']) + '_' \
# + str(self.info_dict['day']) + '_' \
# + str(self.info_dict['hour']) + '_' \
# + str(self.info_dict['minute']) + '_' \
# + str(self.info_dict['second'])
# self.output_path = self.output_path.joinpath( self.ymdhms )
# self.appendSave()

@ -18,3 +18,4 @@
3: 3:
FUNC: Lwater FUNC: Lwater
SN: 852F SN: 852F

@ -32,6 +32,7 @@ class Configuration:
self.cal_configuration =None self.cal_configuration =None
for k,v in self.configuration.items(): for k,v in self.configuration.items():
print(f" ==== {v } ")
if v["SN"] == "" or v['FUNC']=="": if v["SN"] == "" or v['FUNC']=="":
pass pass

@ -0,0 +1,237 @@
# import numpy as np
from pathlib import Path
class DataPlot():
'''
从文件读取数据出来成待显示数据
'''
# def __init__(self, mypanel, ):
def __init__(self, ):
# self.mypanel = mypanel
# self.__eventManager = eventManger
# self.dataSaveFile = DATA_FNAME_WITHOUT_WATER
# self.axes_title = "Water Attenuation Coefficient"
# self.axes_xlabel = "Wavelength (nm)"
# self.axes_ylabel = "Attenuation Coefficient m(-1)"
# self.axes_title = "Attenuation Coefficient Demo"
self.demo_time = ''
self.demo_wl = [] # 纯水
self.demo_data = [] # 纯水
self.wavelength = None
self.data_one = None
self.data_multi = None
# self.mode = "one" # multi
# self.begin_line = None
# self.line_interval = None
self.fpath :Path = Path()
self.total_lines = 0
self.token = ";"
# self.MPL = myPanel.MPL_Panel(self) # 调用自己建立的 panel 类
# self.Figure = self.MPL.Figure
# self.axes = self.MPL.axes
# self.FigureCanvas = self.MPL.FigureCanvas
def set_file_path( self, fpath:Path ):
self.fpath = fpath
pass
def set_wavelength(self):
pass
# def set_mode(self, mode ="one"):
# self.mode = mode
# pass
def set_token(self, token =";"):
self.token = token
pass
def set_begin_line( self, lineno = 0 ):
self.begin_line = lineno
pass
def set_line_interval( self, line_interval = 0 ):
self.line_interval = line_interval
pass
def get_total_lines( self, ):
''' 大文件 '''
count = 0
thefile = open( self.fpath, 'rb')
while True:
buffer = thefile.read(8192*1024)
if not buffer:
break
count += buffer.count(b'\n')
self.total_lines = count + 1
def get_wavelength_from_file( self, ):
tmp = self.get_first_line()
self.wavelength = tmp.split(self.token)[1:]
pass
def get_reverse_x_lineno( self, x ):
line = self.__get_reverse_x_lineno(x)
line = line.split(self.token)
return line[0], line[1:]
pass
def get_multi_by_x_m_n( self, x,m,n ):
# res_time = []
# res_lines = []
lines = self.__get_reverse_x_m_n_line(x,m,n)
# print(f'+++++ {lines}')
# for i in range(len(lines)):
# ln =
# res_time.append( lines[i] [0] )
# res_lines.append( lines[i][1:] )
# return res_time, res_lines
return lines
pass
def __get_reverse_x_lineno(self, x):
"""
获得倒数第x行
"""
try:
# filesize = os.path.getsize(self.fpath)
filesize = self.fpath.stat().st_size
if filesize == 0:
return None
else:
with open(self.fpath, 'rb') as fp: # to use seek from end, must use mode 'rb'
offset = -8 # initialize offset
while -offset < filesize: # offset cannot exceed file size
fp.seek(offset, 2) # read # offset chars from eof(represent by number '2')
lines = fp.readlines() # read from fp to eof
if len(lines) >= x+1: # if contains at least 2 lines
return lines[-1*x] # then last line is totally included
else:
offset *= 2 # enlarge offset
fp.seek(0)
lines = fp.readlines()
if len(lines) < x:
raise Exception("行数有误,请重试")
return lines[-1*x]
except FileNotFoundError:
print(self.fpath.name + ' not found!')
return None
def __get_reverse_x_m_n_line(self, x, m=1, n=1):
"""
获得倒数第x行, 间隔m行, 共取n个行
"""
print(f'__get_reverse_x_m_n_line {x} {self.fpath}')
min_lines = x + m*n
res_lines = []
try:
# filesize = os.path.getsize(self.fpath)
filesize = self.fpath.stat().st_size
if filesize == 0:
return None
else:
with open(self.fpath, 'rb') as fp: # to use seek from end, must use mode 'rb'x
offset = -8 # initialize offset
while -offset < filesize: # offset cannot exceed file size
fp.seek( offset, 2 ) # read # offset chars from eof(represent by number '2')
lines = fp.readlines() # read from fp to eof
if len(lines) >= min_lines+1 :
for i in range(n):
res_lines.append( lines[-1*(x+m*i)].decode())
return res_lines
else:
offset *= 2 # enlarge offset
fp.seek( 0 )
lines = fp.readlines( )
if len(lines) < min_lines:
raise Exception("行数有误,请重试")
for i in range(n):
res_lines.append( lines[-1*(x+m*i)].decode())
return res_lines
print(res_lines)
except FileNotFoundError:
print(self.fpath.name + ' not found!')
return None
def get_first_line(self, ):
firstline = ''
with open(self.fpath, 'rb') as fp: # to use seek from end, must use mode 'rb'x
firstline = fp.readline()
return firstline.decode()
def get_last_line(self,filename:Path):
"""
获得最后一行
:param filename: file name
:return: last line or None for empty file
"""
try:
filesize = filename.stat().st_size
if filesize == 0:
return None
else:
with open(filename, 'rb') as fp: # to use seek from end, must use mode 'rb'
offset = -8 # initialize offset
while -offset < filesize: # offset cannot exceed file size
fp.seek(offset, 2) # read # offset chars from eof(represent by number '2')
lines = fp.readlines() # read from fp to eof
if len(lines) >= 2: # if contains at least 2 lines
return lines[-1] # then last line is totally included
else:
offset *= 2 # enlarge offset
fp.seek(0)
lines = fp.readlines()
return lines[-1]
except FileNotFoundError:
print(filename + ' not found!')
return None
def tail(file, taillines=500, return_str=True, avg_line_length=None):
"""
大文件的尾行小文件会导致报错
taillines : 读取尾部多少行
avg_line_length:每行字符平均数,
return_str:返回类型默认为字符串False为列表
offset:每次循环相对文件末尾指针偏移数
f.tell() 当前指针位置
f.seek(a,b) a 偏移量 b:0 1 2 文件头 当前位置 文件尾部
"""
with open(file, errors='ignore') as f:
if not avg_line_length:
f.seek(0, 2)
f.seek(f.tell() - 3000)
avg_line_length = int(3000 / len(f.readlines())) + 10
f.seek(0, 2)
end_pointer = f.tell()
offset = taillines * avg_line_length
if offset > end_pointer:
f.seek(0, 0)
lines = f.readlines()[-taillines:]
return "".join(lines) if return_str else lines
offset_init = offset
i = 1
while len(f.readlines()) < taillines:
location = f.tell() - offset
f.seek(location)
i += 1
offset = i * offset_init
if f.tell() - offset < 0:
f.seek(0, 0)
break
else:
f.seek(end_pointer - offset)
lines = f.readlines()
if len(lines) >= taillines:
lines = lines[-taillines:]
return "".join(lines) if return_str else lines
if __name__ == "__main__":
d = DataPlot()

@ -1,4 +1,111 @@
import wx import wx
import numpy as np
from enum import Enum
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas #FigureCanvasWxAgg
# from matplotlib.backends.backend_wx import NavigationToolbar2Wx as NavigationToolbar # FIgure 导航
from matplotlib.figure import Figure
class LineColor(Enum):
RED = 0
ORANGE = 1
YELLOW = 2
GREEN = 3
CYAN = 4
BLUE = 5
PURPLE = 6
class Plot(wx.Panel):
'''
# 需要在 Frame 实例化一个实例
# 改变需要对实例化后的进行操作
'''
'''
Matplotlib Panel 单独拿出来画图
可以 __do_layout
可以 __add_widgets
可以 button事件
可以鼠标事件
'''
def __init__(self,parent):
'''
* panel 初始化后的样子
'''
super(Plot,self).__init__(parent)
# 本地化语言
self.locale = wx.Locale(wx.LANGUAGE_CHINESE_SIMPLIFIED)
self.Figure = Figure(figsize=(4,3)) # 4,3 为英寸
self.axes = self.Figure.add_axes([0.1,0.1,0.8,0.8],facecolor="lightgray") # 坐标系起始位置
self.FigureCanvas = FigureCanvas(self,-1,self.Figure)
#继承鼠标移动显示鼠标处坐标的事件
# self.FigureCanvas.mpl_connect('motion_notify_event',self.MPLOnMouseMove)
# self.NavigationToolbar = NavigationToolbar(self.FigureCanvas)
# self.StaticText = wx.StaticText(self,-1,label=u'坐标信息')
# self.SubBoxSizer = wx.BoxSizer(wx.HORIZONTAL)
# self.SubBoxSizer.Add(self.NavigationToolbar,proportion =0, border = 2,flag = wx.ALL | wx.EXPAND)
# self.SubBoxSizer.Add(self.StaticText,proportion =-1, border = 2,flag = wx.ALL | wx.EXPAND)
self.TopBoxSizer = wx.BoxSizer(wx.VERTICAL)
# self.TopBoxSizer.Add(self.SubBoxSizer,proportion =-1, border = 2,flag = wx.ALL | wx.EXPAND)
self.TopBoxSizer.Add(self.FigureCanvas,proportion =-10, border = 2,flag = wx.ALL | wx.EXPAND)
self.SetSizer(self.TopBoxSizer)
self.purewater_legend = (" Rs"
,"Wavelength (nm)"
," Rs " )
self.measure_legend = (" Rs"
,"Wavelength (nm)"
," Rs" )
def set_axes_title(self,title):
self.axes.set_title(title)
def set_axes_xlabel(self,x):
self.axes.set_xlabel(x)
def set_axes_ylable(self,y):
self.axes.set_ylabel(y)
def set_title_x_y(self,title, x, y):
self.axes.set_title(title)
self.axes.set_xlabel(x)
self.axes.set_ylabel(y)
def plot_one( self, time_, wavelength:np.ndarray, data:np.ndarray, color="green" ):
self.axes.plot(wavelength, data, color=color, linewidth=0.5 , label=time_ )
self.axes.legend( )
self.axes.grid( True )
self.FigureCanvas.draw()
def plot_multi( self, tm, wavelength:np.ndarray, data:np.ndarray ):
len_ = len(data)
for i in range(len_):
self.axes.plot(wavelength, data[i], color=LineColor(i).name.lower(), linewidth=0.5 , label=tm[i] )
self.axes.legend( )
self.axes.grid(True)
self.FigureCanvas.draw()
def clear_past( self, ):
self.axes.clear()
# def MPLOnMouseMove(self,event):
# '''
# * 显示坐标值
# '''
# ex=event.xdata#这个数据类型是numpy.float64
# ey=event.ydata#这个数据类型是numpy.float64
# if ex and ey :
# #可以将numpy.float64类型转化为float类型,否则格式字符串可能会出错
# self.StaticText.SetLabel('%10.5f,%10.5f' % (float(ex),float(ey)))
class MyPanel(wx.Panel): class MyPanel(wx.Panel):
"""docstring for MyPanel.""" """docstring for MyPanel."""

@ -0,0 +1,126 @@
import threading
import time
class Mythead(threading.Thread):
'''线程守护'''
def __init__(self ):
super(Mythead, self).__init__()
pass
def set_task(self, func, *args):
self.func = func
self.args = args
def run(self):
# print(f" --- {len(self.args)}")
if len(self.args) > 0:
self.func(self.args)
else:
self.func( )
class Multithread(threading.Thread):
'''
多线程
子线程.join() -> ( 设置在start之后, 等所有阻塞线程运行完, 再运行主线程 )
子线程.setDaemon(True) -> 设置子线程A为守护线程, 主线程所在的进程内所有非守护线程统统运行完毕,
无论子线程A有没有结束, 程序都结束
Method:
'''
def __init__(self):
super(Multithread, self).__init__()
self.__tasks = []
self.act = []
# self.__block = False
pass
# def set_task( self, tasks ):
# self.__tasks = tasks
def add_task(self, func, daemon=False, join=True,args=()):
tmp_dict = {}
tmp_dict.update( {"func" : func})
if daemon == True:
tmp_dict.update( {"daemon" : True})
else:
tmp_dict.update( {"daemon" : False})
if join == True:
tmp_dict.update( {"join" : True})
else:
tmp_dict.update( {"join" : False})
if args == ():
tmp_dict.update( {"args" : ()})
else:
tmp_dict.update( {"args" : args})
self.__tasks.append( tmp_dict )
def remove_tasks(self, ):
self.__tasks = []
self.act = []
def add_task_2_act(self, task):
t = threading.Thread( target = task['func'], args = task['args'] )
self.act.append(t)
t.start()
def execute_one_act(self,i):
if self.__tasks[i]['join']:
self.act[i].join() # 子线程阻塞完毕再运行主线程
pass
def prepare_tasks(self):
self.act = []
for task in self.__tasks:
self.add_task_2_act(task)
def execute_tasks(self):
try:
for i in range( len(self.act) ):
self.execute_one_act( i )
pass
except Exception as e:
print(e)
def prepare_tasks(self):
self.act = []
for task in self.__tasks:
t = threading.Thread( target = task['func'], args = task['args'] )
self.act.append(t)
t.start()
def simultaneously_execute_tasks(self):
self.prepare_tasks()
self.execute_tasks()
def sequently_execute_tasks(self):
for task in self.__tasks:
t = threading.Thread( target = task['func'], args = task['args'] )
t.start()
t.join()
def t1(self):
print("thread1...")
time.sleep(10)
print("thread1... after sleep...")
def t2(self):
print("thread2...")
time.sleep(5)
print("thread2... after sleep...")
def t3(self):
print("thread3...")
time.sleep(3)
print("thread3... after sleep...")
if __name__ == '__main__':
mt = Multithread()
mt.add_task(mt.t1)
mt.add_task(mt.t2)
mt.add_task(mt.t3)
# mt.prepare_tasks() # 线程同步运行
# mt.execute_tasks()
# mt.simultaneously_execute_tasks()
mt.sequently_execute_tasks()

@ -1,3 +1,5 @@
LineBegin: 1
LineInterval: 1
beginWL: 350 beginWL: 350
endWL: 950 endWL: 950
interval: 1 interval: 1

@ -0,0 +1,100 @@
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
import wx
# from configobj import ConfigObj
from myconfig import MyConfig
from myconfig import YAML_FILE_NAME
class UI_Plot_Setting(wx.Dialog):
"""
@description : 绘图 配置
"""
def __init__(self, parent, id):
# 串口页面配置
super(UI_Plot_Setting, self).__init__( parent ,id = id )
self.config = MyConfig()
self.InitUI()
self.SetSize((400, 400))
self.SetTitle(" 绘图 序列号 ")
def InitUI(self):
self.config_yml = self.config.read_rtv_yaml()
self.panel = wx.Panel(self)
self.vbox = wx.BoxSizer(wx.VERTICAL)
self.sb = wx.StaticBox(self.panel, label='指定绘图设置 ')
self.sbs = wx.StaticBoxSizer(self.sb, orient=wx.VERTICAL)
self.hbox1 = wx.BoxSizer(wx.HORIZONTAL)
self.staticText1 = wx.StaticText(self.panel, label='起始行号 ',size=(60, -1), style=wx.ALIGN_CENTRE_VERTICAL )
self.textCtrl1 = wx.TextCtrl(self.panel, value="",size=(250,25) )
tmp = self.get_str_from_config( "LineBegin" )
if tmp is not None:
self.textCtrl1.SetValue(tmp)
self.hbox1.Add(self.staticText1, flag=wx.TOP|wx.LEFT, border=5)
self.hbox1.Add(self.textCtrl1, flag=wx.TOP|wx.LEFT, border=5)
self.sbs.Add(self.hbox1, flag=wx.TOP|wx.LEFT, border= 5)
self.hbox2 = wx.BoxSizer(wx.HORIZONTAL)
self.staticText2 = wx.StaticText(self.panel, label='间隔行号: ' ,size=(60, -1))
# self.staticText2_1 = wx.StaticText(self.panel, label='分钟 ' ,size=(60, -1))
self.textCtrl2 = wx.TextCtrl(self.panel, value="",size=(250,25))
tmp = self.get_str_from_config( "LineInterval" )
if tmp is not None:
self.textCtrl2.SetValue(tmp)
self.hbox2.Add(self.staticText2, flag=wx.TOP|wx.LEFT, border=5)
self.hbox2.Add(self.textCtrl2,flag=wx.TOP|wx.LEFT, border=5)
# self.hbox2.Add(self.staticText2_1, flag=wx.TOP|wx.LEFT, border=5)
self.sbs.Add(self.hbox2, flag=wx.TOP|wx.LEFT, border=5)
self.panel.SetSizer(self.sbs)
self.hbox_0 = wx.BoxSizer(wx.HORIZONTAL)
self.okButton = wx.Button(self, label=u'保存配置')
self.closeButton = wx.Button(self, label='Close')
self.hbox_0.Add(self.okButton)
self.hbox_0.Add(self.closeButton, flag = wx.LEFT, border=5)
# 添加 vbox 到panel
self.vbox.Add(self.panel, proportion=1,
flag=wx.ALL | wx.EXPAND, border=5)
self.vbox.Add(self.hbox_0, flag=wx.ALIGN_CENTER | wx.TOP | wx.BOTTOM, border=10)
self.SetSizer(self.vbox)
self.okButton.Bind(wx.EVT_BUTTON, self.OnSave)
self.closeButton.Bind(wx.EVT_BUTTON, self.OnClose)
def get_str_from_config( self, key ):
return str(self.config_yml[key])
pass
def set_config_by_key_val( self, key, val ):
# print(f" {key} current type {type( self.config_yml[section][key] )}")
if type( self.config_yml [key] ) == int:
self.config_yml [key] = int(val)
elif type( self.config_yml [key] ) == float:
self.config_yml [key] = float(val)
else:
self.config_yml[key] = val
pass
def saveData(self, e):
pass
def OnClose(self, e):
self.Destroy()
def OnSave(self, e):
success = True
# 赋值字典,写入文件
self.set_config_by_key_val( "LineBegin",self.textCtrl1.GetValue( ))
self.set_config_by_key_val( "LineInterval",self.textCtrl2.GetValue( ))
self.config.write_rtv_yaml(self.config_yml)
del self.config
if success:
self.EndModal(wx.ID_OK)

@ -2,20 +2,23 @@ import wx
import os import os
import time import time
import threading import threading
from pathlib import * from pathlib import PurePath,Path
from pubsub import pub
# from configobj import ConfigObj # from configobj import ConfigObj
from listctrl import Listctrl from listctrl import Listctrl
from mypanel import MyPanel from mypanel import MyPanel,Plot,LineColor
from uiconfig.uisensor import UISensor from uiconfig.uisensor import UISensor
# from uiconfig.uilogging import UILogging # from uiconfig.uilogging import UILogging
from uiconfig.uiabout import About from uiconfig.uiabout import About
from uiconfig.uihelp import Help from uiconfig.uihelp import Help
from uiconfig.ui_plot_setting import UI_Plot_Setting
from myconfig import TOKEN,DeviceType,YAML_FILE_NAME,RETRIEVE_CFG_FILE from myconfig import TOKEN,DeviceType,YAML_FILE_NAME,RETRIEVE_CFG_FILE
from myconfig import MyConfig from myconfig import MyConfig,RamsesFunc
from mythread import Mythead
from configuration import Configuration from configuration import Configuration
from awrams import AWRAMS,HandHeldBuf from awrams import AWRAMS,HandHeldBuf
@ -29,10 +32,14 @@ ID_SENSOR_SETTING = 11
ID_LOGGING_SETTING = 12 ID_LOGGING_SETTING = 12
ID_CAL_INFO = 13 ID_CAL_INFO = 13
ID_PLOT_LAST = 15
ID_PLOT_LAST_7 = 16
ID_PLOT_7 = 17
ID_PLOT_SETTING = 18
ID_HELP = 21 ID_HELP = 21
ID_ABOUT = 22 ID_ABOUT = 22
class YiwinFrame(wx.Frame): class YiwinFrame(wx.Frame):
'''将buf类传进来''' '''将buf类传进来'''
def __init__(self, title, parent, size=(900, 750)): def __init__(self, title, parent, size=(900, 750)):
@ -66,7 +73,12 @@ class YiwinFrame(wx.Frame):
self.BoxSizer.Add( self.mypanel, proportion =-10, border = 0, flag = wx.ALL | wx.EXPAND) self.BoxSizer.Add( self.mypanel, proportion =-10, border = 0, flag = wx.ALL | wx.EXPAND)
self.static_text = self.mypanel.staticText1 self.static_text = self.mypanel.staticText1
# 隐藏 等待show # 隐藏 等待show
self.mypanel.Show() self.mypanel.Hide()
self.plotpanel = Plot( self ) # 调用自己建立的 Listctrl panel 类
self.BoxSizer.Add( self.plotpanel, proportion =-10, border = 0, flag = wx.ALL | wx.EXPAND)
self.plotpanel.set_title_x_y(*self.plotpanel.purewater_legend)
self.plotpanel.Show()
self.statusBar = self.CreateStatusBar() # 创建状态栏 self.statusBar = self.CreateStatusBar() # 创建状态栏
self.statusBar.SetFieldsCount(2) # 状态栏分成3个区域 self.statusBar.SetFieldsCount(2) # 状态栏分成3个区域
@ -80,10 +92,10 @@ class YiwinFrame(wx.Frame):
self.__setTimer() self.__setTimer()
log.info(f"system init....",__name__, "__init__") log.info(f"system init....",__name__, "__init__")
self.mycfg = MyConfig() self.mycfg = MyConfig()
self.hh = AWRAMS() self.awrams = AWRAMS()
self.mythread = Mythead()
# self.hhb = HandHeldBuf()
pub.subscribe( self.updateDisplay, "update")
pass pass
def __set_menu(self): def __set_menu(self):
@ -102,6 +114,16 @@ class YiwinFrame(wx.Frame):
# settingMenu.Append(ID_LOGGING_SETTING, u'&采集设置', ' ') # settingMenu.Append(ID_LOGGING_SETTING, u'&采集设置', ' ')
self.menubar.Append(settingMenu, u'&系统 ') self.menubar.Append(settingMenu, u'&系统 ')
plotMenu = wx.Menu()
plotMenu.Append(ID_PLOT_LAST, u'&最后一条', '...')
plotMenu.AppendSeparator()
plotMenu.Append(ID_PLOT_LAST_7, u'&最后七条', ' ')
plotMenu.AppendSeparator()
plotMenu.Append(ID_PLOT_7, u'&指定七条', ' ')
plotMenu.AppendSeparator()
plotMenu.Append(ID_PLOT_SETTING, u'&指定设置', ' ')
self.menubar.Append(plotMenu, u'&绘图 ')
aboutMenu = wx.Menu() aboutMenu = wx.Menu()
aboutMenu.Append(ID_HELP, u'&帮助', 'help...') aboutMenu.Append(ID_HELP, u'&帮助', 'help...')
aboutMenu.AppendSeparator() aboutMenu.AppendSeparator()
@ -126,6 +148,11 @@ class YiwinFrame(wx.Frame):
self.Bind(wx.EVT_MENU, self.OnDealData, id=ID_MEASURE) self.Bind(wx.EVT_MENU, self.OnDealData, id=ID_MEASURE)
# self.Bind(wx.EVT_MENU, self.OnLoggingSetting, id=ID_LOGGING_SETTING) # self.Bind(wx.EVT_MENU, self.OnLoggingSetting, id=ID_LOGGING_SETTING)
self.Bind(wx.EVT_MENU, self.OnPlotLast, id=ID_PLOT_LAST )
self.Bind(wx.EVT_MENU, self.OnPlotLast7, id=ID_PLOT_LAST_7 )
self.Bind(wx.EVT_MENU, self.OnPlot7, id=ID_PLOT_7)
self.Bind(wx.EVT_MENU, self.OnPlotSetting, id=ID_PLOT_SETTING)
self.Bind(wx.EVT_MENU, self.OnHelpConfig, id=ID_HELP) self.Bind(wx.EVT_MENU, self.OnHelpConfig, id=ID_HELP)
self.Bind(wx.EVT_MENU, self.OnAboutConfig, id=ID_ABOUT) self.Bind(wx.EVT_MENU, self.OnAboutConfig, id=ID_ABOUT)
pass pass
@ -135,6 +162,35 @@ class YiwinFrame(wx.Frame):
self.Bind(wx.EVT_TIMER, self.OnTimer, self.timer) #绑定一个定时器事件 self.Bind(wx.EVT_TIMER, self.OnTimer, self.timer) #绑定一个定时器事件
pass pass
def updateDisplay(self, msg):
log.warning(f" updateDisplay 。。 {msg['data']}")
if msg['flag'] == "notice":
self.__update_notice(msg['data'])
pass
if msg['flag'] == "data":
# log.info(f" ... update .{msg['data']}........... " )
self.__update_data(msg['data'])
pass
pass
def __update_notice(self,msg):
log.info(f" .......{msg}... ",__name__,'__update_notice')
self.alterStatus_0( msg)
self.popDialog( msg )
pass
def __update_data(self,data ):
log.info(f" .......... ",__name__,'__update_data')
self.plotpanel.set_axes_title( data['tm'])
res = data['res']
x = self.awrams.wavelength.tolist()
length = len(data)
self.plotpanel.clear_past()
for display in RamsesFunc:
self.plotpanel.plot_one(display.name, x, res[display.name],color= LineColor(display.value).name )
pass
pass
def OnStart( self, event ): def OnStart( self, event ):
log.info(f"OnStart....interval: {self.interval} min, port: {self.port}") log.info(f"OnStart....interval: {self.interval} min, port: {self.port}")
# self.m = SerialThread() # self.m = SerialThread()
@ -171,20 +227,31 @@ class YiwinFrame(wx.Frame):
self.statusBar.SetStatusText("Pls get the cal info, and try again",0) self.statusBar.SetStatusText("Pls get the cal info, and try again",0)
pass pass
self.hh.getDataFileList() self.awrams.getDataFileList()
self.hh.setDeviceID(self.device_id) self.awrams.setDeviceID(self.device_id)
self.hh.setRetrieve(self.retrieve) self.awrams.setRetrieve(self.retrieve)
if self.syscfg != {}: if self.syscfg != {}:
self.hh.setSyscfg(self.syscfg) self.awrams.setSyscfg(self.syscfg)
else: else:
log.warning(f"Pls get the cal info, and try again", __name__, "OnDealData","setCfg") log.warning(f"Pls get the cal info, and try again", __name__, "OnDealData","setCfg")
MyException( f"System Configuration is empty." ) MyException( f"System Configuration is empty." )
pass pass
if self.hh.dealAllMeasurements( ): # 处理数据
self.onNotify("正在处理数据" ) self.alterStatus_0(" 正在处理数据...." )
self.statusBar.SetStatusText(u" 数据处理完成......", 0) try:
self.onNotify("处理数据已经结束" ) self.mythread.set_task( self.awrams.dealAllMeasurements )
self.mythread.start()
except Exception as e:
log.error(e)
pass
# if self.awrams.dealAllMeasurements( ):
# self.onNotify("正在处理数据" )
# self.statusBar.SetStatusText(u" 数据处理完成......", 0)
# self.onNotify("处理数据已经结束" )
pass pass
def OnCalInfo(self,e): def OnCalInfo(self,e):
@ -236,6 +303,27 @@ class YiwinFrame(wx.Frame):
with wx.MessageDialog( self, msg, msg_type, wx.OK )as dlg: with wx.MessageDialog( self, msg, msg_type, wx.OK )as dlg:
dlg.ShowModal() dlg.ShowModal()
def OnPlotLast(self,e):
pass
def OnPlotLast7(self,e):
pass
def OnPlot7(self,e):
pass
def OnPlotSetting(self,e):
with UI_Plot_Setting(
self,
-1 ) as Dialog_Sensor_Setting:
Dialog_Sensor_Setting.CenterOnParent()
resultLog = Dialog_Sensor_Setting.ShowModal()
if resultLog == wx.ID_OK:
log.info( " Plot config dialog confirm, call back " )
self.__read_config()
pass
def OnSensorSetting(self,e): def OnSensorSetting(self,e):
with UISensor( with UISensor(
self, self,
@ -277,61 +365,3 @@ class YiwinFrame(wx.Frame):
self.Close() self.Close()
# class SerialThread(threading.Thread):
# """进度条类 """
# def __init__(self, parent):
# """
# :param parent: 主线程UI
# """
# super(SerialThread, self).__init__() # 继承
# self.parent = parent
# # log.info(f"SerialThread ... {self.parent.kh}")
# self.start()
# self.join()
# # self.setDaemon(True) # 设置为守护线程, 即子线程是守护进程,主线程结束子线程也随之结束。
# def stop(self):
# self.parent.kh.disconnect()
# log.info(" Serial stop.... ")
# pass
# def run(self):
# log.info(" Serial run.... ")
# wx.CallAfter(self.parent.OnRcv)
# wx.CallAfter(self.parent.update_process_bar, count) # 调用parent的函数
# wx.CallAfter(self.parent.close_process_bar) # destroy进度条
# def OnSerialThreadStart(self):
# self.m = SerialThread(self)
# pass
# def OnSerialThreadStop(self):
# self.m.stop()
# pass
# def OnDisplaySave(self):
# '''
# 保存数据 self.result
# '''
# log.info(f"OnDisplaySave ....")
# # self.m = SerialThread(self)
# # self.kh.flush()
# self.OnSerialThreadStart()
# def OnRcv( self ):
# log.info(f"OnRcv....")
# self.kh.setPort(self.port)
# if not self.OnDetectPort:
# MyException(f"Can not find port : {self.port}")
# log.info(f"{self.port} ok!")
# # if not self.kh:
# # self.kh = KH3000(self.port)
# # self.result = self.kh.OneMeasure()
# log.info( f"OnRcv success {self.result}", __class__.__name__ )
# self.OnSave()
# self.OnDisplay()
# pass
Loading…
Cancel
Save