first commit

main
esea_info 3 years ago
commit a9e20ad08b
  1. 91
      .vscode/settings.json
  2. 33
      app.py
  3. 45
      app.spec
  4. 312
      calfile/Basis aq_B055.dat
  5. 312
      calfile/Reflectivity_B055.dat
  6. 197
      calfile/abs_pure_water.dat
  7. 27
      config.yml
  8. 32
      configuration.py
  9. 2058
      data/20210305/CALIBRAT.DAT
  10. 18
      data/output/B055.csv
  11. 466
      dataplot.py
  12. BIN
      icon.ico
  13. 32
      listctrl.py
  14. 188
      myconfig.py
  15. 14
      myexception.py
  16. 285
      mylogger.py
  17. 141
      mypanel.py
  18. 277
      mypath.py
  19. 126
      mythread.py
  20. 71
      mytime.py
  21. 476
      oscar.py
  22. 1020
      readcal.py
  23. 3
      retrieve.yml
  24. 200
      uart.py
  25. 110
      uiconfig/ui_algorithm.py
  26. 138
      uiconfig/ui_com_setting.py
  27. 92
      uiconfig/ui_filepath_setting.py
  28. 100
      uiconfig/ui_log_setting.py
  29. 100
      uiconfig/ui_pathsn_setting.py
  30. 100
      uiconfig/ui_plot_setting.py
  31. 60
      uiconfig/uiabout.py
  32. 58
      uiconfig/uihelp.py
  33. 124
      uiconfig/uisensor.py
  34. 772
      yiwinframe.py

@ -0,0 +1,91 @@
{
// ()
"editor.fontSize": 16,
// #editor.wordWrap# wordWrapColumn bounded 100
"editor.wordWrapColumn": 100,
// tab true false
"editor.detectIndentation": false,
// tab
"editor.tabSize": 4,
//
"editor.formatOnSave": false,
// vscode
"breadcrumbs.enabled": true,
// prettier ,C_cpp
"prettier.semi": false,
// prettier
"prettier.singleQuote": true,
// 'none' - ' es5' - ES5 'all' -
"prettier.trailingComma": "none",
//
"javascript.format.insertSpaceBeforeFunctionParenthesis": true,
// , ctrl+
"editor.mouseWheelZoom": true,
"editor.defaultFormatter": "ms-python.vscode-pylance",
"files.encoding":"utf8",
// python tab4
"[python]": {
"editor.insertSpaces": true,
"editor.tabSize": 4
},
// astyle,astyle -C c++ java
// "astyle.executable": "D:\\AStyle\\bin\\astyle.exe", //window
// "astyle.executable": "/usr/bin/astyle", // linux
// "astyle.additional_languages": [
// "c",
// "cpp",
// "*.h",
// ],
// "astyle.cmd_options": [
// // -----------------------------------------------------------
// // "--style=ansi", //ANSI
// // "--style=kr", //Kernighan&Ritchie
// "--style=linux", //Linux
// //"--style=gnu", //GNU
// // "--style=java", //Java
// "--indent=spaces=4", //4
// "--indent-preproc-block",
// "--pad-oper", //
// "--pad-header",
// "--unpad-paren",
// "--suffix=none",
// "--align-pointer=name",
// "--lineend=linux",
// "--convert-tabs", //TAB
// "--verbose",
// // "--delete-empty-lines", //
// //"--pad-paren-in", //
// "--unpad-paren", //
// ],
// pylint --python pylint
// "python.linting.enabled": true,
// "python.linting.pylintEnabled": true,
// "python.linting.lintOnSave": true,
// "python.linting.pylintPath": "D:\\pylint\\bin\\pylint.exe",
// "python.linting.pylintArgs": [
// "--rcfile={path}/.pylintrc",
// "--extension-pkg-whitelist=PyQt5",
// "--disable=invalid-name,missing-module-docstring",
// "--disable=W0612,W0631,W0703,W0621,W0613,W0611,W1308,C0411,C0111,C0103,C0301,C0304,C0305,E1101,R0913,R0914,R0915,R0903" ,
// ],
// ,
"terminal.integrated.defaultProfile.windows" : "PowerShell",
// "terminal.integrated.defaultProfile.windows" : "Git Bash",
// "terminal.integrated.defaultProfile.windows" : "Windows PowerShell",
// "terminal.integrated.defaultProfile.windows": "Ubuntu-20.04 (WSL)",
"python.defaultInterpreterPath": "python3", // python3 python
"code-runner.executorMap": {
"python":"python3 -u $fullFileName"
},
}

@ -0,0 +1,33 @@
#! python3
# -*- encoding: utf-8 -*-
'''
@File : app.py
@Time : 2021/09/12 12:38:46
@Author : Jim
@Version : 1.0
@Desp :
'''
# VERSION = "3.3.2"
# LASTDATE = "2021-09-20"
import wx
from yiwinframe import YiwinFrame
from mylogger import log
from myconfig import VERSION,LASTDATE,COMPANY
class YiwinApp(wx.App):
def OnInit(self):
self.myframe = YiwinFrame( u'奕枫水体吸收系数测量软件 v1.0', parent=None)
self.myframe.statusBar.SetStatusText( u" 版权所有 " + COMPANY
+" Version "+ VERSION + " "+ LASTDATE, 1 ) #给状态栏设文字
self.myframe.Show(True)
return True
if __name__ == "__main__":
log.info(f"******** Shanghai Yiwin Instrument@Equipment Company *********", __name__, "", "")
log.info(f"******** Viper attenuation Software .... *********", __name__, "", "")
app = YiwinApp( )
app.MainLoop()

@ -0,0 +1,45 @@
# -*- mode: python ; coding: utf-8 -*-
block_cipher = None
a = Analysis(
['app.py'],
pathex=[],
binaries=[],
datas=[],
hiddenimports=[],
hookspath=[],
hooksconfig={},
runtime_hooks=[],
excludes=[],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher,
noarchive=False,
)
pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher)
exe = EXE(
pyz,
a.scripts,
a.binaries,
a.zipfiles,
a.datas,
[],
name='app',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
upx_exclude=[],
runtime_tmpdir=None,
console=False,
disable_windowed_traceback=False,
argv_emulation=False,
target_arch=None,
codesign_identity=None,
entitlements_file=None,
icon='icon.ico',
)

@ -0,0 +1,312 @@
[Spectrum]
Version = 1
IDData = OSCAR_B055_2020-12-04_13-57-29_Waterbase_041
IDDevice = OSCAR_B055
IDDataType = SPECTRUM
IDDataTypeSub1 = CALIBRATED
IDDataTypeSub2 = BASIS
IDDataTypeSub3 =
DateTime = 2020-12-04 13:57:29
PositionLatitude = 0
PositionLongitude = 0
Comment = Basis aq_B055
CommentSub1 =
CommentSub2 =
CommentSub3 =
IDMethodType =
MethodName =
Mission = 1 ; 12.7888 ; ;
MissionSub = 0
RecordType = 1
[Attributes]
Averaging = 10
CalFactor = 0
Deviation = 12.7888
FlashCount = 1
IDBasisSpec =
IDDataBack =
IDDataCal =
IntegrationTime = 512
Maximum = 14.0468
P31 = 0
P31e = 0
PathLength = 10
PathLengthCustomOn = 0
RAWDynamic = 65535
Salinity = 0
SpectrumType = Waterbase
Temperature = 21.6
Unit1 = $01 $01 Wavelength nm
Unit2 = $03 $05 Intensity counts
Unit3 = $f0 $05 Error counts
Unit4 = $f1 $00 Status
lampLEDs = 255
lampReference[0] = 0
lampReference[1] = 0
p999 = 0
tempLampModule = 24.9625
tempMainCPU = 28.125
tempRefDiode = 0
tempSpectrometer = 27.3531
[END] of [Attributes]
[DATA]
0 8 0 0
304.594 0.0210566 0 0
307.975 0.0231822 0 0
311.356 0.0252777 0 0
314.738 0.0283652 0 0
318.12 0.0320467 0 0
321.503 0.036545 0 0
324.887 0.0395432 0 0
328.27 0.0447027 0 0
331.655 0.0490757 0 0
335.04 0.0535368 0 0
338.425 0.0582091 0 0
341.811 0.0632415 0 0
345.197 0.0693582 0 0
348.584 0.0762549 0 0
351.971 0.0862348 0 0
355.359 0.105558 0 0
358.746 0.166794 0 0
362.135 0.444266 0 0
365.523 1.61241 0 0
368.912 4.71591 0 0
372.302 8.63911 0 0
375.692 9.90672 0 0
379.082 7.6983 0 0
382.472 4.68655 0 0
385.863 2.8009 0 0
389.254 2.16211 0 0
392.645 2.63598 0 0
396.037 4.19367 0 0
399.429 6.57256 0 0
402.821 8.72203 0 0
406.213 9.42163 0 0
409.606 8.55542 0 0
412.999 6.94181 0 0
416.392 5.29259 0 0
419.785 3.98554 0 0
423.179 3.17615 0 0
426.572 2.87384 0 0
429.966 3.06099 0 0
433.36 3.76249 0 0
436.754 5.08917 0 0
440.149 7.18661 0 0
443.543 9.91796 0 0
446.938 12.517 0 0
450.332 14.0135 0 0
453.727 14.0468 0 0
457.122 13.0209 0 0
460.517 11.4783 0 0
463.912 9.72502 0 0
467.307 8.00122 0 0
470.702 6.54226 0 0
474.097 5.40552 0 0
477.492 4.52299 0 0
480.887 3.83399 0 0
484.282 3.31924 0 0
487.678 2.98197 0 0
491.073 2.8091 0 0
494.468 2.779 0 0
497.863 2.86794 0 0
501.258 3.05796 0 0
504.653 3.32977 0 0
508.048 3.65804 0 0
511.442 4.03031 0 0
514.837 4.43456 0 0
518.232 4.86578 0 0
521.626 5.3154 0 0
525.021 5.76721 0 0
528.415 6.21011 0 0
531.809 6.64985 0 0
535.203 7.0616 0 0
538.596 7.4466 0 0
541.99 7.79216 0 0
545.383 8.07482 0 0
548.776 8.28954 0 0
552.169 8.43504 0 0
555.562 8.51663 0 0
558.954 8.53201 0 0
562.347 8.49503 0 0
565.739 8.39947 0 0
569.13 8.26454 0 0
572.522 8.0873 0 0
575.913 7.85227 0 0
579.304 7.56516 0 0
582.694 7.21857 0 0
586.084 6.8161 0 0
589.474 6.35792 0 0
592.864 5.8454 0 0
596.253 5.31237 0 0
599.642 4.84331 0 0
603.03 4.47609 0 0
606.418 4.18657 0 0
609.806 3.9524 0 0
613.193 3.7444 0 0
616.58 3.55138 0 0
619.966 3.37612 0 0
623.352 3.21094 0 0
626.737 3.05199 0 0
630.122 2.89697 0 0
633.507 2.73312 0 0
636.891 2.556 0 0
640.274 2.36686 0 0
643.658 2.17118 0 0
647.04 1.97787 0 0
650.422 1.79679 0 0
653.804 1.62428 0 0
657.184 1.46539 0 0
660.565 1.31924 0 0
663.945 1.18516 0 0
667.324 1.06363 0 0
670.702 0.959542 0 0
674.08 0.871582 0 0
677.458 0.793595 0 0
680.835 0.722821 0 0
684.211 0.6558 0 0
687.586 0.592462 0 0
690.961 0.531973 0 0
694.335 0.474165 0 0
697.709 0.419892 0 0
701.082 0.370012 0 0
704.454 0.324413 0 0
707.825 0.282091 0 0
711.196 0.243811 0 0
714.566 0.208403 0 0
717.935 0.176369 0 0
721.303 0.147406 0 0
724.671 0.12289 0 0
728.038 0.101408 0 0
731.404 0.0822255 0 0
734.769 0.0672734 0 0
738.134 0.0567692 0 0
741.497 0.0499812 0 0
744.86 0.0444286 0 0
748.222 0.0406367 0 0
751.583 0.0364964 0 0
754.944 0.0336154 0 0
758.303 0.0301431 0 0
761.662 0.0275487 0 0
765.019 0.0251491 0 0
768.376 0.0236934 0 0
771.732 0.0215465 0 0
775.087 0.0189808 0 0
778.441 0.0179091 0 0
781.794 0.0161808 0 0
785.146 0.0156396 0 0
788.497 0.0140658 0 0
791.847 0.0138507 0 0
795.196 0.0120979 0 0
798.544 0.0113958 0 0
801.891 0.0110699 0 0
805.237 0.00978003 0 0
808.583 0.00946944 0 0
811.927 0.00800721 0 0
815.269 0.00719762 0 0
818.611 0.00572726 0 0
821.952 0.00526265 0 0
825.292 0.00452969 0 0
828.63 0.00450948 0 0
831.968 0.00366555 0 0
835.304 0.00317755 0 0
838.64 0.00343594 0 0
841.974 0.00266997 0 0
845.307 0.00234687 0 0
848.639 0.00265867 0 0
851.969 0.00243576 0 0
855.299 0.00205385 0 0
858.627 0.00109726 0 0
861.954 0.00183287 0 0
865.28 0.000746415 0 0
868.604 0.00160104 0 0
871.927 0.00210132 0 0
875.25 0.00212947 0 0
878.57 0.00113513 0 0
881.89 0.000910693 0 0
885.208 0.00181068 0 0
888.525 0.00173474 0 0
891.841 0.00156189 0 0
895.155 0.00140958 0 0
898.468 0.00175973 0 0
901.78 0.00190556 0 0
905.09 0.00130031 0 0
908.399 0.00206208 0 0
911.707 0.00175176 0 0
915.013 0.00268119 0 0
918.318 0.00133652 0 0
921.621 0.00235074 0 0
924.923 0.00213741 0 0
928.224 0.00193116 0 0
931.523 0.00167193 0 0
934.821 0.00313712 0 0
938.117 0.00399409 0 0
941.412 0.00236253 0 0
944.705 0.00798147 0 0
947.997 0.00834754 0 0
951.287 0.00336406 0 0
954.576 0.0129665 0 0
957.864 0.00995627 0 0
961.149 0.0113662 0 0
964.434 0.00182761 0 0
967.716 0.0479155 0 0
970.998 -0.0120681 0 0
974.277 0.0521257 0 0
977.555 -0.00392658 0 0
980.831 -0.00331801 0 0
984.106 -0.00542654 0 0
987.379 -0.000761557 0 0
990.651 -0.000917581 0 0
993.921 -0.000709999 0 0
997.189 -0.000316759 0 0
1000.46 -0.000508475 0 0
1003.72 -0.000456869 0 0
1006.98 -0.000226175 0 0
1010.25 -0.000160049 0 0
1013.5 -1.5969e-05 0 0
1016.76 -1.957e-05 0 0
1020.02 3.26416e-06 0 0
1023.27 3.09945e-05 0 0
1026.53 0.000103156 0 0
1029.78 -3.10342e-05 0 0
1033.03 -1.69953e-05 0 0
1036.28 -0.000127137 0 0
1039.52 -6.73423e-05 0 0
1042.77 1.57546e-05 0 0
1046.01 0.000185623 0 0
1049.25 0.000144434 0 0
1052.49 -0.00018054 0 0
1055.72 3.17146e-05 0 0
1058.96 -5.29127e-05 0 0
1062.19 -0.000215598 0 0
1065.42 0.000147456 0 0
1068.65 -4.9335e-06 0 0
1071.88 -0.000128095 0 0
1075.1 -0.000125368 0 0
1078.33 7.34804e-05 0 0
1081.55 -6.86384e-05 0 0
1084.77 -0.000124123 0 0
1087.99 -8.19662e-05 0 0
1091.2 0.000177756 0 0
1094.42 -5.58525e-06 0 0
1097.63 -5.95557e-05 0 0
1100.84 -0.000182336 0 0
1104.04 -0.000262782 0 0
1107.25 0.000259209 0 0
1110.45 -0.000167749 0 0
1113.66 -0.000399004 0 0
1116.86 -0.000423914 0 0
1120.05 2.15958e-05 0 0
1123.25 0.000275597 0 0
1126.44 0.000273604 0 0
1129.63 0.000316467 0 0
1132.82 -0.000118352 0 0
1136.01 -8.5051e-05 0 0
1139.19 -0.000267692 0 0
1142.38 0.000135329 0 0
1145.56 -1.74812e-05 0 0
1148.74 0.000689914 0 0
1151.91 0.00185774 0 0
[END] of [DATA]
[END] of Spectrum

@ -0,0 +1,312 @@
[Spectrum]
Version = 1
IDData = ALAB_2020-12-04_17-11-55_757_061
IDDevice = OSCAR_B055
IDDataType = SPECTRUM
IDDataTypeSub1 = Reflectivity
IDDataTypeSub2 =
IDDataTypeSub3 =
DateTime = 2020-12-04 17:11:55
PositionLatitude = 0
PositionLongitude = 0
Comment = Reflectivity B055
CommentSub1 = Referenz Lamda850_100mmK
CommentSub2 = WL-Bereich 360-750 nm
CommentSub3 =
IDMethodType = Oscar Control
MethodName = OSCAR_B055
Mission = 1 ; 9.75544 ; ;
MissionSub = 0
RecordType = 0
[Attributes]
Averaging = 10
CalFactor = 0
Deviation = 9.75544
FlashCount = 1
IDBasisSpec =
IDDataBack =
IDDataCal =
IntegrationTime = 2048
Maximum = 3.21223
P31 = 0
P31e = 0
PathLength = 100
PathLengthCustomOn = 0
RAWDynamic = 65535
Salinity = 0
SpectrumType = Nigrosin
Temperature = 20.7
Unit1 = $01 $01 Wavelength nm
Unit2 = $0d $08 Reflectivity 1
Unit3 = $0d $08 Reflectivity 1
Unit4 = $f1 $00 Status
lampLEDs = 255
lampReference[0] = 0
lampReference[1] = 0
p999 = 0
tempLampModule = 27.3125
tempMainCPU = 30.4312
tempRefDiode = 0
tempSpectrometer = 29.7562
[END] of [Attributes]
[DATA]
0 10 0 0
304.594 -NAN 0 0
307.975 -NAN 0 0
311.356 -NAN 0 0
314.738 -NAN 0 0
318.12 -NAN 0 0
321.503 -NAN 0 0
324.887 -NAN 0 0
328.27 -NAN 0 0
331.655 -NAN 0 0
335.04 -NAN 0 0
338.425 -NAN 0 0
341.811 -NAN 0 0
345.197 -NAN 0 0
348.584 -NAN 0 0
351.971 -NAN 0 0
355.359 -NAN 0 0
358.746 -NAN 0 0
362.135 0.978428499401649 0 0
365.523 0.978965953688747 0 0
368.912 0.97929591821286 0 0
372.302 0.979465872969741 0 0
375.692 0.979531290603612 0 0
379.082 0.979319242805614 0 0
382.472 0.979305911503146 0 0
385.863 0.979221413496553 0 0
389.254 0.979197496540882 0 0
392.645 0.979323668830666 0 0
396.037 0.979331245986962 0 0
399.429 0.979287619477527 0 0
402.821 0.979119533409878 0 0
406.213 0.978973859065406 0 0
409.606 0.978790753060641 0 0
412.999 0.978551720462383 0 0
416.392 0.978456786967265 0 0
419.785 0.978354214857909 0 0
423.179 0.978314542339825 0 0
426.572 0.978245299398871 0 0
429.966 0.978166588669129 0 0
433.36 0.977966897521694 0 0
436.754 0.977884151118849 0 0
440.149 0.977693826499285 0 0
443.543 0.977596798279483 0 0
446.938 0.977382806578674 0 0
450.332 0.977151968740062 0 0
453.727 0.976927976192701 0 0
457.122 0.976675617101858 0 0
460.517 0.976526056087864 0 0
463.912 0.976279834695182 0 0
467.307 0.976158213212832 0 0
470.702 0.975968223809452 0 0
474.097 0.975864381832555 0 0
477.492 0.97564814733514 0 0
480.887 0.975422871055887 0 0
484.282 0.975378267554234 0 0
487.678 0.97518550259529 0 0
491.073 0.975122332762432 0 0
494.468 0.974938884041278 0 0
497.863 0.974916392305076 0 0
501.258 0.974752516633885 0 0
504.653 0.974569311326216 0 0
508.048 0.974550022680223 0 0
511.442 0.974370672460727 0 0
514.837 0.974302747865652 0 0
518.232 0.974099614706827 0 0
521.626 0.973922361261296 0 0
525.021 0.973762054489896 0 0
528.415 0.973484174796049 0 0
531.809 0.973367498606616 0 0
535.203 0.973039382374481 0 0
538.596 0.972943285074893 0 0
541.99 0.972711445811679 0 0
545.383 0.972537887684075 0 0
548.776 0.972412371662826 0 0
552.169 0.972301685378471 0 0
555.562 0.972123819682298 0 0
558.954 0.971885560850787 0 0
562.347 0.971717847597481 0 0
565.739 0.971550854437924 0 0
569.13 0.971328384620963 0 0
572.522 0.971197927540782 0 0
575.913 0.971011504601151 0 0
579.304 0.970807629136665 0 0
582.694 0.9708116570687 0 0
586.084 0.97066512772835 0 0
589.474 0.970838032007098 0 0
592.864 0.970842236916884 0 0
596.253 0.970940116701782 0 0
599.642 0.97084709835456 0 0
603.03 0.970753920057021 0 0
606.418 0.970654749248275 0 0
609.806 0.970326360121843 0 0
613.193 0.970256797566305 0 0
616.58 0.970026140408362 0 0
619.966 0.969923302576538 0 0
623.352 0.969772124401762 0 0
626.737 0.969571939958024 0 0
630.122 0.969399888366939 0 0
633.507 0.969078647824134 0 0
636.891 0.968921269439267 0 0
640.274 0.968677827062214 0 0
643.658 0.968679533496021 0 0
647.04 0.968509398556534 0 0
650.422 0.968563862841168 0 0
653.804 0.968438132514117 0 0
657.184 0.968184350493791 0 0
660.565 0.967865577127992 0 0
663.945 0.967486924999228 0 0
667.324 0.967488176527944 0 0
670.702 0.966979931069267 0 0
674.08 0.966744441155398 0 0
677.458 0.966607254162634 0 0
680.835 0.966542448319853 0 0
684.211 0.966509544212223 0 0
687.586 0.966418626742675 0 0
690.961 0.966579055749823 0 0
694.335 0.966860555377936 0 0
697.709 0.966943564328317 0 0
701.082 0.96724436824475 0 0
704.454 0.967896682193911 0 0
707.825 0.968250713384282 0 0
711.196 0.969339433411549 0 0
714.566 0.971069610849988 0 0
717.935 0.972660542809938 0 0
721.303 0.973427173090292 0 0
724.671 0.977484950025803 0 0
728.038 0.982323543105391 0 0
731.404 0.989647380222074 0 0
734.769 0.997665689658877 0 0
738.134 1.00352514426919 0 0
741.497 1.01139618545043 0 0
744.86 1.01267967530863 0 0
748.222 1.02058869844595 0 0
751.583 -NAN 0 0
754.944 -NAN 0 0
758.303 -NAN 0 0
761.662 -NAN 0 0
765.019 -NAN 0 0
768.376 -NAN 0 0
771.732 -NAN 0 0
775.087 -NAN 0 0
778.441 -NAN 0 0
781.794 -NAN 0 0
785.146 -NAN 0 0
788.497 -NAN 0 0
791.847 -NAN 0 0
795.196 -NAN 0 0
798.544 -NAN 0 0
801.891 -NAN 0 0
805.237 -NAN 0 0
808.583 -NAN 0 0
811.927 -NAN 0 0
815.269 -NAN 0 0
818.611 -NAN 0 0
821.952 -NAN 0 0
825.292 -NAN 0 0
828.63 -NAN 0 0
831.968 -NAN 0 0
835.304 -NAN 0 0
838.64 -NAN 0 0
841.974 -NAN 0 0
845.307 -NAN 0 0
848.639 -NAN 0 0
851.969 -NAN 0 0
855.299 -NAN 0 0
858.627 -NAN 0 0
861.954 -NAN 0 0
865.28 -NAN 0 0
868.604 -NAN 0 0
871.927 -NAN 0 0
875.25 -NAN 0 0
878.57 -NAN 0 0
881.89 -NAN 0 0
885.208 -NAN 0 0
888.525 -NAN 0 0
891.841 -NAN 0 0
895.155 -NAN 0 0
898.468 -NAN 0 0
901.78 -NAN 0 0
905.09 -NAN 0 0
908.399 -NAN 0 0
911.707 -NAN 0 0
915.013 -NAN 0 0
918.318 -NAN 0 0
921.621 -NAN 0 0
924.923 -NAN 0 0
928.224 -NAN 0 0
931.523 -NAN 0 0
934.821 -NAN 0 0
938.117 -NAN 0 0
941.412 -NAN 0 0
944.705 -NAN 0 0
947.997 -NAN 0 0
951.287 -NAN 0 0
954.576 -NAN 0 0
957.864 -NAN 0 0
961.149 -NAN 0 0
964.434 -NAN 0 0
967.716 -NAN 0 0
970.998 -NAN 0 0
974.277 -NAN 0 0
977.555 -NAN 0 0
980.831 -NAN 0 0
984.106 -NAN 0 0
987.379 -NAN 0 0
990.651 -NAN 0 0
993.921 -NAN 0 0
997.189 -NAN 0 0
1000.46 -NAN 0 0
1003.72 -NAN 0 0
1006.98 -NAN 0 0
1010.25 -NAN 0 0
1013.5 -NAN 0 0
1016.76 -NAN 0 0
1020.02 -NAN 0 0
1023.27 -NAN 0 0
1026.53 -NAN 0 0
1029.78 -NAN 0 0
1033.03 -NAN 0 0
1036.28 -NAN 0 0
1039.52 -NAN 0 0
1042.77 -NAN 0 0
1046.01 -NAN 0 0
1049.25 -NAN 0 0
1052.49 -NAN 0 0
1055.72 -NAN 0 0
1058.96 -NAN 0 0
1062.19 -NAN 0 0
1065.42 -NAN 0 0
1068.65 -NAN 0 0
1071.88 -NAN 0 0
1075.1 -NAN 0 0
1078.33 -NAN 0 0
1081.55 -NAN 0 0
1084.77 -NAN 0 0
1087.99 -NAN 0 0
1091.2 -NAN 0 0
1094.42 -NAN 0 0
1097.63 -NAN 0 0
1100.84 -NAN 0 0
1104.04 -NAN 0 0
1107.25 -NAN 0 0
1110.45 -NAN 0 0
1113.66 -NAN 0 0
1116.86 -NAN 0 0
1120.05 -NAN 0 0
1123.25 -NAN 0 0
1126.44 -NAN 0 0
1129.63 -NAN 0 0
1132.82 -NAN 0 0
1136.01 -NAN 0 0
1139.19 -NAN 0 0
1142.38 -NAN 0 0
1145.56 -NAN 0 0
1148.74 -NAN 0 0
1151.91 -NAN 0 0
[END] of [DATA]
[END] of Spectrum

@ -0,0 +1,197 @@
[Spectrum]
Version = 1
IDData = absorption coefficients of pure water
IDDevice = OSCAR_B047
IDDataType = SPECTRUM
IDDataTypeSub1 = CALIBRATED
IDDataTypeSub2 = pure water
IDDataTypeSub3 = Average of 10
DateTime = 2017-12-11 12:00:07
PositionLatitude = 0
PositionLongitude = 0
Comment = pure water
CommentSub1 =
CommentSub2 =
CommentSub3 =
IDMethodType = SingleSpecCalc
MethodName = SingleSpecCalc
Mission = 1 ; 9.67752 ; ;
MissionSub = 0
RecordType = 1
[Attributes]
Averaging = 1
CalFactor = 0
Deviation = 9.67752
FlashCount = 1
IDBasisSpec =
IDDataBack =
IDDataCal =
IntegrationTime = 1024
Maximum = 4.5334
P31 = 0
P31e = 0
PathLength = 1000
PathLengthCustomOn = 0
RAWDynamic = 65535
Salinity = 0
SpectrumType = Calibrated
Temperature = 20
Unit1 = $01 $01 Wavelength nm
Unit2 = $03 $00 Intensity
Unit3 = $f0 $00 Error
Unit4 = $f1 $00 Status
lampLEDs = 255
lampReference[0] = 0
lampReference[1] = 0
p999 = 0
tempLampModule = 28.25
tempMainCPU = 31.375
tempRefDiode = 0
tempSpectrometer = 30.5625
[END] of [Attributes]
[DATA]
0 9 0 0
360 0.0066 0.0007 0
365 0.0063 0.0007 0
370 0.0060 0.0007 0
375 0.0056 0.0007 1
380 0.0052 0.0007 0
385 0.0050 0.0007 0
390 0.0048 0.0007 0
395 0.0047 0.0007 0
400 0.0046 0.0007 0
405 0.0046 0.0007 0
410 0.0046 0.0007 0
415 0.0046 0.0006 0
420.0 0.00454 0.0006 14
422.5 0.00474 0.0006 13
425.0 0.00478 0.0006 14
427.5 0.00482 0.0006 13
430.0 0.00495 0.0006 12
432.5 0.00504 0.0005 11
435.0 0.00530 0.0005 11
437.5 0.00580 0.0005 10
440.0 0.00635 0.0005 9
442.5 0.00696 0.0005 9
445.0 0.00751 0.0006 8
447.5 0.00830 0.0005 7
450.0 0.00922 0.0005 6
452.5 0.00969 0.0004 6
455.0 0.00962 0.0004 5
457.5 0.00957 0.0004 5
460.0 0.00979 0.0005 6
462.5 0.01005 0.0005 6
465.0 0.01011 0.0006 7
467.5 0.0102 0.0006 6
470.0 0.0106 0.0005 6
472.5 0.0109 0.0008 8
475.0 0.0114 0.0007 7
477.5 0.0121 0.0008 8
480.0 0.0127 0.0008 7
482.5 0.0131 0.0008 7
485.0 0.0136 0.0007 6
487.5 0.0144 0.0007 6
490.0 0.0150 0.0007 5
492.5 0.0162 0.0014 9
495.0 0.0173 0.0010 6
497.5 0.0191 0.0014 8
500.0 0.0204 0.0011 6
502.5 0.0228 0.0012 6
505.0 0.0256 0.0013 6
507.5 0.0280 0.0010 5
510.0 0.0325 0.0011 4
512.5 0.0372 0.0012 4
515.0 0.0396 0.0012 4
517.5 0.0399 0.0015 5
520.0 0.0409 0.0009 3
522.5 0.0416 0.0014 4
525.0 0.0417 0.0010 4
527.5 0.0428 0.0017 5
530.0 0.0434 0.0011 4
532.5 0.0447 0.0017 5
535.0 0.0452 0.0012 4
537.5 0.0466 0.0015 4
540.0 0.0474 0.0010 3
542.5 0.0489 0.0016 4
545.0 0.0511 0.0011 3
547.5 0.0537 0.0016 4
550.0 0.0565 0.0011 3
552.5 0.0593 0.0012 3
555.0 0.0596 0.0012 3
557.5 0.0606 0.0014 4
560.0 0.0619 0.0010 3
562.5 0.0640 0.0015 4
565.0 0.0642 0.0009 3
567.5 0.0672 0.0014 3
570.0 0.0695 0.0011 3
572.5 0.0733 0.0017 4
575.0 0.0772 0.0011 3
577.5 0.0836 0.0016 3
580.0 0.0896 0.0012 3
582.5 0.0989 0.0016 3
585.0 0.1100 0.0012 3
587.5 0.1220 0.0018 3
590.0 0.1351 0.0012 3
592.5 0.1516 0.0017 3
595.0 0.1672 0.0014 3
597.5 0.1925 0.0019 3
600.0 0.2224 0.0017 3
602.5 0.2470 0.0023 3
605.0 0.2577 0.0019 3
607.5 0.2629 0.0028 3
610.0 0.2644 0.0019 3
612.5 0.2665 0.0023 3
615.0 0.2678 0.0019 3
617.5 0.2707 0.0026 3
620.0 0.2755 0.0025 3
622.5 0.2810 0.0039 3
625.0 0.2834 0.0028 3
627.5 0.2904 0.0039 3
630.0 0.2916 0.0027 3
632.5 0.2995 0.0038 3
635.0 0.3012 0.0028 3
637.5 0.3077 0.0049 3
640.0 0.3108 0.0028 3
642.5 0.322 0.005 3
645.0 0.325 0.003 3
647.5 0.335 0.004 3
650.0 0.340 0.003 3
652.5 0.358 0.006 3
655.0 0.371 0.003 3
657.5 0.393 0.006 3
660.0 0.410 0.004 3
662.5 0.424 0.005 3
665.0 0.429 0.004 3
667.5 0.436 0.005 3
670.0 0.439 0.004 3
672.5 0.448 0.007 3
675.0 0.448 0.004 3
677.5 0.461 0.006 3
680.0 0.465 0.004 3
682.5 0.478 0.006 3
685.0 0.486 0.004 3
687.5 0.502 0.006 3
690.0 0.516 0.004 3
692.5 0.538 0.007 3
695.0 0.559 0.005 3
697.5 0.592 0.008 3
700.0 0.624 0.006 3
702.5 0.663 0.008 3
705.0 0.704 0.006 3
707.5 0.756 0.009 3
710.0 0.827 0.007 3
712.5 0.914 0.011 3
715.0 1.007 0.009 3
717.5 1.119 0.014 3
720.0 1.231 0.011 3
722.5 1.356 0.008 3
725.0 1.489 0.006 3
727.5 1.678 0.007 3
730 1.97 0.05 1
735 2.51 0.04 1
740 2.78 0.04 1
745 2.83 0.04 1
750 2.85 0.04 1
[END] of [DATA]
[END] of Spectrum

@ -0,0 +1,27 @@
algorithm:
'A720': 0
'PureWater': 0
'PureWater2': 0
comsetting:
baudrate: 9600
bytesize: 8
parity: N
port: COM1
stopbit: 1
device:
UIPath: 150
UISN: B055
logsetting:
LogInterval: 1
RefreshInterval: 0
plotsetting:
LineBegin: 0
LineInterval: 1
register:
DataBeginAddress: 2614
SNAddress: 2840
SNLen: 5
WLBeginAddress: 2102
count: 2
functioncode: 3
slaveaddress: 1

@ -0,0 +1,32 @@
from pathlib import Path, PurePath
from mylogger import log
from readcal import ReadCal
from myconfig import CAL_DIR, DATA_DIR, FILE_MARK, DeviceType
class Configuration:
def __init__(self, ) -> None:
log.info(f"Viper Configure init: ", __name__, "", "")
self.device_type = None
self.configuration =None
pass
def setSystemCfgDict(self, cfg:dict) -> None:
self.configuration = cfg
log.info(f"self.configuration : {self.configuration} ", __name__, "", "")
pass
def get_wl_from_datafile(self, fpath) -> None:
# self.cfgtool = Config()
if fpath.exists( ):
res = ReadCal.read_columns_set_by_mark( fpath, FILE_MARK, 1 )
self.configuration.update({ "wavelength" : res[1][0] })
pass
def getCalConfiguration(self) -> None:
pass

File diff suppressed because it is too large Load Diff

@ -0,0 +1,18 @@
B055;362.135;365.523;368.912;372.302;375.692;379.082;382.472;385.863;389.254;392.645;396.037;399.429;402.821;406.213;409.606;412.999;416.392;419.785;423.179;426.572;429.966;433.36;436.754;440.149;443.543;446.938;450.332;453.727;457.122;460.517;463.912;467.307;470.702;474.097;477.492;480.887;484.282;487.678;491.073;494.468;497.863;501.258;504.653;508.048;511.442;514.837;518.232;521.626;525.021;528.415;531.809;535.203;538.596;541.99;545.383;548.776;552.169;555.562;558.954;562.347;565.739;569.13;572.522;575.913;579.304;582.694;586.084;589.474;592.864;596.253;599.642;603.03;606.418;609.806;613.193;616.58;619.966;623.352;626.737;630.122;633.507;636.891;640.274;643.658;647.04;650.422;653.804;657.184;660.565;663.945;667.324;670.702;674.08;677.458;680.835;684.211;687.586;690.961;694.335;697.709;701.082;704.454;707.825;711.196;714.566;717.935;721.303
2023-04-11 20:07:27;1.0;1.0;1.0;1.0;1.0;1.0;1.0;1.0;1.0;1.0;1.0;1.0;1.0;1.0;-10.763668055027939;8.305640072501342;31.637826554877694;48.03477977281296;51.94904038253991;43.92046873517888;30.282275085971904;18.515274810999323;13.658622670969802;18.370134441351663;29.40783794382829;41.17537487525726;49.33643700339432;51.67851518715106;48.73493019741106;42.65339654617092;35.260104682961405;28.008926326954338;22.451500039132164;19.917594700410206;21.015444700157946;25.489475650108464;32.756025413305224;42.06435812027997;51.81698014846449;59.61323203088072;63.688920586051836;63.86911181347037;61.27553173312963;57.07070900159253;51.8052855352636;45.96670425987968;40.314358632389755;35.271352518068596;30.806216342783753;26.857135218342812;23.55330174047621;21.186169723572256;19.916316730516474;19.729283211564656;20.467222928242798;21.934437171604444;23.8973322628643;26.100847575755644;28.417908858283532;30.753125068757775;33.0712381305316;35.32927088078379;37.459065942721274;39.429152460663026;41.285050198547665;42.940430138711655;44.42081263576579;45.694708189031104;46.69307016781613;47.41973251988903;47.88970073237569;48.13385899043243;48.14158818851574;47.96181848655466;47.57067698627792;47.02983018409779;46.327729045432555;45.394914823373846;44.236406623066;42.80513495789607;41.072946813848205;39.00008846084816;36.52804689988775;33.74993494537631;31.063365858214304;28.72079005511716;26.66138106482925;24.8053096479965;22.968829922528794;21.015715961676975;18.9376609840618;16.682009982738663;14.20249000364825;11.184361647225444;6.9382609934193535;1.5423016933942209;2.483037386309892;3.0775737211799967;3.043403263161106;2.3469762513268866;0.2497067928830013;-3.6112874940500985;-10.674480324842285;-3.1305892821692707;0.7576967304456016;3.46920512317714;5.705835911986699
2020-01-01 11:51:00;1.0;1.0;1.0;1.0;1.0;1.0;1.0;1.0;1.0;1.0;1.0;1.0;1.0;1.0;8.415412981193239;3.5996009682587506;31.338329488965524;48.7749513729038;53.06382072824175;45.30875693934652;31.254677437114978;17.532611772316216;10.779726040523236;15.838614015715283;28.191866228270005;40.66985662655916;49.080572139996015;51.48319799151623;48.500883933779164;42.28292181009363;34.61451378177913;26.92226639410169;20.892862896209724;18.239209735086014;19.890747869186736;25.35852991591349;33.521274713508184;43.290769850459824;53.1152687544041;60.80908367848658;64.76485312234782;64.85099453829739;62.17766314472533;57.88546252994962;52.50454031350051;46.49689704670959;40.60044195055234;35.23342648168196;30.367620364654808;25.94954293423029;22.145442973056532;19.34566939986061;17.792867190973404;17.517315105555916;18.344250258868357;20.030198711674522;22.272635497046114;24.763130908702973;27.345401827467224;29.908644493688083;32.4160050563308;34.832033933363604;37.09136990438783;39.17081374925895;41.119807229076606;42.85536849200251;44.409104644778054;45.75285556671083;46.81989555171627;47.61231414995964;48.14106135144582;48.435164813011575;48.49199342321336;48.36182514653572;48.02130221181661;47.53514341402985;46.88757443079104;46.013271428886725;44.92010426348285;43.55986252876977;41.91835732244482;39.95833581445667;37.635655630271394;35.05192901881426;32.60924548135646;30.56311367000687;28.842867983650773;27.369001440848916;25.993083685487285;24.65362166462979;23.383867807324293;22.133808226335944;20.87703253197588;19.59976702684183;18.180525704012343;16.56799949335673;14.741236089072956;12.735637877309088;10.639157063826262;8.5763589883041;6.572572712242101;4.7513722915734835;3.173216882725356;1.9092118626120613;1.0498064519790538;0.6520100533130619;0.6256365637083021
2020-01-01 11:52:00;1.0;1.0;1.0;1.0;1.0;1.0;1.0;1.0;1.0;1.0;1.0;1.0;1.0;1.0;8.415412981193239;3.5996009682587506;31.338329488965524;48.7749513729038;53.06382072824175;45.30875693934652;31.254677437114978;17.532611772316216;10.779726040523236;15.838614015715283;28.191866228270005;40.66985662655916;49.080572139996015;51.48319799151623;48.500883933779164;42.28292181009363;34.61451378177913;26.92226639410169;20.892862896209724;18.239209735086014;19.890747869186736;25.35852991591349;33.521274713508184;43.290769850459824;53.1152687544041;60.80908367848658;64.76485312234782;64.85099453829739;62.17766314472533;57.88546252994962;52.50454031350051;46.49689704670959;40.60044195055234;35.23342648168196;30.367620364654808;25.94954293423029;22.145442973056532;19.34566939986061;17.792867190973404;17.517315105555916;18.344250258868357;20.030198711674522;22.272635497046114;24.763130908702973;27.345401827467224;29.908644493688083;32.4160050563308;34.832033933363604;37.09136990438783;39.17081374925895;41.119807229076606;42.85536849200251;44.409104644778054;45.75285556671083;46.81989555171627;47.61231414995964;48.14106135144582;48.435164813011575;48.49199342321336;48.36182514653572;48.02130221181661;47.53514341402985;46.88757443079104;46.013271428886725;44.92010426348285;43.55986252876977;41.91835732244482;39.95833581445667;37.635655630271394;35.05192901881426;32.60924548135646;30.56311367000687;28.842867983650773;27.369001440848916;25.993083685487285;24.65362166462979;23.383867807324293;22.133808226335944;20.87703253197588;19.59976702684183;18.180525704012343;16.56799949335673;14.741236089072956;12.735637877309088;10.639157063826262;8.5763589883041;6.572572712242101;4.7513722915734835;3.173216882725356;1.9092118626120613;1.0498064519790538;0.6520100533130619;0.6256365637083021
2020-01-01 11:53:00;1.0;1.0;1.0;1.0;1.0;1.0;1.0;1.0;1.0;1.0;1.0;1.0;1.0;1.0;8.415412981193239;3.5996009682587506;31.338329488965524;48.7749513729038;53.06382072824175;45.30875693934652;31.254677437114978;17.532611772316216;10.779726040523236;15.838614015715283;28.191866228270005;40.66985662655916;49.080572139996015;51.48319799151623;48.500883933779164;42.28292181009363;34.61451378177913;26.92226639410169;20.892862896209724;18.239209735086014;19.890747869186736;25.35852991591349;33.521274713508184;43.290769850459824;53.1152687544041;60.80908367848658;64.76485312234782;64.85099453829739;62.17766314472533;57.88546252994962;52.50454031350051;46.49689704670959;40.60044195055234;35.23342648168196;30.367620364654808;25.94954293423029;22.145442973056532;19.34566939986061;17.792867190973404;17.517315105555916;18.344250258868357;20.030198711674522;22.272635497046114;24.763130908702973;27.345401827467224;29.908644493688083;32.4160050563308;34.832033933363604;37.09136990438783;39.17081374925895;41.119807229076606;42.85536849200251;44.409104644778054;45.75285556671083;46.81989555171627;47.61231414995964;48.14106135144582;48.435164813011575;48.49199342321336;48.36182514653572;48.02130221181661;47.53514341402985;46.88757443079104;46.013271428886725;44.92010426348285;43.55986252876977;41.91835732244482;39.95833581445667;37.635655630271394;35.05192901881426;32.60924548135646;30.56311367000687;28.842867983650773;27.369001440848916;25.993083685487285;24.65362166462979;23.383867807324293;22.133808226335944;20.87703253197588;19.59976702684183;18.180525704012343;16.56799949335673;14.741236089072956;12.735637877309088;10.639157063826262;8.5763589883041;6.572572712242101;4.7513722915734835;3.173216882725356;1.9092118626120613;1.0498064519790538;0.6520100533130619;0.6256365637083021
2020-01-01 11:54:00;1.0;1.0;1.0;1.0;1.0;1.0;1.0;1.0;1.0;1.0;1.0;1.0;1.0;1.0;8.415412981193239;3.5996009682587506;31.338329488965524;48.7749513729038;53.06382072824175;45.30875693934652;31.254677437114978;17.532611772316216;10.779726040523236;15.838614015715283;28.191866228270005;40.66985662655916;49.080572139996015;51.48319799151623;48.500883933779164;42.28292181009363;34.61451378177913;26.92226639410169;20.892862896209724;18.239209735086014;19.890747869186736;25.35852991591349;33.521274713508184;43.290769850459824;53.1152687544041;60.80908367848658;64.76485312234782;64.85099453829739;62.17766314472533;57.88546252994962;52.50454031350051;46.49689704670959;40.60044195055234;35.23342648168196;30.367620364654808;25.94954293423029;22.145442973056532;19.34566939986061;17.792867190973404;17.517315105555916;18.344250258868357;20.030198711674522;22.272635497046114;24.763130908702973;27.345401827467224;29.908644493688083;32.4160050563308;34.832033933363604;37.09136990438783;39.17081374925895;41.119807229076606;42.85536849200251;44.409104644778054;45.75285556671083;46.81989555171627;47.61231414995964;48.14106135144582;48.435164813011575;48.49199342321336;48.36182514653572;48.02130221181661;47.53514341402985;46.88757443079104;46.013271428886725;44.92010426348285;43.55986252876977;41.91835732244482;39.95833581445667;37.635655630271394;35.05192901881426;32.60924548135646;30.56311367000687;28.842867983650773;27.369001440848916;25.993083685487285;24.65362166462979;23.383867807324293;22.133808226335944;20.87703253197588;19.59976702684183;18.180525704012343;16.56799949335673;14.741236089072956;12.735637877309088;10.639157063826262;8.5763589883041;6.572572712242101;4.7513722915734835;3.173216882725356;1.9092118626120613;1.0498064519790538;0.6520100533130619;0.6256365637083021
2020-01-01 11:55:00;1.0;1.0;1.0;1.0;1.0;1.0;1.0;1.0;1.0;1.0;1.0;1.0;1.0;1.0;8.415412981193239;3.5996009682587506;31.338329488965524;48.7749513729038;53.06382072824175;45.30875693934652;31.254677437114978;17.532611772316216;10.779726040523236;15.838614015715283;28.191866228270005;40.66985662655916;49.080572139996015;51.48319799151623;48.500883933779164;42.28292181009363;34.61451378177913;26.92226639410169;20.892862896209724;18.239209735086014;19.890747869186736;25.35852991591349;33.521274713508184;43.290769850459824;53.1152687544041;60.80908367848658;64.76485312234782;64.85099453829739;62.17766314472533;57.88546252994962;52.50454031350051;46.49689704670959;40.60044195055234;35.23342648168196;30.367620364654808;25.94954293423029;22.145442973056532;19.34566939986061;17.792867190973404;17.517315105555916;18.344250258868357;20.030198711674522;22.272635497046114;24.763130908702973;27.345401827467224;29.908644493688083;32.4160050563308;34.832033933363604;37.09136990438783;39.17081374925895;41.119807229076606;42.85536849200251;44.409104644778054;45.75285556671083;46.81989555171627;47.61231414995964;48.14106135144582;48.435164813011575;48.49199342321336;48.36182514653572;48.02130221181661;47.53514341402985;46.88757443079104;46.013271428886725;44.92010426348285;43.55986252876977;41.91835732244482;39.95833581445667;37.635655630271394;35.05192901881426;32.60924548135646;30.56311367000687;28.842867983650773;27.369001440848916;25.993083685487285;24.65362166462979;23.383867807324293;22.133808226335944;20.87703253197588;19.59976702684183;18.180525704012343;16.56799949335673;14.741236089072956;12.735637877309088;10.639157063826262;8.5763589883041;6.572572712242101;4.7513722915734835;3.173216882725356;1.9092118626120613;1.0498064519790538;0.6520100533130619;0.6256365637083021
2020-01-01 11:56:00;1.0;1.0;1.0;1.0;1.0;1.0;1.0;1.0;1.0;1.0;1.0;1.0;1.0;1.0;8.415412981193239;3.5996009682587506;31.338329488965524;48.7749513729038;53.06382072824175;45.30875693934652;31.254677437114978;17.532611772316216;10.779726040523236;15.838614015715283;28.191866228270005;40.66985662655916;49.080572139996015;51.48319799151623;48.500883933779164;42.28292181009363;34.61451378177913;26.92226639410169;20.892862896209724;18.239209735086014;19.890747869186736;25.35852991591349;33.521274713508184;43.290769850459824;53.1152687544041;60.80908367848658;64.76485312234782;64.85099453829739;62.17766314472533;57.88546252994962;52.50454031350051;46.49689704670959;40.60044195055234;35.23342648168196;30.367620364654808;25.94954293423029;22.145442973056532;19.34566939986061;17.792867190973404;17.517315105555916;18.344250258868357;20.030198711674522;22.272635497046114;24.763130908702973;27.345401827467224;29.908644493688083;32.4160050563308;34.832033933363604;37.09136990438783;39.17081374925895;41.119807229076606;42.85536849200251;44.409104644778054;45.75285556671083;46.81989555171627;47.61231414995964;48.14106135144582;48.435164813011575;48.49199342321336;48.36182514653572;48.02130221181661;47.53514341402985;46.88757443079104;46.013271428886725;44.92010426348285;43.55986252876977;41.91835732244482;39.95833581445667;37.635655630271394;35.05192901881426;32.60924548135646;30.56311367000687;28.842867983650773;27.369001440848916;25.993083685487285;24.65362166462979;23.383867807324293;22.133808226335944;20.87703253197588;19.59976702684183;18.180525704012343;16.56799949335673;14.741236089072956;12.735637877309088;10.639157063826262;8.5763589883041;6.572572712242101;4.7513722915734835;3.173216882725356;1.9092118626120613;1.0498064519790538;0.6520100533130619;0.6256365637083021
2020-01-01 12:08:00;1.0;1.0;1.0;1.0;1.0;1.0;1.0;1.0;1.0;1.0;1.0;1.0;1.0;1.0;8.415412981193239;3.5996009682587506;31.338329488965524;48.7749513729038;53.06382072824175;45.30875693934652;31.254677437114978;17.532611772316216;10.779726040523236;15.838614015715283;28.191866228270005;40.66985662655916;49.080572139996015;51.48319799151623;48.500883933779164;42.28292181009363;34.61451378177913;26.92226639410169;20.892862896209724;18.239209735086014;19.890747869186736;25.35852991591349;33.521274713508184;43.290769850459824;53.1152687544041;60.80908367848658;64.76485312234782;64.85099453829739;62.17766314472533;57.88546252994962;52.50454031350051;46.49689704670959;40.60044195055234;35.23342648168196;30.367620364654808;25.94954293423029;22.145442973056532;19.34566939986061;17.792867190973404;17.517315105555916;18.344250258868357;20.030198711674522;22.272635497046114;24.763130908702973;27.345401827467224;29.908644493688083;32.4160050563308;34.832033933363604;37.09136990438783;39.17081374925895;41.119807229076606;42.85536849200251;44.409104644778054;45.75285556671083;46.81989555171627;47.61231414995964;48.14106135144582;48.435164813011575;48.49199342321336;48.36182514653572;48.02130221181661;47.53514341402985;46.88757443079104;46.013271428886725;44.92010426348285;43.55986252876977;41.91835732244482;39.95833581445667;37.635655630271394;35.05192901881426;32.60924548135646;30.56311367000687;28.842867983650773;27.369001440848916;25.993083685487285;24.65362166462979;23.383867807324293;22.133808226335944;20.87703253197588;19.59976702684183;18.180525704012343;16.56799949335673;14.741236089072956;12.735637877309088;10.639157063826262;8.5763589883041;6.572572712242101;4.7513722915734835;3.173216882725356;1.9092118626120613;1.0498064519790538;0.6520100533130619;0.6256365637083021
2020-01-01 11:51:00;8.417737297758135;3.6003210616146095;31.338272439002946;48.77492727918919;53.06380857297471;45.30874684378469;31.254671851695033;17.53261532414694;10.779672643743828;15.838631955112836;28.191967140583625;40.66995055518302;49.08065786270199;51.48328009262055;48.50097581388598;42.28304833654381;34.61469193371904;26.922484942198942;20.893064894784953;18.239370031948738;19.89097470286485;25.358833593133255;33.52153932962637;43.290956605696884;53.11539213296727;60.809175752703325;64.76493825822062;64.8510953221729;62.17781191356055;57.88568438935276;52.50491331016351;46.49746676033152;40.60118285600951;35.23435495825925;30.368672337783654;25.950675240662438;22.146517887380686;19.346519036982766;17.793509426865167;17.5179082380076;18.344992365267892;20.03118327542923;22.273787745746976;24.764244860684187;27.346338145237937;29.90948002948232;32.416802867203714;34.832844886797844;37.09223417373295;39.17173190982804;41.12081715938511;42.85653714763779;44.410469153844005;45.754426847107766;46.82171758485793;47.614446627227814;48.14370668978048;48.43825993770717;48.495229261930916;48.36508733085604;48.02462201317626;47.53850396910848;46.89102990740052;46.016831613096585;44.92375304290284;43.56351080009117;41.92204195611228;39.96199596378572;37.63919076941768;35.05530536201176;32.61203701781444;30.56541436137355;28.845430933487766;27.37208881829137;25.996611916755132;24.65729084277052;23.38739437277862;22.137022087802627;20.879814854326426;19.602063469247692;18.18186550000487;16.567816898314867;14.738317891495022;12.727998959540258;10.623177605896181;8.54560060332246;6.51966071209112;4.6657839884785455;3.036312907848326;1.6820459455679468;0.6921106974450838;0.12359578075040828;-0.09367329985645387;-0.031341689825133606;0.23717164699237966;0.6997800604297433;1.2979843274680154;2.0657283515050686;2.9615094560290176;3.9886574343032963;5.048029170775037;6.1827566231801345;7.400535839426023;8.609660807489144;9.866618625112752;11.165875582893802;12.525868733319928
2020-01-01 11:52:00;8.417737297758135;3.6003210616146095;31.338272439002946;48.77492727918919;53.06380857297471;45.30874684378469;31.254671851695033;17.53261532414694;10.779672643743828;15.838631955112836;28.191967140583625;40.66995055518302;49.08065786270199;51.48328009262055;48.50097581388598;42.28304833654381;34.61469193371904;26.922484942198942;20.893064894784953;18.239370031948738;19.89097470286485;25.358833593133255;33.52153932962637;43.290956605696884;53.11539213296727;60.809175752703325;64.76493825822062;64.8510953221729;62.17781191356055;57.88568438935276;52.50491331016351;46.49746676033152;40.60118285600951;35.23435495825925;30.368672337783654;25.950675240662438;22.146517887380686;19.346519036982766;17.793509426865167;17.5179082380076;18.344992365267892;20.03118327542923;22.273787745746976;24.764244860684187;27.346338145237937;29.90948002948232;32.416802867203714;34.832844886797844;37.09223417373295;39.17173190982804;41.12081715938511;42.85653714763779;44.410469153844005;45.754426847107766;46.82171758485793;47.614446627227814;48.14370668978048;48.43825993770717;48.495229261930916;48.36508733085604;48.02462201317626;47.53850396910848;46.89102990740052;46.016831613096585;44.92375304290284;43.56351080009117;41.92204195611228;39.96199596378572;37.63919076941768;35.05530536201176;32.61203701781444;30.56541436137355;28.845430933487766;27.37208881829137;25.996611916755132;24.65729084277052;23.38739437277862;22.137022087802627;20.879814854326426;19.602063469247692;18.18186550000487;16.567816898314867;14.738317891495022;12.727998959540258;10.623177605896181;8.54560060332246;6.51966071209112;4.6657839884785455;3.036312907848326;1.6820459455679468;0.6921106974450838;0.12359578075040828;-0.09367329985645387;-0.031341689825133606;0.23717164699237966;0.6997800604297433;1.2979843274680154;2.0657283515050686;2.9615094560290176;3.9886574343032963;5.048029170775037;6.1827566231801345;7.400535839426023;8.609660807489144;9.866618625112752;11.165875582893802;12.525868733319928
2020-01-01 11:53:00;8.417737297758135;3.6003210616146095;31.338272439002946;48.77492727918919;53.06380857297471;45.30874684378469;31.254671851695033;17.53261532414694;10.779672643743828;15.838631955112836;28.191967140583625;40.66995055518302;49.08065786270199;51.48328009262055;48.50097581388598;42.28304833654381;34.61469193371904;26.922484942198942;20.893064894784953;18.239370031948738;19.89097470286485;25.358833593133255;33.52153932962637;43.290956605696884;53.11539213296727;60.809175752703325;64.76493825822062;64.8510953221729;62.17781191356055;57.88568438935276;52.50491331016351;46.49746676033152;40.60118285600951;35.23435495825925;30.368672337783654;25.950675240662438;22.146517887380686;19.346519036982766;17.793509426865167;17.5179082380076;18.344992365267892;20.03118327542923;22.273787745746976;24.764244860684187;27.346338145237937;29.90948002948232;32.416802867203714;34.832844886797844;37.09223417373295;39.17173190982804;41.12081715938511;42.85653714763779;44.410469153844005;45.754426847107766;46.82171758485793;47.614446627227814;48.14370668978048;48.43825993770717;48.495229261930916;48.36508733085604;48.02462201317626;47.53850396910848;46.89102990740052;46.016831613096585;44.92375304290284;43.56351080009117;41.92204195611228;39.96199596378572;37.63919076941768;35.05530536201176;32.61203701781444;30.56541436137355;28.845430933487766;27.37208881829137;25.996611916755132;24.65729084277052;23.38739437277862;22.137022087802627;20.879814854326426;19.602063469247692;18.18186550000487;16.567816898314867;14.738317891495022;12.727998959540258;10.623177605896181;8.54560060332246;6.51966071209112;4.6657839884785455;3.036312907848326;1.6820459455679468;0.6921106974450838;0.12359578075040828;-0.09367329985645387;-0.031341689825133606;0.23717164699237966;0.6997800604297433;1.2979843274680154;2.0657283515050686;2.9615094560290176;3.9886574343032963;5.048029170775037;6.1827566231801345;7.400535839426023;8.609660807489144;9.866618625112752;11.165875582893802;12.525868733319928
2020-01-01 11:54:00;8.417737297758135;3.6003210616146095;31.338272439002946;48.77492727918919;53.06380857297471;45.30874684378469;31.254671851695033;17.53261532414694;10.779672643743828;15.838631955112836;28.191967140583625;40.66995055518302;49.08065786270199;51.48328009262055;48.50097581388598;42.28304833654381;34.61469193371904;26.922484942198942;20.893064894784953;18.239370031948738;19.89097470286485;25.358833593133255;33.52153932962637;43.290956605696884;53.11539213296727;60.809175752703325;64.76493825822062;64.8510953221729;62.17781191356055;57.88568438935276;52.50491331016351;46.49746676033152;40.60118285600951;35.23435495825925;30.368672337783654;25.950675240662438;22.146517887380686;19.346519036982766;17.793509426865167;17.5179082380076;18.344992365267892;20.03118327542923;22.273787745746976;24.764244860684187;27.346338145237937;29.90948002948232;32.416802867203714;34.832844886797844;37.09223417373295;39.17173190982804;41.12081715938511;42.85653714763779;44.410469153844005;45.754426847107766;46.82171758485793;47.614446627227814;48.14370668978048;48.43825993770717;48.495229261930916;48.36508733085604;48.02462201317626;47.53850396910848;46.89102990740052;46.016831613096585;44.92375304290284;43.56351080009117;41.92204195611228;39.96199596378572;37.63919076941768;35.05530536201176;32.61203701781444;30.56541436137355;28.845430933487766;27.37208881829137;25.996611916755132;24.65729084277052;23.38739437277862;22.137022087802627;20.879814854326426;19.602063469247692;18.18186550000487;16.567816898314867;14.738317891495022;12.727998959540258;10.623177605896181;8.54560060332246;6.51966071209112;4.6657839884785455;3.036312907848326;1.6820459455679468;0.6921106974450838;0.12359578075040828;-0.09367329985645387;-0.031341689825133606;0.23717164699237966;0.6997800604297433;1.2979843274680154;2.0657283515050686;2.9615094560290176;3.9886574343032963;5.048029170775037;6.1827566231801345;7.400535839426023;8.609660807489144;9.866618625112752;11.165875582893802;12.525868733319928
2020-01-01 11:55:00;8.417737297758135;3.6003210616146095;31.338272439002946;48.77492727918919;53.06380857297471;45.30874684378469;31.254671851695033;17.53261532414694;10.779672643743828;15.838631955112836;28.191967140583625;40.66995055518302;49.08065786270199;51.48328009262055;48.50097581388598;42.28304833654381;34.61469193371904;26.922484942198942;20.893064894784953;18.239370031948738;19.89097470286485;25.358833593133255;33.52153932962637;43.290956605696884;53.11539213296727;60.809175752703325;64.76493825822062;64.8510953221729;62.17781191356055;57.88568438935276;52.50491331016351;46.49746676033152;40.60118285600951;35.23435495825925;30.368672337783654;25.950675240662438;22.146517887380686;19.346519036982766;17.793509426865167;17.5179082380076;18.344992365267892;20.03118327542923;22.273787745746976;24.764244860684187;27.346338145237937;29.90948002948232;32.416802867203714;34.832844886797844;37.09223417373295;39.17173190982804;41.12081715938511;42.85653714763779;44.410469153844005;45.754426847107766;46.82171758485793;47.614446627227814;48.14370668978048;48.43825993770717;48.495229261930916;48.36508733085604;48.02462201317626;47.53850396910848;46.89102990740052;46.016831613096585;44.92375304290284;43.56351080009117;41.92204195611228;39.96199596378572;37.63919076941768;35.05530536201176;32.61203701781444;30.56541436137355;28.845430933487766;27.37208881829137;25.996611916755132;24.65729084277052;23.38739437277862;22.137022087802627;20.879814854326426;19.602063469247692;18.18186550000487;16.567816898314867;14.738317891495022;12.727998959540258;10.623177605896181;8.54560060332246;6.51966071209112;4.6657839884785455;3.036312907848326;1.6820459455679468;0.6921106974450838;0.12359578075040828;-0.09367329985645387;-0.031341689825133606;0.23717164699237966;0.6997800604297433;1.2979843274680154;2.0657283515050686;2.9615094560290176;3.9886574343032963;5.048029170775037;6.1827566231801345;7.400535839426023;8.609660807489144;9.866618625112752;11.165875582893802;12.525868733319928
2020-01-01 11:56:00;8.417737297758135;3.6003210616146095;31.338272439002946;48.77492727918919;53.06380857297471;45.30874684378469;31.254671851695033;17.53261532414694;10.779672643743828;15.838631955112836;28.191967140583625;40.66995055518302;49.08065786270199;51.48328009262055;48.50097581388598;42.28304833654381;34.61469193371904;26.922484942198942;20.893064894784953;18.239370031948738;19.89097470286485;25.358833593133255;33.52153932962637;43.290956605696884;53.11539213296727;60.809175752703325;64.76493825822062;64.8510953221729;62.17781191356055;57.88568438935276;52.50491331016351;46.49746676033152;40.60118285600951;35.23435495825925;30.368672337783654;25.950675240662438;22.146517887380686;19.346519036982766;17.793509426865167;17.5179082380076;18.344992365267892;20.03118327542923;22.273787745746976;24.764244860684187;27.346338145237937;29.90948002948232;32.416802867203714;34.832844886797844;37.09223417373295;39.17173190982804;41.12081715938511;42.85653714763779;44.410469153844005;45.754426847107766;46.82171758485793;47.614446627227814;48.14370668978048;48.43825993770717;48.495229261930916;48.36508733085604;48.02462201317626;47.53850396910848;46.89102990740052;46.016831613096585;44.92375304290284;43.56351080009117;41.92204195611228;39.96199596378572;37.63919076941768;35.05530536201176;32.61203701781444;30.56541436137355;28.845430933487766;27.37208881829137;25.996611916755132;24.65729084277052;23.38739437277862;22.137022087802627;20.879814854326426;19.602063469247692;18.18186550000487;16.567816898314867;14.738317891495022;12.727998959540258;10.623177605896181;8.54560060332246;6.51966071209112;4.6657839884785455;3.036312907848326;1.6820459455679468;0.6921106974450838;0.12359578075040828;-0.09367329985645387;-0.031341689825133606;0.23717164699237966;0.6997800604297433;1.2979843274680154;2.0657283515050686;2.9615094560290176;3.9886574343032963;5.048029170775037;6.1827566231801345;7.400535839426023;8.609660807489144;9.866618625112752;11.165875582893802;12.525868733319928
2020-01-01 12:08:00;8.417737297758135;3.6003210616146095;31.338272439002946;48.77492727918919;53.06380857297471;45.30874684378469;31.254671851695033;17.53261532414694;10.779672643743828;15.838631955112836;28.191967140583625;40.66995055518302;49.08065786270199;51.48328009262055;48.50097581388598;42.28304833654381;34.61469193371904;26.922484942198942;20.893064894784953;18.239370031948738;19.89097470286485;25.358833593133255;33.52153932962637;43.290956605696884;53.11539213296727;60.809175752703325;64.76493825822062;64.8510953221729;62.17781191356055;57.88568438935276;52.50491331016351;46.49746676033152;40.60118285600951;35.23435495825925;30.368672337783654;25.950675240662438;22.146517887380686;19.346519036982766;17.793509426865167;17.5179082380076;18.344992365267892;20.03118327542923;22.273787745746976;24.764244860684187;27.346338145237937;29.90948002948232;32.416802867203714;34.832844886797844;37.09223417373295;39.17173190982804;41.12081715938511;42.85653714763779;44.410469153844005;45.754426847107766;46.82171758485793;47.614446627227814;48.14370668978048;48.43825993770717;48.495229261930916;48.36508733085604;48.02462201317626;47.53850396910848;46.89102990740052;46.016831613096585;44.92375304290284;43.56351080009117;41.92204195611228;39.96199596378572;37.63919076941768;35.05530536201176;32.61203701781444;30.56541436137355;28.845430933487766;27.37208881829137;25.996611916755132;24.65729084277052;23.38739437277862;22.137022087802627;20.879814854326426;19.602063469247692;18.18186550000487;16.567816898314867;14.738317891495022;12.727998959540258;10.623177605896181;8.54560060332246;6.51966071209112;4.6657839884785455;3.036312907848326;1.6820459455679468;0.6921106974450838;0.12359578075040828;-0.09367329985645387;-0.031341689825133606;0.23717164699237966;0.6997800604297433;1.2979843274680154;2.0657283515050686;2.9615094560290176;3.9886574343032963;5.048029170775037;6.1827566231801345;7.400535839426023;8.609660807489144;9.866618625112752;11.165875582893802;12.525868733319928
2023-04-11 20:11:32;1.0;1.0;1.0;1.0;1.0;1.0;1.0;1.0;1.0;1.0;1.0;1.0;1.0;1.0;-10.763668055027939;8.305640072501342;31.637826554877694;48.03477977281296;51.94904038253991;43.92046873517888;30.282275085971904;18.515274810999323;13.658622670969802;18.370134441351663;29.40783794382829;41.17537487525726;49.33643700339432;51.67851518715106;48.73493019741106;42.65339654617092;35.260104682961405;28.008926326954338;22.451500039132164;19.917594700410206;21.015444700157946;25.489475650108464;32.756025413305224;42.06435812027997;51.81698014846449;59.61323203088072;63.688920586051836;63.86911181347037;61.27553173312963;57.07070900159253;51.8052855352636;45.96670425987968;40.314358632389755;35.271352518068596;30.806216342783753;26.857135218342812;23.55330174047621;21.186169723572256;19.916316730516474;19.729283211564656;20.467222928242798;21.934437171604444;23.8973322628643;26.100847575755644;28.417908858283532;30.753125068757775;33.0712381305316;35.32927088078379;37.459065942721274;39.429152460663026;41.285050198547665;42.940430138711655;44.42081263576579;45.694708189031104;46.69307016781613;47.41973251988903;47.88970073237569;48.13385899043243;48.14158818851574;47.96181848655466;47.57067698627792;47.02983018409779;46.327729045432555;45.394914823373846;44.236406623066;42.80513495789607;41.072946813848205;39.00008846084816;36.52804689988775;33.74993494537631;31.063365858214304;28.72079005511716;26.66138106482925;24.8053096479965;22.968829922528794;21.015715961676975;18.9376609840618;16.682009982738663;14.20249000364825;11.184361647225444;6.9382609934193535;1.5423016933942209;2.483037386309892;3.0775737211799967;3.043403263161106;2.3469762513268866;0.2497067928830013;-3.6112874940500985;-10.674480324842285;-3.1305892821692707;0.7576967304456016;3.46920512317714;5.705835911986699
2023-04-11 20:12:33;1.0;1.0;1.0;1.0;1.0;1.0;1.0;1.0;1.0;1.0;1.0;1.0;1.0;1.0;-10.763668055027939;8.305640072501342;31.637826554877694;48.03477977281296;51.94904038253991;43.92046873517888;30.282275085971904;18.515274810999323;13.658622670969802;18.370134441351663;29.40783794382829;41.17537487525726;49.33643700339432;51.67851518715106;48.73493019741106;42.65339654617092;35.260104682961405;28.008926326954338;22.451500039132164;19.917594700410206;21.015444700157946;25.489475650108464;32.756025413305224;42.06435812027997;51.81698014846449;59.61323203088072;63.688920586051836;63.86911181347037;61.27553173312963;57.07070900159253;51.8052855352636;45.96670425987968;40.314358632389755;35.271352518068596;30.806216342783753;26.857135218342812;23.55330174047621;21.186169723572256;19.916316730516474;19.729283211564656;20.467222928242798;21.934437171604444;23.8973322628643;26.100847575755644;28.417908858283532;30.753125068757775;33.0712381305316;35.32927088078379;37.459065942721274;39.429152460663026;41.285050198547665;42.940430138711655;44.42081263576579;45.694708189031104;46.69307016781613;47.41973251988903;47.88970073237569;48.13385899043243;48.14158818851574;47.96181848655466;47.57067698627792;47.02983018409779;46.327729045432555;45.394914823373846;44.236406623066;42.80513495789607;41.072946813848205;39.00008846084816;36.52804689988775;33.74993494537631;31.063365858214304;28.72079005511716;26.66138106482925;24.8053096479965;22.968829922528794;21.015715961676975;18.9376609840618;16.682009982738663;14.20249000364825;11.184361647225444;6.9382609934193535;1.5423016933942209;2.483037386309892;3.0775737211799967;3.043403263161106;2.3469762513268866;0.2497067928830013;-3.6112874940500985;-10.674480324842285;-3.1305892821692707;0.7576967304456016;3.46920512317714;5.705835911986699
1 B055 362.135 365.523 368.912 372.302 375.692 379.082 382.472 385.863 389.254 392.645 396.037 399.429 402.821 406.213 409.606 412.999 416.392 419.785 423.179 426.572 429.966 433.36 436.754 440.149 443.543 446.938 450.332 453.727 457.122 460.517 463.912 467.307 470.702 474.097 477.492 480.887 484.282 487.678 491.073 494.468 497.863 501.258 504.653 508.048 511.442 514.837 518.232 521.626 525.021 528.415 531.809 535.203 538.596 541.99 545.383 548.776 552.169 555.562 558.954 562.347 565.739 569.13 572.522 575.913 579.304 582.694 586.084 589.474 592.864 596.253 599.642 603.03 606.418 609.806 613.193 616.58 619.966 623.352 626.737 630.122 633.507 636.891 640.274 643.658 647.04 650.422 653.804 657.184 660.565 663.945 667.324 670.702 674.08 677.458 680.835 684.211 687.586 690.961 694.335 697.709 701.082 704.454 707.825 711.196 714.566 717.935 721.303
2 2023-04-11 20:07:27 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 -10.763668055027939 8.305640072501342 31.637826554877694 48.03477977281296 51.94904038253991 43.92046873517888 30.282275085971904 18.515274810999323 13.658622670969802 18.370134441351663 29.40783794382829 41.17537487525726 49.33643700339432 51.67851518715106 48.73493019741106 42.65339654617092 35.260104682961405 28.008926326954338 22.451500039132164 19.917594700410206 21.015444700157946 25.489475650108464 32.756025413305224 42.06435812027997 51.81698014846449 59.61323203088072 63.688920586051836 63.86911181347037 61.27553173312963 57.07070900159253 51.8052855352636 45.96670425987968 40.314358632389755 35.271352518068596 30.806216342783753 26.857135218342812 23.55330174047621 21.186169723572256 19.916316730516474 19.729283211564656 20.467222928242798 21.934437171604444 23.8973322628643 26.100847575755644 28.417908858283532 30.753125068757775 33.0712381305316 35.32927088078379 37.459065942721274 39.429152460663026 41.285050198547665 42.940430138711655 44.42081263576579 45.694708189031104 46.69307016781613 47.41973251988903 47.88970073237569 48.13385899043243 48.14158818851574 47.96181848655466 47.57067698627792 47.02983018409779 46.327729045432555 45.394914823373846 44.236406623066 42.80513495789607 41.072946813848205 39.00008846084816 36.52804689988775 33.74993494537631 31.063365858214304 28.72079005511716 26.66138106482925 24.8053096479965 22.968829922528794 21.015715961676975 18.9376609840618 16.682009982738663 14.20249000364825 11.184361647225444 6.9382609934193535 1.5423016933942209 2.483037386309892 3.0775737211799967 3.043403263161106 2.3469762513268866 0.2497067928830013 -3.6112874940500985 -10.674480324842285 -3.1305892821692707 0.7576967304456016 3.46920512317714 5.705835911986699
3 2020-01-01 11:51:00 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 8.415412981193239 3.5996009682587506 31.338329488965524 48.7749513729038 53.06382072824175 45.30875693934652 31.254677437114978 17.532611772316216 10.779726040523236 15.838614015715283 28.191866228270005 40.66985662655916 49.080572139996015 51.48319799151623 48.500883933779164 42.28292181009363 34.61451378177913 26.92226639410169 20.892862896209724 18.239209735086014 19.890747869186736 25.35852991591349 33.521274713508184 43.290769850459824 53.1152687544041 60.80908367848658 64.76485312234782 64.85099453829739 62.17766314472533 57.88546252994962 52.50454031350051 46.49689704670959 40.60044195055234 35.23342648168196 30.367620364654808 25.94954293423029 22.145442973056532 19.34566939986061 17.792867190973404 17.517315105555916 18.344250258868357 20.030198711674522 22.272635497046114 24.763130908702973 27.345401827467224 29.908644493688083 32.4160050563308 34.832033933363604 37.09136990438783 39.17081374925895 41.119807229076606 42.85536849200251 44.409104644778054 45.75285556671083 46.81989555171627 47.61231414995964 48.14106135144582 48.435164813011575 48.49199342321336 48.36182514653572 48.02130221181661 47.53514341402985 46.88757443079104 46.013271428886725 44.92010426348285 43.55986252876977 41.91835732244482 39.95833581445667 37.635655630271394 35.05192901881426 32.60924548135646 30.56311367000687 28.842867983650773 27.369001440848916 25.993083685487285 24.65362166462979 23.383867807324293 22.133808226335944 20.87703253197588 19.59976702684183 18.180525704012343 16.56799949335673 14.741236089072956 12.735637877309088 10.639157063826262 8.5763589883041 6.572572712242101 4.7513722915734835 3.173216882725356 1.9092118626120613 1.0498064519790538 0.6520100533130619 0.6256365637083021
4 2020-01-01 11:52:00 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 8.415412981193239 3.5996009682587506 31.338329488965524 48.7749513729038 53.06382072824175 45.30875693934652 31.254677437114978 17.532611772316216 10.779726040523236 15.838614015715283 28.191866228270005 40.66985662655916 49.080572139996015 51.48319799151623 48.500883933779164 42.28292181009363 34.61451378177913 26.92226639410169 20.892862896209724 18.239209735086014 19.890747869186736 25.35852991591349 33.521274713508184 43.290769850459824 53.1152687544041 60.80908367848658 64.76485312234782 64.85099453829739 62.17766314472533 57.88546252994962 52.50454031350051 46.49689704670959 40.60044195055234 35.23342648168196 30.367620364654808 25.94954293423029 22.145442973056532 19.34566939986061 17.792867190973404 17.517315105555916 18.344250258868357 20.030198711674522 22.272635497046114 24.763130908702973 27.345401827467224 29.908644493688083 32.4160050563308 34.832033933363604 37.09136990438783 39.17081374925895 41.119807229076606 42.85536849200251 44.409104644778054 45.75285556671083 46.81989555171627 47.61231414995964 48.14106135144582 48.435164813011575 48.49199342321336 48.36182514653572 48.02130221181661 47.53514341402985 46.88757443079104 46.013271428886725 44.92010426348285 43.55986252876977 41.91835732244482 39.95833581445667 37.635655630271394 35.05192901881426 32.60924548135646 30.56311367000687 28.842867983650773 27.369001440848916 25.993083685487285 24.65362166462979 23.383867807324293 22.133808226335944 20.87703253197588 19.59976702684183 18.180525704012343 16.56799949335673 14.741236089072956 12.735637877309088 10.639157063826262 8.5763589883041 6.572572712242101 4.7513722915734835 3.173216882725356 1.9092118626120613 1.0498064519790538 0.6520100533130619 0.6256365637083021
5 2020-01-01 11:53:00 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 8.415412981193239 3.5996009682587506 31.338329488965524 48.7749513729038 53.06382072824175 45.30875693934652 31.254677437114978 17.532611772316216 10.779726040523236 15.838614015715283 28.191866228270005 40.66985662655916 49.080572139996015 51.48319799151623 48.500883933779164 42.28292181009363 34.61451378177913 26.92226639410169 20.892862896209724 18.239209735086014 19.890747869186736 25.35852991591349 33.521274713508184 43.290769850459824 53.1152687544041 60.80908367848658 64.76485312234782 64.85099453829739 62.17766314472533 57.88546252994962 52.50454031350051 46.49689704670959 40.60044195055234 35.23342648168196 30.367620364654808 25.94954293423029 22.145442973056532 19.34566939986061 17.792867190973404 17.517315105555916 18.344250258868357 20.030198711674522 22.272635497046114 24.763130908702973 27.345401827467224 29.908644493688083 32.4160050563308 34.832033933363604 37.09136990438783 39.17081374925895 41.119807229076606 42.85536849200251 44.409104644778054 45.75285556671083 46.81989555171627 47.61231414995964 48.14106135144582 48.435164813011575 48.49199342321336 48.36182514653572 48.02130221181661 47.53514341402985 46.88757443079104 46.013271428886725 44.92010426348285 43.55986252876977 41.91835732244482 39.95833581445667 37.635655630271394 35.05192901881426 32.60924548135646 30.56311367000687 28.842867983650773 27.369001440848916 25.993083685487285 24.65362166462979 23.383867807324293 22.133808226335944 20.87703253197588 19.59976702684183 18.180525704012343 16.56799949335673 14.741236089072956 12.735637877309088 10.639157063826262 8.5763589883041 6.572572712242101 4.7513722915734835 3.173216882725356 1.9092118626120613 1.0498064519790538 0.6520100533130619 0.6256365637083021
6 2020-01-01 11:54:00 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 8.415412981193239 3.5996009682587506 31.338329488965524 48.7749513729038 53.06382072824175 45.30875693934652 31.254677437114978 17.532611772316216 10.779726040523236 15.838614015715283 28.191866228270005 40.66985662655916 49.080572139996015 51.48319799151623 48.500883933779164 42.28292181009363 34.61451378177913 26.92226639410169 20.892862896209724 18.239209735086014 19.890747869186736 25.35852991591349 33.521274713508184 43.290769850459824 53.1152687544041 60.80908367848658 64.76485312234782 64.85099453829739 62.17766314472533 57.88546252994962 52.50454031350051 46.49689704670959 40.60044195055234 35.23342648168196 30.367620364654808 25.94954293423029 22.145442973056532 19.34566939986061 17.792867190973404 17.517315105555916 18.344250258868357 20.030198711674522 22.272635497046114 24.763130908702973 27.345401827467224 29.908644493688083 32.4160050563308 34.832033933363604 37.09136990438783 39.17081374925895 41.119807229076606 42.85536849200251 44.409104644778054 45.75285556671083 46.81989555171627 47.61231414995964 48.14106135144582 48.435164813011575 48.49199342321336 48.36182514653572 48.02130221181661 47.53514341402985 46.88757443079104 46.013271428886725 44.92010426348285 43.55986252876977 41.91835732244482 39.95833581445667 37.635655630271394 35.05192901881426 32.60924548135646 30.56311367000687 28.842867983650773 27.369001440848916 25.993083685487285 24.65362166462979 23.383867807324293 22.133808226335944 20.87703253197588 19.59976702684183 18.180525704012343 16.56799949335673 14.741236089072956 12.735637877309088 10.639157063826262 8.5763589883041 6.572572712242101 4.7513722915734835 3.173216882725356 1.9092118626120613 1.0498064519790538 0.6520100533130619 0.6256365637083021
7 2020-01-01 11:55:00 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 8.415412981193239 3.5996009682587506 31.338329488965524 48.7749513729038 53.06382072824175 45.30875693934652 31.254677437114978 17.532611772316216 10.779726040523236 15.838614015715283 28.191866228270005 40.66985662655916 49.080572139996015 51.48319799151623 48.500883933779164 42.28292181009363 34.61451378177913 26.92226639410169 20.892862896209724 18.239209735086014 19.890747869186736 25.35852991591349 33.521274713508184 43.290769850459824 53.1152687544041 60.80908367848658 64.76485312234782 64.85099453829739 62.17766314472533 57.88546252994962 52.50454031350051 46.49689704670959 40.60044195055234 35.23342648168196 30.367620364654808 25.94954293423029 22.145442973056532 19.34566939986061 17.792867190973404 17.517315105555916 18.344250258868357 20.030198711674522 22.272635497046114 24.763130908702973 27.345401827467224 29.908644493688083 32.4160050563308 34.832033933363604 37.09136990438783 39.17081374925895 41.119807229076606 42.85536849200251 44.409104644778054 45.75285556671083 46.81989555171627 47.61231414995964 48.14106135144582 48.435164813011575 48.49199342321336 48.36182514653572 48.02130221181661 47.53514341402985 46.88757443079104 46.013271428886725 44.92010426348285 43.55986252876977 41.91835732244482 39.95833581445667 37.635655630271394 35.05192901881426 32.60924548135646 30.56311367000687 28.842867983650773 27.369001440848916 25.993083685487285 24.65362166462979 23.383867807324293 22.133808226335944 20.87703253197588 19.59976702684183 18.180525704012343 16.56799949335673 14.741236089072956 12.735637877309088 10.639157063826262 8.5763589883041 6.572572712242101 4.7513722915734835 3.173216882725356 1.9092118626120613 1.0498064519790538 0.6520100533130619 0.6256365637083021
8 2020-01-01 11:56:00 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 8.415412981193239 3.5996009682587506 31.338329488965524 48.7749513729038 53.06382072824175 45.30875693934652 31.254677437114978 17.532611772316216 10.779726040523236 15.838614015715283 28.191866228270005 40.66985662655916 49.080572139996015 51.48319799151623 48.500883933779164 42.28292181009363 34.61451378177913 26.92226639410169 20.892862896209724 18.239209735086014 19.890747869186736 25.35852991591349 33.521274713508184 43.290769850459824 53.1152687544041 60.80908367848658 64.76485312234782 64.85099453829739 62.17766314472533 57.88546252994962 52.50454031350051 46.49689704670959 40.60044195055234 35.23342648168196 30.367620364654808 25.94954293423029 22.145442973056532 19.34566939986061 17.792867190973404 17.517315105555916 18.344250258868357 20.030198711674522 22.272635497046114 24.763130908702973 27.345401827467224 29.908644493688083 32.4160050563308 34.832033933363604 37.09136990438783 39.17081374925895 41.119807229076606 42.85536849200251 44.409104644778054 45.75285556671083 46.81989555171627 47.61231414995964 48.14106135144582 48.435164813011575 48.49199342321336 48.36182514653572 48.02130221181661 47.53514341402985 46.88757443079104 46.013271428886725 44.92010426348285 43.55986252876977 41.91835732244482 39.95833581445667 37.635655630271394 35.05192901881426 32.60924548135646 30.56311367000687 28.842867983650773 27.369001440848916 25.993083685487285 24.65362166462979 23.383867807324293 22.133808226335944 20.87703253197588 19.59976702684183 18.180525704012343 16.56799949335673 14.741236089072956 12.735637877309088 10.639157063826262 8.5763589883041 6.572572712242101 4.7513722915734835 3.173216882725356 1.9092118626120613 1.0498064519790538 0.6520100533130619 0.6256365637083021
9 2020-01-01 12:08:00 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 8.415412981193239 3.5996009682587506 31.338329488965524 48.7749513729038 53.06382072824175 45.30875693934652 31.254677437114978 17.532611772316216 10.779726040523236 15.838614015715283 28.191866228270005 40.66985662655916 49.080572139996015 51.48319799151623 48.500883933779164 42.28292181009363 34.61451378177913 26.92226639410169 20.892862896209724 18.239209735086014 19.890747869186736 25.35852991591349 33.521274713508184 43.290769850459824 53.1152687544041 60.80908367848658 64.76485312234782 64.85099453829739 62.17766314472533 57.88546252994962 52.50454031350051 46.49689704670959 40.60044195055234 35.23342648168196 30.367620364654808 25.94954293423029 22.145442973056532 19.34566939986061 17.792867190973404 17.517315105555916 18.344250258868357 20.030198711674522 22.272635497046114 24.763130908702973 27.345401827467224 29.908644493688083 32.4160050563308 34.832033933363604 37.09136990438783 39.17081374925895 41.119807229076606 42.85536849200251 44.409104644778054 45.75285556671083 46.81989555171627 47.61231414995964 48.14106135144582 48.435164813011575 48.49199342321336 48.36182514653572 48.02130221181661 47.53514341402985 46.88757443079104 46.013271428886725 44.92010426348285 43.55986252876977 41.91835732244482 39.95833581445667 37.635655630271394 35.05192901881426 32.60924548135646 30.56311367000687 28.842867983650773 27.369001440848916 25.993083685487285 24.65362166462979 23.383867807324293 22.133808226335944 20.87703253197588 19.59976702684183 18.180525704012343 16.56799949335673 14.741236089072956 12.735637877309088 10.639157063826262 8.5763589883041 6.572572712242101 4.7513722915734835 3.173216882725356 1.9092118626120613 1.0498064519790538 0.6520100533130619 0.6256365637083021
10 2020-01-01 11:51:00 8.417737297758135 3.6003210616146095 31.338272439002946 48.77492727918919 53.06380857297471 45.30874684378469 31.254671851695033 17.53261532414694 10.779672643743828 15.838631955112836 28.191967140583625 40.66995055518302 49.08065786270199 51.48328009262055 48.50097581388598 42.28304833654381 34.61469193371904 26.922484942198942 20.893064894784953 18.239370031948738 19.89097470286485 25.358833593133255 33.52153932962637 43.290956605696884 53.11539213296727 60.809175752703325 64.76493825822062 64.8510953221729 62.17781191356055 57.88568438935276 52.50491331016351 46.49746676033152 40.60118285600951 35.23435495825925 30.368672337783654 25.950675240662438 22.146517887380686 19.346519036982766 17.793509426865167 17.5179082380076 18.344992365267892 20.03118327542923 22.273787745746976 24.764244860684187 27.346338145237937 29.90948002948232 32.416802867203714 34.832844886797844 37.09223417373295 39.17173190982804 41.12081715938511 42.85653714763779 44.410469153844005 45.754426847107766 46.82171758485793 47.614446627227814 48.14370668978048 48.43825993770717 48.495229261930916 48.36508733085604 48.02462201317626 47.53850396910848 46.89102990740052 46.016831613096585 44.92375304290284 43.56351080009117 41.92204195611228 39.96199596378572 37.63919076941768 35.05530536201176 32.61203701781444 30.56541436137355 28.845430933487766 27.37208881829137 25.996611916755132 24.65729084277052 23.38739437277862 22.137022087802627 20.879814854326426 19.602063469247692 18.18186550000487 16.567816898314867 14.738317891495022 12.727998959540258 10.623177605896181 8.54560060332246 6.51966071209112 4.6657839884785455 3.036312907848326 1.6820459455679468 0.6921106974450838 0.12359578075040828 -0.09367329985645387 -0.031341689825133606 0.23717164699237966 0.6997800604297433 1.2979843274680154 2.0657283515050686 2.9615094560290176 3.9886574343032963 5.048029170775037 6.1827566231801345 7.400535839426023 8.609660807489144 9.866618625112752 11.165875582893802 12.525868733319928
11 2020-01-01 11:52:00 8.417737297758135 3.6003210616146095 31.338272439002946 48.77492727918919 53.06380857297471 45.30874684378469 31.254671851695033 17.53261532414694 10.779672643743828 15.838631955112836 28.191967140583625 40.66995055518302 49.08065786270199 51.48328009262055 48.50097581388598 42.28304833654381 34.61469193371904 26.922484942198942 20.893064894784953 18.239370031948738 19.89097470286485 25.358833593133255 33.52153932962637 43.290956605696884 53.11539213296727 60.809175752703325 64.76493825822062 64.8510953221729 62.17781191356055 57.88568438935276 52.50491331016351 46.49746676033152 40.60118285600951 35.23435495825925 30.368672337783654 25.950675240662438 22.146517887380686 19.346519036982766 17.793509426865167 17.5179082380076 18.344992365267892 20.03118327542923 22.273787745746976 24.764244860684187 27.346338145237937 29.90948002948232 32.416802867203714 34.832844886797844 37.09223417373295 39.17173190982804 41.12081715938511 42.85653714763779 44.410469153844005 45.754426847107766 46.82171758485793 47.614446627227814 48.14370668978048 48.43825993770717 48.495229261930916 48.36508733085604 48.02462201317626 47.53850396910848 46.89102990740052 46.016831613096585 44.92375304290284 43.56351080009117 41.92204195611228 39.96199596378572 37.63919076941768 35.05530536201176 32.61203701781444 30.56541436137355 28.845430933487766 27.37208881829137 25.996611916755132 24.65729084277052 23.38739437277862 22.137022087802627 20.879814854326426 19.602063469247692 18.18186550000487 16.567816898314867 14.738317891495022 12.727998959540258 10.623177605896181 8.54560060332246 6.51966071209112 4.6657839884785455 3.036312907848326 1.6820459455679468 0.6921106974450838 0.12359578075040828 -0.09367329985645387 -0.031341689825133606 0.23717164699237966 0.6997800604297433 1.2979843274680154 2.0657283515050686 2.9615094560290176 3.9886574343032963 5.048029170775037 6.1827566231801345 7.400535839426023 8.609660807489144 9.866618625112752 11.165875582893802 12.525868733319928
12 2020-01-01 11:53:00 8.417737297758135 3.6003210616146095 31.338272439002946 48.77492727918919 53.06380857297471 45.30874684378469 31.254671851695033 17.53261532414694 10.779672643743828 15.838631955112836 28.191967140583625 40.66995055518302 49.08065786270199 51.48328009262055 48.50097581388598 42.28304833654381 34.61469193371904 26.922484942198942 20.893064894784953 18.239370031948738 19.89097470286485 25.358833593133255 33.52153932962637 43.290956605696884 53.11539213296727 60.809175752703325 64.76493825822062 64.8510953221729 62.17781191356055 57.88568438935276 52.50491331016351 46.49746676033152 40.60118285600951 35.23435495825925 30.368672337783654 25.950675240662438 22.146517887380686 19.346519036982766 17.793509426865167 17.5179082380076 18.344992365267892 20.03118327542923 22.273787745746976 24.764244860684187 27.346338145237937 29.90948002948232 32.416802867203714 34.832844886797844 37.09223417373295 39.17173190982804 41.12081715938511 42.85653714763779 44.410469153844005 45.754426847107766 46.82171758485793 47.614446627227814 48.14370668978048 48.43825993770717 48.495229261930916 48.36508733085604 48.02462201317626 47.53850396910848 46.89102990740052 46.016831613096585 44.92375304290284 43.56351080009117 41.92204195611228 39.96199596378572 37.63919076941768 35.05530536201176 32.61203701781444 30.56541436137355 28.845430933487766 27.37208881829137 25.996611916755132 24.65729084277052 23.38739437277862 22.137022087802627 20.879814854326426 19.602063469247692 18.18186550000487 16.567816898314867 14.738317891495022 12.727998959540258 10.623177605896181 8.54560060332246 6.51966071209112 4.6657839884785455 3.036312907848326 1.6820459455679468 0.6921106974450838 0.12359578075040828 -0.09367329985645387 -0.031341689825133606 0.23717164699237966 0.6997800604297433 1.2979843274680154 2.0657283515050686 2.9615094560290176 3.9886574343032963 5.048029170775037 6.1827566231801345 7.400535839426023 8.609660807489144 9.866618625112752 11.165875582893802 12.525868733319928
13 2020-01-01 11:54:00 8.417737297758135 3.6003210616146095 31.338272439002946 48.77492727918919 53.06380857297471 45.30874684378469 31.254671851695033 17.53261532414694 10.779672643743828 15.838631955112836 28.191967140583625 40.66995055518302 49.08065786270199 51.48328009262055 48.50097581388598 42.28304833654381 34.61469193371904 26.922484942198942 20.893064894784953 18.239370031948738 19.89097470286485 25.358833593133255 33.52153932962637 43.290956605696884 53.11539213296727 60.809175752703325 64.76493825822062 64.8510953221729 62.17781191356055 57.88568438935276 52.50491331016351 46.49746676033152 40.60118285600951 35.23435495825925 30.368672337783654 25.950675240662438 22.146517887380686 19.346519036982766 17.793509426865167 17.5179082380076 18.344992365267892 20.03118327542923 22.273787745746976 24.764244860684187 27.346338145237937 29.90948002948232 32.416802867203714 34.832844886797844 37.09223417373295 39.17173190982804 41.12081715938511 42.85653714763779 44.410469153844005 45.754426847107766 46.82171758485793 47.614446627227814 48.14370668978048 48.43825993770717 48.495229261930916 48.36508733085604 48.02462201317626 47.53850396910848 46.89102990740052 46.016831613096585 44.92375304290284 43.56351080009117 41.92204195611228 39.96199596378572 37.63919076941768 35.05530536201176 32.61203701781444 30.56541436137355 28.845430933487766 27.37208881829137 25.996611916755132 24.65729084277052 23.38739437277862 22.137022087802627 20.879814854326426 19.602063469247692 18.18186550000487 16.567816898314867 14.738317891495022 12.727998959540258 10.623177605896181 8.54560060332246 6.51966071209112 4.6657839884785455 3.036312907848326 1.6820459455679468 0.6921106974450838 0.12359578075040828 -0.09367329985645387 -0.031341689825133606 0.23717164699237966 0.6997800604297433 1.2979843274680154 2.0657283515050686 2.9615094560290176 3.9886574343032963 5.048029170775037 6.1827566231801345 7.400535839426023 8.609660807489144 9.866618625112752 11.165875582893802 12.525868733319928
14 2020-01-01 11:55:00 8.417737297758135 3.6003210616146095 31.338272439002946 48.77492727918919 53.06380857297471 45.30874684378469 31.254671851695033 17.53261532414694 10.779672643743828 15.838631955112836 28.191967140583625 40.66995055518302 49.08065786270199 51.48328009262055 48.50097581388598 42.28304833654381 34.61469193371904 26.922484942198942 20.893064894784953 18.239370031948738 19.89097470286485 25.358833593133255 33.52153932962637 43.290956605696884 53.11539213296727 60.809175752703325 64.76493825822062 64.8510953221729 62.17781191356055 57.88568438935276 52.50491331016351 46.49746676033152 40.60118285600951 35.23435495825925 30.368672337783654 25.950675240662438 22.146517887380686 19.346519036982766 17.793509426865167 17.5179082380076 18.344992365267892 20.03118327542923 22.273787745746976 24.764244860684187 27.346338145237937 29.90948002948232 32.416802867203714 34.832844886797844 37.09223417373295 39.17173190982804 41.12081715938511 42.85653714763779 44.410469153844005 45.754426847107766 46.82171758485793 47.614446627227814 48.14370668978048 48.43825993770717 48.495229261930916 48.36508733085604 48.02462201317626 47.53850396910848 46.89102990740052 46.016831613096585 44.92375304290284 43.56351080009117 41.92204195611228 39.96199596378572 37.63919076941768 35.05530536201176 32.61203701781444 30.56541436137355 28.845430933487766 27.37208881829137 25.996611916755132 24.65729084277052 23.38739437277862 22.137022087802627 20.879814854326426 19.602063469247692 18.18186550000487 16.567816898314867 14.738317891495022 12.727998959540258 10.623177605896181 8.54560060332246 6.51966071209112 4.6657839884785455 3.036312907848326 1.6820459455679468 0.6921106974450838 0.12359578075040828 -0.09367329985645387 -0.031341689825133606 0.23717164699237966 0.6997800604297433 1.2979843274680154 2.0657283515050686 2.9615094560290176 3.9886574343032963 5.048029170775037 6.1827566231801345 7.400535839426023 8.609660807489144 9.866618625112752 11.165875582893802 12.525868733319928
15 2020-01-01 11:56:00 8.417737297758135 3.6003210616146095 31.338272439002946 48.77492727918919 53.06380857297471 45.30874684378469 31.254671851695033 17.53261532414694 10.779672643743828 15.838631955112836 28.191967140583625 40.66995055518302 49.08065786270199 51.48328009262055 48.50097581388598 42.28304833654381 34.61469193371904 26.922484942198942 20.893064894784953 18.239370031948738 19.89097470286485 25.358833593133255 33.52153932962637 43.290956605696884 53.11539213296727 60.809175752703325 64.76493825822062 64.8510953221729 62.17781191356055 57.88568438935276 52.50491331016351 46.49746676033152 40.60118285600951 35.23435495825925 30.368672337783654 25.950675240662438 22.146517887380686 19.346519036982766 17.793509426865167 17.5179082380076 18.344992365267892 20.03118327542923 22.273787745746976 24.764244860684187 27.346338145237937 29.90948002948232 32.416802867203714 34.832844886797844 37.09223417373295 39.17173190982804 41.12081715938511 42.85653714763779 44.410469153844005 45.754426847107766 46.82171758485793 47.614446627227814 48.14370668978048 48.43825993770717 48.495229261930916 48.36508733085604 48.02462201317626 47.53850396910848 46.89102990740052 46.016831613096585 44.92375304290284 43.56351080009117 41.92204195611228 39.96199596378572 37.63919076941768 35.05530536201176 32.61203701781444 30.56541436137355 28.845430933487766 27.37208881829137 25.996611916755132 24.65729084277052 23.38739437277862 22.137022087802627 20.879814854326426 19.602063469247692 18.18186550000487 16.567816898314867 14.738317891495022 12.727998959540258 10.623177605896181 8.54560060332246 6.51966071209112 4.6657839884785455 3.036312907848326 1.6820459455679468 0.6921106974450838 0.12359578075040828 -0.09367329985645387 -0.031341689825133606 0.23717164699237966 0.6997800604297433 1.2979843274680154 2.0657283515050686 2.9615094560290176 3.9886574343032963 5.048029170775037 6.1827566231801345 7.400535839426023 8.609660807489144 9.866618625112752 11.165875582893802 12.525868733319928
16 2020-01-01 12:08:00 8.417737297758135 3.6003210616146095 31.338272439002946 48.77492727918919 53.06380857297471 45.30874684378469 31.254671851695033 17.53261532414694 10.779672643743828 15.838631955112836 28.191967140583625 40.66995055518302 49.08065786270199 51.48328009262055 48.50097581388598 42.28304833654381 34.61469193371904 26.922484942198942 20.893064894784953 18.239370031948738 19.89097470286485 25.358833593133255 33.52153932962637 43.290956605696884 53.11539213296727 60.809175752703325 64.76493825822062 64.8510953221729 62.17781191356055 57.88568438935276 52.50491331016351 46.49746676033152 40.60118285600951 35.23435495825925 30.368672337783654 25.950675240662438 22.146517887380686 19.346519036982766 17.793509426865167 17.5179082380076 18.344992365267892 20.03118327542923 22.273787745746976 24.764244860684187 27.346338145237937 29.90948002948232 32.416802867203714 34.832844886797844 37.09223417373295 39.17173190982804 41.12081715938511 42.85653714763779 44.410469153844005 45.754426847107766 46.82171758485793 47.614446627227814 48.14370668978048 48.43825993770717 48.495229261930916 48.36508733085604 48.02462201317626 47.53850396910848 46.89102990740052 46.016831613096585 44.92375304290284 43.56351080009117 41.92204195611228 39.96199596378572 37.63919076941768 35.05530536201176 32.61203701781444 30.56541436137355 28.845430933487766 27.37208881829137 25.996611916755132 24.65729084277052 23.38739437277862 22.137022087802627 20.879814854326426 19.602063469247692 18.18186550000487 16.567816898314867 14.738317891495022 12.727998959540258 10.623177605896181 8.54560060332246 6.51966071209112 4.6657839884785455 3.036312907848326 1.6820459455679468 0.6921106974450838 0.12359578075040828 -0.09367329985645387 -0.031341689825133606 0.23717164699237966 0.6997800604297433 1.2979843274680154 2.0657283515050686 2.9615094560290176 3.9886574343032963 5.048029170775037 6.1827566231801345 7.400535839426023 8.609660807489144 9.866618625112752 11.165875582893802 12.525868733319928
17 2023-04-11 20:11:32 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 -10.763668055027939 8.305640072501342 31.637826554877694 48.03477977281296 51.94904038253991 43.92046873517888 30.282275085971904 18.515274810999323 13.658622670969802 18.370134441351663 29.40783794382829 41.17537487525726 49.33643700339432 51.67851518715106 48.73493019741106 42.65339654617092 35.260104682961405 28.008926326954338 22.451500039132164 19.917594700410206 21.015444700157946 25.489475650108464 32.756025413305224 42.06435812027997 51.81698014846449 59.61323203088072 63.688920586051836 63.86911181347037 61.27553173312963 57.07070900159253 51.8052855352636 45.96670425987968 40.314358632389755 35.271352518068596 30.806216342783753 26.857135218342812 23.55330174047621 21.186169723572256 19.916316730516474 19.729283211564656 20.467222928242798 21.934437171604444 23.8973322628643 26.100847575755644 28.417908858283532 30.753125068757775 33.0712381305316 35.32927088078379 37.459065942721274 39.429152460663026 41.285050198547665 42.940430138711655 44.42081263576579 45.694708189031104 46.69307016781613 47.41973251988903 47.88970073237569 48.13385899043243 48.14158818851574 47.96181848655466 47.57067698627792 47.02983018409779 46.327729045432555 45.394914823373846 44.236406623066 42.80513495789607 41.072946813848205 39.00008846084816 36.52804689988775 33.74993494537631 31.063365858214304 28.72079005511716 26.66138106482925 24.8053096479965 22.968829922528794 21.015715961676975 18.9376609840618 16.682009982738663 14.20249000364825 11.184361647225444 6.9382609934193535 1.5423016933942209 2.483037386309892 3.0775737211799967 3.043403263161106 2.3469762513268866 0.2497067928830013 -3.6112874940500985 -10.674480324842285 -3.1305892821692707 0.7576967304456016 3.46920512317714 5.705835911986699
18 2023-04-11 20:12:33 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 -10.763668055027939 8.305640072501342 31.637826554877694 48.03477977281296 51.94904038253991 43.92046873517888 30.282275085971904 18.515274810999323 13.658622670969802 18.370134441351663 29.40783794382829 41.17537487525726 49.33643700339432 51.67851518715106 48.73493019741106 42.65339654617092 35.260104682961405 28.008926326954338 22.451500039132164 19.917594700410206 21.015444700157946 25.489475650108464 32.756025413305224 42.06435812027997 51.81698014846449 59.61323203088072 63.688920586051836 63.86911181347037 61.27553173312963 57.07070900159253 51.8052855352636 45.96670425987968 40.314358632389755 35.271352518068596 30.806216342783753 26.857135218342812 23.55330174047621 21.186169723572256 19.916316730516474 19.729283211564656 20.467222928242798 21.934437171604444 23.8973322628643 26.100847575755644 28.417908858283532 30.753125068757775 33.0712381305316 35.32927088078379 37.459065942721274 39.429152460663026 41.285050198547665 42.940430138711655 44.42081263576579 45.694708189031104 46.69307016781613 47.41973251988903 47.88970073237569 48.13385899043243 48.14158818851574 47.96181848655466 47.57067698627792 47.02983018409779 46.327729045432555 45.394914823373846 44.236406623066 42.80513495789607 41.072946813848205 39.00008846084816 36.52804689988775 33.74993494537631 31.063365858214304 28.72079005511716 26.66138106482925 24.8053096479965 22.968829922528794 21.015715961676975 18.9376609840618 16.682009982738663 14.20249000364825 11.184361647225444 6.9382609934193535 1.5423016933942209 2.483037386309892 3.0775737211799967 3.043403263161106 2.3469762513268866 0.2497067928830013 -3.6112874940500985 -10.674480324842285 -3.1305892821692707 0.7576967304456016 3.46920512317714 5.705835911986699

@ -0,0 +1,466 @@
# 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
# def makeMsg(self,key,value):
# """
# 事件对象:制造事件
# 将事件写入event 并send
# """
# # event = eventManager.Event( type_ = eventManager.EVENT_MSG)
# event.dict[key] = value
# # 发送事件
# self.__eventManager.SendEvent(event)
if __name__ == "__main__":
d = DataPlot()
# def plot_demo( self, time_, data ,wavelength):
# '''
# @ 根据数据画demo曲线
# '''
# x = np.array( wavelength ).astype(np.float)
# datetime_ = str(time_ )
# y = np.array(data).astype(np.float)
# self.mypanel.axes.clear() # 清空上次画的内容
# self.mypanel.axes.set_title( self.axes_title )
# self.mypanel.axes.set_xlabel( self.axes_xlabel )
# self.mypanel.axes.set_ylabel( self.axes_ylabel )
# self.mypanel.axes.plot(x, y, color="green", linewidth=0.5 , label=datetime_ )
# self.mypanel.axes.legend()
# self.mypanel.axes.grid(True)
# self.mypanel.FigureCanvas.draw()
# def plot_one( self, time_, data ,wavelength):
# '''
# @ 根据数据画一条曲线
# @ 参数 data
# '''
# x = np.array( wavelength ).astype(np.float)
# datetime_ = str(time_ )
# y = np.array(data).astype(np.float)
# self.mypanel.axes.clear() # 清空上次画的内容
# self.mypanel.axes.set_title( self.axes_title )
# self.mypanel.axes.set_xlabel( self.axes_xlabel )
# self.mypanel.axes.set_ylabel( self.axes_ylabel )
# self.mypanel.axes.plot(x, y, color="green", linewidth=0.5 , label=datetime_ )
# self.mypanel.axes.legend()
# self.mypanel.axes.grid(True)
# self.mypanel.FigureCanvas.draw()
# def plotOne( self, data ):
# '''
# @ 根据数据画一条曲线
# @ 参数 data
# '''
# x = np.array( self.wavelength ).astype(np.float)
# datetime_ = data[0]
# y = np.array(data[1:]).astype(np.float)
# self.mypanel.axes.clear() # 清空上次画的内容
# self.mypanel.axes.set_title( self.axes_title )
# self.mypanel.axes.set_xlabel( self.axes_xlabel )
# self.mypanel.axes.set_ylabel( self.axes_ylabel )
# self.mypanel.axes.plot(x, y, color="green", linewidth=0.5 , label=datetime_ )
# self.mypanel.axes.legend()
# self.mypanel.axes.grid(True)
# self.mypanel.FigureCanvas.draw()
# def OnPlot(self, wl, fpath ):
# """
# * 查看历史曲线
# * 默认从最后一条记录读取
# """
# temp = self.__get_last_line( fpath ).decode().split(TOKEN)
# time_ = temp[0]
# data = temp[1:]
# # 加判断波长
# print(fpath)
# if len(data) > len( wl ):
# for i in range( len(data)-len(wl) ):
# data.pop()
# self.plot_one( time_ , data, wl )
# def plotSeven(self,wavelength,d):
# '''
# * 根据数据画七条曲线
# * 兼容数量不够七条的
# '''
# # myDebug.MyDebug.log_info( ":::::::::::: Class : %s -> Function : get_file_list " % ( __name__, ) )
# # myDebug.MyDebug.log_ctl( " d len : %s " % ( len(d), ) )
# # myDebug.MyDebug.log_ctl( " d : %s " % ( d, ) )
# x = np.array( wavelength ).astype(np.float)
# self.mypanel.axes.clear() # 清空上次画的内容
# self.mypanel.axes.set_title( self.axes_title )
# self.mypanel.axes.set_xlabel( self.axes_xlabel )
# self.mypanel.axes.set_ylabel( self.axes_ylabel )
# # 处理 data
# length = len(d)
# data = []
# for s in d:
# ss = s.split(TOKEN)
# ss0 = ss[0]
# ss1 = ss[1:]
# # 去掉尾部多余
# if len(ss1) > len( wavelength ):
# for i in range( len(ss1)-len(wavelength) ):
# ss1.pop()
# data.append( [ss0, ss1] )
# print( " data : %s " % ( len(data) , ) )
# if length >=1 :
# print( " data[0][0] %s " % (data[0][0],))
# d0 = data[0][0]
# y0 =np.array(data[0][1]).astype(np.float)
# self.mypanel.axes.plot(x, y0, 'r', linewidth=0.5 , label = d0 )
# # len(data) =2
# if len(data) >=2 :
# d1 = data[1][0]
# y1 =np.array(data[1][1]).astype(np.float)
# self.mypanel.axes.plot(x, y1, color='orange', linewidth=0.5 , label=d1 )
# # len(data) =3
# if len(data) >=3 :
# d2 = data[2][0]
# y2 =np.array(data[2][1]).astype(np.float)
# self.mypanel.axes.plot(x, y2, 'y', linewidth=0.5 , label=d2 )
# # len(data) =4
# if len(data) >=4 :
# d3 = data[3][0]
# y3 =np.array(data[3][1]).astype(np.float)
# self.mypanel.axes.plot(x, y3, 'g', linewidth=0.5 , label=d3 )
# # len(data) =5
# if len(data) >=5 :
# d4 = data[4][0]
# y4 =np.array(data[4][1]).astype(np.float)
# self.mypanel.axes.plot(x, y4, 'c', linewidth=0.5 , label=d4 )
# # len(data) =6
# if len(data) >=6 :
# d5 = data[5][0]
# y5 =np.array(data[5][1]).astype(np.float)
# self.mypanel.axes.plot(x, y5, 'b', linewidth=0.5 , label=d5 )
# # len(data) =7
# if len(data) >=7 :
# d6 = data[6][0]
# y6 =np.array(data[6][1]).astype(np.float)
# self.mypanel.axes.plot(x, y6, color='purple', linewidth=0.5 , label=d6 )
# self.mypanel.axes.legend()
# self.mypanel.axes.grid( True )
# self.mypanel.FigureCanvas.draw()
# def OnPlot_7(self, wl, fpath):
# """
# 最后间隔七条
# 默认间隔数为1
# """
# result_line = []
# count = 0
# thefile = open( fpath, 'rb')
# while True:
# buffer = thefile.read(8192*1024)
# if not buffer:
# break
# count += buffer.count(b'\n')
# count = count + 1
# self.makeMsg(1, u" 文件共有 " + str(count) + " 行" )
# # self.statusBar.SetStatusText(u" 文件共有 "+str(count)+" 行",0)
# # 判断文件是否已有数据
# if count == 0:
# #print('文件没有内容!')
# self.makeMsg(2, u"数据文件没有记录!" )
# # with wx.MessageDialog(self, u"数据文件没有记录!", u"错误提示", wx.OK )as dlg:
# # dlg.ShowModal()
# elif count < 8:
# for i in range(count-1):
# result_line.append(linecache.getline( fpath, count-i).strip("\n"))
# else:
# for i in range(7):
# result_line.append(linecache.getline( fpath, count-i).strip("\n"))
# # 画7天的图像
# thefile.close()
# self.plotSeven( wl,result_line )
# def OnPlot_D(self, wl,fpath, interval, begin):
# """
# 指定位置间隔七条
# 考虑数据是否够
# """
# # print( "i am plot d")
# # self.readConfig()
# result_line = []
# count = 0
# thefile = open( fpath, 'rb')
# while True:
# buffer = thefile.read(8192*1024)
# if not buffer:
# break
# count += buffer.count(b'\n')
# count = count + 1
# self.makeMsg(1, u" 文件共有 "+str(count)+" 行" )
# # 判断文件绘图参数设置是否正确
# if count == 0:
# #print('文件没有内容!')
# self.makeMsg(2, u"数据文件没有记录!" )
# # with wx.MessageDialog(self, u"数据文件没有记录!", u"错误提示", wx.OK )as dlg:
# # dlg.ShowModal()
# elif ( interval*7 + begin ) < (count-1):
# for i in range(7):
# result_line.append( linecache.getline( fpath,count-begin-i*interval ).strip("\n") )
# else:
# for i in range( ( (count-1)-begin )//interval ):
# result_line.append(linecache.getline( fpath,count-begin-i*interval ).strip("\n") )
# # 画7天的图像
# thefile.close()
# self.plotSeven( wl, result_line )

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

@ -0,0 +1,32 @@
from myconfig import TOKEN
import wx
class Listctrl(wx.Panel):
'''
# 需要在 Frame 实例化一个实例
# 改变需要对实例化后的进行操作
'''
def __init__(self, parent ):
'''
* panel 初始化后的样子
'''
# self.para_setting = para
super(Listctrl,self).__init__(parent)
self.locale = wx.Locale(wx.LANGUAGE_CHINESE_SIMPLIFIED)
self.SetBackgroundColour('lightgrey')
self.box = wx.BoxSizer(wx.HORIZONTAL)
self.list_ctrl = wx.ListCtrl(self, -1, style = wx.LC_REPORT | wx.LC_SORT_DESCENDING)
self.list_ctrl.SetBackgroundColour( 'lightgrey' )
self.list_ctrl.InsertColumn(0, u'测量时间', width = 180)
self.list_ctrl.InsertColumn(1, u'花粉_Pollen', width = 180)
i = 1
self.list_ctrl.SetFont( wx.Font( 11, wx.FONTFAMILY_SWISS, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, False ) )
self.box.Add(self.list_ctrl,1,wx.EXPAND)
self.SetSizer(self.box)
self.Fit()

@ -0,0 +1,188 @@
#! python3
# -*- encoding: utf-8 -*-
'''
@File : myconfig.py
@Time : 2023/03/01 15:28:20
@Author : Jim @ Yiwin
@Version : 1.0
@Contact : jim@yi-win.com
@Descrip : SysConfig
'''
import yaml
from enum import Enum
from pathlib import Path
VERSION = "3.5.0"
LASTDATE = "2023-03-7"
COMPANY = u"奕枫仪器"
CURRENT_DIR = Path()
DATA_DIR = "data"
CAL_DIR = "calfile"
OUTPUT_DIR = "output"
YAML_FILE_NAME = "config.yml"
RETRIEVE_CFG_FILE = "retrieve.yml"
PURE_WATER_FNAME = "abs_pure_water.DAT"
FILE_MARK = ['Spectrum', 'DATA']
SAVE_EXT_NAME = ".csv"
INTERVAL = 1.0
SEPARATOR = ";"
TOKEN = ";"
NEWLINE = "\n"
OSCAR_R = 0.04
OSCAR_R0 = 0.035
class DeviceType(Enum) :
VIPER = 1
OSCAR = 2
SC6 = 3
DEVICE = {
"UISN" : "B055"
}
# 一次最多 256个字节,步长<128, 字节数<256,浮点数最多63个
# viper 2100 2462 352/2 = 171, 一次60个
# oscar 2100 2329 230/2 = 116 一次60个
REGISTER = {
"slaveaddress" : 1,
"functioncode" : 3,
"SNAddress" : 10, # 测试使用2980
"SNLen" : 5,
"WLBeginAddress" : 2102, # 2100+2
"DataBeginAddress" : 2614, # 2612+2
"count" : 3 #oscar 2 viper 3
}
COMSETTING = {
"port" : "COM1" ,
"baudrate" : 9600,
'bytesize' : 8,
'parity' : "N",
'stopbit' : 1
}
PLOTSETTING = {
"LineInterval" : 1 ,
"LineBegin" : 0
}
LOGSETTING= {
"LogInterval" : 1,
"RefreshInterval" : 0
}
ALGORITHM = {
"A720" : 0, # 0: 720 11项平均值法, 1: 720 附近两个点插值 2: 720 为0
"PureWater" : 0, # 0 :包含纯水系数 1: 不包含纯水系数
"PureWater2" : 0
}
RETRIEVE = {
# "Enable" : 1,
"BeginWL" : 360,
"EndWL" : 721,
"Interval" : 1
}
FILEPATH = {
"path" : ''
}
class MyConfig(object):
"""
如上预定义数据
先写一个yaml 文件出来修改后读文件数据就可以
"""
def __init__(self) -> None:
self.device_sn = ""
self.system_cfg = {}
self.cfg_path = Path()
self.yml_cfg_file = self.cfg_path.joinpath(YAML_FILE_NAME)
self.retrieve_cfg_file = Path(RETRIEVE_CFG_FILE)
self.getSystemCfg() # 默认的值
def getSystemCfg(self,)->None:
'''
获得默认的值
'''
self.system_cfg = {}
self.system_cfg.update( {"device":DEVICE} )
self.system_cfg.update( {"register":REGISTER} )
self.system_cfg.update( {"plotsetting":PLOTSETTING} )
self.system_cfg.update( {"logsetting":LOGSETTING} )
self.system_cfg.update( {"comsetting":COMSETTING} )
self.system_cfg.update( {"algorithm":ALGORITHM} )
self.system_cfg.update( {"filepath":FILEPATH} )
pass
def getDictByAttr(self, *args) -> dict:
ret = {}
if len(args) == 0:
return ret
if len(args) == 1:
if not hasattr( self, args[0] ):
return ret
tmp = getattr( self, args[0] )
if isinstance( tmp, dict ):
ret.update(tmp)
return ret
if len(args) == 2:
if not hasattr(self, args[0]):
return ret
if not isinstance(getattr(self, args[0]), dict):
return ret
tmp: dict = getattr(self, args[0])
if not tmp.__contains__(args[1]):
return ret
tmp2 = tmp[args[1]]
if isinstance(tmp2, dict):
ret.update(tmp2)
return ret
if len(args) > 2:
return ret
pass
# 设置字典对应的键值
def set_attr(self, d: dict, k, v) -> bool:
if d.__contains__(k):
d.update({k: v})
return True
return False
def write_yaml(self, d: dict):
with open(self.yml_cfg_file, "w", encoding = "utf-8") as f:
yaml.dump(d, f)
def read_yaml(self ) -> dict:
# self.write_yaml(self.system_cfg)
with open(self.yml_cfg_file, "r", encoding="utf-8") as f:
content = f.read() # conent 读出来是字符串
d = yaml.load(content, Loader=yaml.FullLoader) # 用load方法转字典
return d
def write_rtv_yaml(self, d: dict):
with open(self.retrieve_cfg_file, "w", encoding="utf-8") as f:
yaml.dump(d, f)
def read_rtv_yaml(self ) -> dict:
with open(self.retrieve_cfg_file, "r", encoding="utf-8") as f:
content = f.read() # conent 读出来是字符串
d = yaml.load(content, Loader=yaml.FullLoader) # 用load方法转字典
return d
def set_retrieve(self) -> dict:
retrieve = {}
# retrieve.update({"enable": RETRIEVE["Enable"]})
retrieve.update({"beginWL": RETRIEVE["BeginWL"]})
retrieve.update({"endWL": RETRIEVE["EndWL"]})
retrieve.update({"interval": RETRIEVE["Interval"]})
self.write_rtv_yaml(retrieve)
return retrieve
pass
if __name__ == "__main__":
pass

@ -0,0 +1,14 @@
class TCPIPException(Exception):
def __init__(self, message="TCPIP 自定义异常"):
self.message = "TCPIP exception : " + message
class SerialException(Exception):
def __init__(self, message="Serial 自定义异常"):
self.message = "serial exception : " + message
class MyException(Exception):
def __init__(self, message=" 自定义异常"):
self.message = "自定义异常: " + message

@ -0,0 +1,285 @@
# coding=utf-8
'''
单例模式日志 -- 使用一次关闭 handler
这种方法优缺点
缺点 输出的format 需要自己定义 并过滤
过滤要看是否以什么开头或包含什么
优点 不占用文件资源占用系统资源小
调用 log.info( ) log.error()
'''
import logging
import logging.handlers
import os
import time
import threading
# from config import LOG_PATH,LOG_LEVEL,LOG_ENABLED,LOG_FORMAT, \
# LOG_TO_CONSOLE,LOG_TO_FILE
MY_LOGGER_NAME = "DefaultLogger"
LOG_ENABLED = True # 是否启用日志
LOG_TO_CONSOLE = True # 是否启用控制台输出日志
LOG_TO_FILE = False # 是否启用文件输出
LOG_COLOR_ENABLE = True # 是否启用颜色日志
LOGGER_DIR = "logs"
LOGGER_PATH = os.path.join( os.path.dirname(__file__), LOGGER_DIR )
LOGGER_FILENAME = os.path.join( LOGGER_PATH, 'logs.log' )
"""
logging.INFO , logging.DEBUG , logging.WARNING , logging.ERROR ,
"""
LOG_LEVEL = logging.INFO # 日志等级DEBUG INFO WARNIG ERROR
# LOG_LEVEL = logging.DEBUG
# LOG_LEVEL = logging.WARNING
"""
# LOG_FORMAT = " %(name)s - %(module)s - %(filename)s - %(lineno)d | %(levelname)s : %(message)s"
# LOG_FORMAT = "%(levelname)s - %(asctime)s - process: %(process)d - threadname: %(thread)s " \
# "- %(filename)s - %(funcName)s - %(lineno)d - %(module)s " \
# "- %(message)s "
# LOG_FORMAT = "%(asctime)s - %(thread)s " \
# "- %(levelname)s ::: %(message)s "
# '[%(asctime)s] |%(thread)s| %(levelname)-6s: %(message)s'
# fm = '%(levelname):%(levelno)s:%(name)s:%(funcName)s:%(asctime):%(pathname):%(filename):%(module):%(thread):%(threadName)'
# 此处日志颜色,修改日志颜色是通过 Filter实现的
"""
LOG_FORMAT = '%(levelname)s\t[%(asctime)s] %(package)s:%(classname)s:%(funcname)s \t>> %(message)s'
"""
# 此处日志颜色,修改日志颜色是通过 Filter实现的
"""
LOG_FORMAT_COLOR_DICT = {
'ERROR' : "\033[31mERROR\033[0m",
'INFO' : "\033[36mINFO\033[0m",
'DEBUG' : "\033[1mDEBUG\033[0m",
'WARN' : "\033[33mWARN\033[0m",
'WARNING' : "\033[33mWARNING\033[0m",
'CRITICAL': "\033[35mCRITICAL\033[0m",
}
"""
# Filter 用法, 以package class function 过滤 __package__ __class__
# log.error( f"{__package__}::{__class__.__name__}::{sys._getframe().f_code.co_name} >> ")
# log.error( f"PacakgeName::ClassName::FunctionName:: ")
# LOGGER_FILTER_PACKAGE=[] 为空, 则Filter不起作用
# 不为空,则只显示定义的报名
# LOGGER_FILTER_CLASS=[] 为空, 则Filter不起作用
# 不为空,则只显示定义的类或
# LOGGER_FILTER_FUNCNAME=[] 为空, 则Filter不起作用
# 不为空,则只显示定义的函数
"""
# LOGGER_FILTER_PACKAGE = [ "test_logger" ] # 包名,文件名去 .py??
LOGGER_FILTER_PACKAGE = [ ]
LOGGER_FILTER_CLASS = [ ] # 类名,文件名去 .py??
# LOGGER_FILTER_CLASS = [ "LogTest" ]
# LOGGER_FILTER_FUNCNAME = [ "test1","test" ] # 函数名
LOGGER_FILTER_FUNCNAME = [ ]
LOGGER_FILTER_LEVELNAME = [ ] # INFO DEBUG WARNING
class PackageFilter(logging.Filter):
def __init__(self, filter_word:list = []):
self.filter_word = filter_word
pass
def filter(self, record: logging.LogRecord) -> bool:
if self.filter_word is not None:
return record.package in self.filter_word
class ClassFilter(logging.Filter):
def __init__(self, filter_word:list = []):
self.filter_word = filter_word
pass
def filter(self, record: logging.LogRecord) -> bool:
if self.filter_word is not None:
return record.classname in self.filter_word
pass
class FunctionFilter(logging.Filter):
def __init__(self, filter_word:list = []):
self.filter_word = filter_word
pass
def filter(self, record:logging.LogRecord) -> bool:
if self.filter_word is not None:
return record.funcname in self.filter_word
class LevelNameFilter(logging.Filter):
def __init__(self, filter_word:list = []):
self.filter_word = filter_word
pass
def filter(self, record:logging.LogRecord) -> bool:
if self.filter_word is not None:
return record.levelname in self.filter_word
class ColorFilter(logging.Filter):
def __init__(self,):
pass
def filter(self, record: logging.LogRecord) -> bool:
record.levelname = LOG_FORMAT_COLOR_DICT.get(record.levelname)
return True
class Log(object):
_instance_lock = threading.Lock()
def __new__(cls, *args, **kwargs):
if not hasattr(Log, "_instance"):
with Log._instance_lock:
if not hasattr(Log, "_instance"):
Log._instance = object.__new__(cls)
return Log._instance
def __init__(self, loggername = "DefaultLog" ):
# 文件命名 os.path.join(): 将多个路径组合后返回
self.logger_filepath = LOGGER_FILENAME
self.loggername = loggername
self.level = LOG_LEVEL
# 日志输出格式
fm = LOG_FORMAT
self.formatter = logging.Formatter( fm )
# 生成记录器对象
self.logger = logging.getLogger( self.loggername )
self.logger.setLevel(LOG_LEVEL)
# 日志过滤
self.__add_filter()
def __console(self, level, message, extra={} ):
# 添加 handler
self.__add_handler()
# 判断日志级别
if level == logging.INFO:
self.logger.info( message, extra=extra)
elif level == logging.DEBUG:
self.logger.debug(message,extra=extra)
elif level == logging.WARNING:
self.logger.warning(message,extra=extra)
elif level == logging.ERROR:
self.logger.error(message,extra=extra)
# removeHandler在记录日志之后移除句柄,避免日志输出重复问题
self.__remove_handler()
# if LOG_TO_FILE and self.file_handler:
# self.logger.removeHandler(self.file_handler)
# # 关闭打开的文件
# self.file_handler.close()
# if LOG_TO_CONSOLE and self.stream_handler:
# self.logger.removeHandler(self.stream_handler)
# # 关闭打开的文件
# self.stream_handler.close()
pass
# debug < info< warning< error< critical
# debug模式
def debug(self, message, package="Unknown", classname="Unknown", funcname="Unknown" ):
self.__console(logging.DEBUG, message, extra={"package":package, "classname":classname, "funcname":funcname} )
# self.__remove_handler()
# info模式
def info(self, message, package="Unknown", classname="Unknown", funcname="Unknown" ):
self.__console(logging.INFO, message, extra={"package":package, "classname":classname, "funcname":funcname} )
# self.__remove_handler()
# warning模式
def warning(self, message, package="Unknown", classname="Unknown", funcname="Unknown"):
self.__console(logging.WARNING, message, extra={"package":package, "classname":classname, "funcname":funcname} )
# self.__remove_handler()
# error模式
def error(self, message, package="Unknown", classname="Unknown", funcname="Unknown"):
self.__console(logging.ERROR, message, extra={"package":package, "classname":classname, "funcname":funcname} )
# self.__remove_handler()
def __add_filter(self ):
if len( LOGGER_FILTER_PACKAGE ) > 0 :
self.logger.addFilter( PackageFilter( filter_word=LOGGER_FILTER_PACKAGE ) )
if len( LOGGER_FILTER_CLASS ) > 0 :
self.logger.addFilter( ClassFilter( filter_word=LOGGER_FILTER_CLASS ) )
if len( LOGGER_FILTER_FUNCNAME ) > 0 :
self.logger.addFilter( FunctionFilter( filter_word=LOGGER_FILTER_FUNCNAME ) )
if len(LOGGER_FILTER_LEVELNAME) > 0 :
self.logger.addFilter( LevelNameFilter( filter_word=LOGGER_FILTER_LEVELNAME ) )
def __add_handler(self ):
if LOG_ENABLED and LOG_TO_FILE:
# 考虑使用 RotatingFileHandler TimedRotatingFileHandler防止日志过大
# RotatingFileHandler("test", "a", 4096, 2, "utf-8")
# TimedRotatingFileHandler(filename=LOG_PATH+"thread_", when="D", interval=1, backupCount=7)
self.file_handler = logging.handlers.TimedRotatingFileHandler(filename=self.logger_filepath, when='D', interval=1, backupCount=30, encoding='utf-8')
# self.file_handler = logging.FileHandler( self.logger_filepath, encoding='utf-8' )
self.file_handler.setFormatter( self.formatter )
# self.file_handler.setLevel( LOG_LEVEL )
# if LOG_COLOR_ENABLE: # 文件日志无需加彩色
# self.file_handler.addFilter( ColorFilter( ) )
self.logger.addHandler(self.file_handler)
if LOG_ENABLED and LOG_TO_CONSOLE:
# 创建一个StreamHandler,用于输出到控制台
self.stream_handler = logging.StreamHandler()
self.stream_handler.setFormatter(self.formatter)
# self.stream_handler.setLevel( LOG_LEVEL )
if LOG_COLOR_ENABLE:
self.stream_handler.addFilter( ColorFilter( ) )
self.logger.addHandler(self.stream_handler)
def __remove_handler(self ):
if LOG_TO_FILE and self.file_handler:
self.logger.removeHandler(self.file_handler)
if len(self.logger.handlers)>0:
self.logger.handlers.pop()
# 关闭打开的文件
self.file_handler.close()
if LOG_TO_CONSOLE and self.stream_handler:
self.logger.removeHandler(self.stream_handler)
if len(self.logger.handlers)>0:
self.logger.handlers.pop()
# 关闭控制台
self.stream_handler.close()
def __remove_handler2(self ):
if LOG_ENABLED and LOG_TO_CONSOLE:
self.logger.removeHandler(self.stream_handler)
self.logger.handlers.pop()
# 关闭控制台
self.stream_handler.close()
if LOG_ENABLED and LOG_TO_FILE:
self.logger.removeHandler(self.file_handler)
self.logger.handlers.pop()
# 关闭打开的文件
self.file_handler.close()
log = Log( loggername = "DefaultLog")
"""
filename: 指定日志文件名
filemode: 和file函数意义相同指定日志文件的打开模式wa
format: 指定输出的格式和内容format可以输出很多有用信息显示的条目可以是以下内容
%(levelname) 日志级别的名字格式
%(levelno)s 日志级别的数字表示
%(name)s 日志名字 loggername
%(funcName)s 函数名字
%(asctime) 日志时间可以使用datefmt去定义时间格式如上图
%(pathname) 脚本的绝对路径
%(filename) 脚本的名字
%(module) 模块的名字
%(thread): thread id
%(threadName) 线程的名字
"""
"""
文件名行号 函数名, 要在调用的时候想办法了
# 绝对路径
print( __file__ )
print( sys.argv[0] )
# 文件名
print( os.path.basename(__file__) )
print( os.path.basename(sys.argv[0]) )
self.__class__.__name__
self.__class__.__name__, get_current_function_name()
logger名 __name__
"""

@ -0,0 +1,141 @@
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 = ("Pure Water Absorption Coefficience"
,"Wavelength (nm)"
,"Absorption Coefficience m(-1)" )
self.measure_legend = (" Absorption Coefficient"
,"Wavelength (nm)"
,"Absorption Coefficience m(-1)" )
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, time_, 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=time_[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):
"""docstring for MyPanel."""
def __init__(self, *arg, **kwarg):
super(MyPanel, self).__init__( *arg,**kwarg)
self.SetBackgroundColour("#F2F2F2")
self.sb = wx.StaticBox( self, label='系统信息', pos = (30,30) )
self.sbs = wx.StaticBoxSizer( self.sb, orient=wx.VERTICAL )
self.vbox1 = wx.BoxSizer(wx.VERTICAL)
self.staticText0 = wx.StaticText(self , label='',size=(60, 30), style=wx.ALIGN_CENTRE_VERTICAL )
self.staticText1 = wx.StaticText(self, -1,size=(600, -1),
label='''\n上海奕枫仪器设备有限公司
\n电话: 021-54270075
\n网站: http://www.yi-win.com
\n邮件: sales@yi-win.com
\n描述: AWRAMS离线数据处理 ''' )
self.vbox1.Add(self.staticText0, flag=wx.TOP|wx.LEFT, border=5)
self.vbox1.Add(self.staticText1, flag=wx.TOP|wx.LEFT, border=5)
# 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.vbox1, flag=wx.TOP|wx.LEFT, border= 5)
self.SetSizer(self.sbs)
def setStaticText(self, msg:str):
self.staticText1.SetLabel(msg)

@ -0,0 +1,277 @@
from pathlib import PurePath, Path
# from myconfig import NEWLINE,TOKEN,SEPARATOR
"""
"""
class MyDir(object):
"""
操作方法:设置base tuple_dir header
设置的是路径, 文件名要 ifNotNewFile 传入
调用方法
self.mydir.setBaseDir(path)
self.mydir.newDirIfNot()
self.mydir.newFileIfNot(file_name)
self.mydir.setHeader(header_list, TOKEN, header_str)
if self.mydir.checkHeader() == 0:
self.mydir.writeHeader()
if self.mydir.checkHeader() == -1:
pass
self.mydir.setContent(header_list, TOKEN, header_str)
self.mydir.writeContent()
"""
def __init__(self) -> None:
self.base_dir = Path()
self.dir_tuple = ()
self.header = []
self.header_str = ""
self.content = []
self.content_str = ""
self.current_dir = None
self.current_filepath = None
pass
def getDir(self,):
return self.current_dir
pass
def setBaseDir(self, dir: Path):
self.base_dir = dir
self.current_dir = self.base_dir
pass
def setDir(self, t:tuple=()):
self.dir_tuple = t
if len(self.dir_tuple) == 0 :
self.current_dir = self.base_dir
else:
self.current_dir = self.base_dir.joinpath( *t )
pass
def getDirFromBaseAndTuple(self, base_dir:Path, dir_tuple: tuple):
'''外部调用返回路径'''
ret_path = base_dir
t = dir_tuple
if len(t) == 0 :
ret_path = ret_path
else:
ret_path = ret_path.joinpath( *t )
return ret_path
pass
def setHeader(self, headerlist:list, headerSeperator: str = ";", headerinfo: str = None):
header_str = ""
if len(headerlist) == 0:
return
if headerinfo != None:
header_str = headerinfo + headerSeperator
for hl in headerlist:
header_str = header_str + str(hl) + headerSeperator
self.header_str = header_str[:-1]
pass
def setContent(self, contentlist: list, contentSeperator: str = ";", contentinfo: str = None):
content_str = ""
if len(contentlist) == 0:
return
if contentinfo != None:
content_str = contentinfo + contentSeperator
tmp_str = ""
for cl in contentlist:
tmp_str = tmp_str + str(cl) + contentSeperator
self.content_str = content_str + tmp_str[:-1]
pass
def newDirIfNot(self,) -> None:
# self.current_path = self.base_path.joinpath(self.path_tuple)
self.current_dir.mkdir(parents=True, exist_ok=True)
pass
def newFileIfNot(self, fname: str) -> None:
self.newDirIfNot()
self.current_filepath = self.current_dir.joinpath(fname)
if not self.current_filepath.exists():
with open(self.current_filepath, 'a') as f:
pass
return
pass
def getCurrentFileSize(self,):
return self.current_filepath.stat().st_size
def getFirstline(self,):
first_line = ""
with open(self.current_filepath, 'r') as f: # 打开文件
first_line = f.readline() # 取第一行
return first_line.strip('\n').strip('\r')
def checkHeader(self,) -> int:
'''
返回:
0 : 文件为空,可以直接写header
1 : header对应上 无需处理
-1: 需要提醒用户保存数据后,删除文件后再处理
'''
if self.getCurrentFileSize() == 0:
return 0
first_line = self.getFirstline()
# print(f"firstline: {first_line}" )
# print(f"header_str: {self.header_str}" )
if first_line == self.header_str:
return 1
return -1
pass
def writeHeader(self,) -> None:
with open(self.current_filepath, "a") as f:
f.write(self.header_str)
return None
pass
def writeContent(self,new_line="\n") -> None:
with open(self.current_filepath, "a") as f:
f.write(new_line+self.content_str)
return None
pass
def is_dir_empty(self, ):
'''文件夹是否为空'''
has_next = next(self.current_dir.iterdir(), None)
if has_next is None:
return True
return False
def is_file_empty(self,):
'''文件是否为空'''
if self.current_dir.stat().st_size ==0:
return True
return False
def deleteDir(self,):
'''文件夹是否为空'''
try:
if self.current_dir.exists():
self.current_dir.rmdir()
except OSError as e:
raise Exception(e)
return True
## 其他需求
def get_child_dir(self,) -> list:
ret = []
tmp_dir = self.current_dir.glob("**/")
for td in tmp_dir:
if td.is_dir():
ret.append(td.relative_to(self.current_dir))
return ret
pass
def get_child_dir_only(self,) -> list:
ret = []
for d in self.current_dir.iterdir():
if d.is_dir():
ret.append(d.relative_to(self.current_dir))
return ret
pass
def get_files_from_currentdir(self, fmt:str="*/*" ) -> list:
'''fmt: * */* */*/*'''
ret = []
tmp_dir = self.current_dir.glob(fmt)
print(tmp_dir)
for td in tmp_dir:
if td.is_file():
ret.append(td)
return ret
pass
def sort_dir_and_check( self, dirs:list ):
'''相对目录排序,目录最后一级'''
ret = []
if len(dirs) == 0:
return ret
tmp = {}
tmp_lst = []
for d in dirs:
last:str = d.parts[-1]
if last.isdigit() :
tmp.update( {last:d} )
tmp_lst.append(int(last))
pass
tmp_lst.sort()
for t in tmp:
ret.append(tmp.get(str(t)))
pass
return ret
def sort_filepath_and_check(self, path_files:list):
'''相对目录排序,目录最后一级'''
ret = []
if len(path_files) == 0:
return ret
tmp = {}
tmp_lst = []
for d in path_files:
last:str = d.stem
if last.isdigit() :
tmp.update( {last:d} )
tmp_lst.append(int(last))
pass
tmp_lst.sort()
for t in tmp:
ret.append(tmp.get(str(t)))
pass
return ret
def group_and_sort_filepath(self,path_files:list):
ret = {}
# dirs_lst = []
# len_files = len(path_files)
# if len_files == 0:
# return False
# for pf in path_files:
# pf_dir:str = pf.parts[-2]
# if pf_dir.isdigit() and int(pf_dir) not in dirs_lst:
# dirs_lst.append( int(pf_dir) )
# dirs_lst.sort()
def check_dirs(self, dirs:list, begin:int =0, step:int=1):
'''检查目录是否从begin开始递增'''
len_dirs = len(dirs)
if len_dirs == 0:
return False
for i in range(begin,len_dirs,step) :
if dirs[i].parts[-1] != str(i) :
return False
return True
def check_path_files(self,path_files:list,begin:int =0, step:int=1):
'''检查文件名从begin开始递增'''
len_files = len(path_files)
if len_files == 0:
return False
for i in range(begin,len_files,step) :
if path_files[i].stem != str(i) :
return False
return True
if __name__ == "__main__":
mp = MyDir()
mp.setBaseDir(Path())
print(mp.current_dir)
# t = ("test_dir","1","11")
t = ("test_dir", )
mp.setDir( t )
print(mp.current_dir)
cd = mp.get_child_dir_only()
c = mp.sort_dir_and_check(cd)
print(cd )
print(c )

@ -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()

@ -0,0 +1,71 @@
from datetime import datetime, timedelta
# import locale
# locale.setlocale(locale.LC_ALL, '')
TIME_STR = "2022-06-10 16:16:16"
STD_TIME_STR_FMT = "%Y-%m-%d %H:%M:%S" # 小写y是两位年份
CUR_TIME_STR_FMT = "%Y-%m-%d %H:%M:%S"
class MyTime(object):
"""
操作方法:设置base tuple_path header
调用方法
self.mytime = Mytime()
self.mytime.setCurrentTimeStrFmt()
print(self.mytime.cur_datetime)
s
"""
def __init__(self) -> None:
self.cur_time_str_fmt = "%Y-%m-%d %H:%M:%S"
self.std_time_str_fmt = "%Y-%m-%d %H:%M:%S"
self.cur_time_str = ""
self.std_time_str = ""
self.cur_datetime = ""
pass
def setCurrentTimeStrFmt(self, s):
self.cur_time_str_fmt = s
pass
def setStdTimeStrFmt(self, s):
self.std_time_str_fmt = s
pass
def setCurrentTimeStr(self, s):
self.cur_time_str = s
self.cur_datetime = datetime.strptime(self.cur_time_str, self.cur_time_str_fmt)
pass
def setStdTimeStr(self, s):
self.std_time_str = s
self.cur_datetime = datetime.strptime(
self.std_time_str, STD_TIME_STR_FMT)
pass
def Current2STD(self):
# self.cur_datetime = datetime.strptime(self.cur_time_str , CUR_TIME_STR_FMT)
self.std_time_str = datetime.strftime(
self.cur_datetime, STD_TIME_STR_FMT)
pass
def STD2Current(self, format: str):
# self.cur_datetime = datetime.strptime(self.std_time_str , STD_TIME_STR_FMT)
self.cur_time_str = datetime.strftime(
self.cur_datetime, CUR_TIME_STR_FMT)
pass
def timeDelta(self, days=0, seconds=0, microseconds=0, milliseconds=0, minutes=0, hours=0, weeks=0):
self.cur_datetime = self.cur_datetime + \
timedelta(days=0, seconds=0, microseconds=0,
milliseconds=0, minutes=0, hours=0, weeks=0)
pass
if __name__ == "__main__":
s = "2023-02-07 14:02:46"
mt = MyTime()
mt.setCurrentTimeStr(s)
print(mt.cur_datetime)
pass

@ -0,0 +1,476 @@
import numpy as np
import struct
import math
import time
from scipy.optimize import leastsq
from myconfig import TOKEN, DATA_DIR, FILE_MARK, OUTPUT_DIR, CAL_DIR
from myconfig import PURE_WATER_FNAME,SAVE_EXT_NAME,OSCAR_R,OSCAR_R0
from myconfig import MyConfig
from configuration import Configuration
from myexception import MyException
from mylogger import log
from mypath import MyDir
from mythread import Multithread
from readcal import ReadCal
from uart import Uart
from pathlib import Path, PurePath
from wx.lib.pubsub import pub
FLOAT_RESERVE_BIT = 8
class Oscar(object):
def __init__(self,):
self.cfg = {}
self.mydir = MyDir()
self.file_lst = []
self.raw_wavelength = []
self.raw_wavelength_np = np.array([])
self.purewater_wavelength = []
self.purewater_attenuation = []
self.output_wavelength = []
self.basis = []
self.reflectivity = []
self.begin = 0
self.end = 0
self.dir :Path = Path()
self.datadir :Path = self.dir.joinpath(DATA_DIR)
self.output_dir:Path= self.datadir.joinpath(OUTPUT_DIR)
self.measure_time = ''
self.data = []
self.res = b''
self.msg = {"type":"", "data":{}}
self.__get_purewater_wl_and_data()
self.purewater_after_interp = []
self.uart = Uart()
self.uart_thread = Multithread()
self.ui_sn = ''
self.devicesn = ''
self.filesn = ''
pass
def set_cfg(self, cfg):
self.cfg = cfg
self.ui_sn = self.cfg['device']['UISN']
self.__get_cal_info()
pass
# def set_read_para(self, cfg):
# self.cfg = cfg
# self.ui_sn = self.cfg['device']['UISN']
# pass
# def set_uart_para(self, cfg):
# self.cfg = cfg
# self.ui_sn = self.cfg['device']['UISN']
# pass
def __set_msg(self, typ, d):
self.msg = {}
self.msg.update( {"type":typ} )
self.msg.update( {"data":d} )
pass
# def file_deal_thread(self, func) -> list:
# self.get_data_files()
# self.__deal_file_lst(func)
# pass
def get_data_files(self,) -> list:
# 读取配置文件
self.mydir.setBaseDir(Path(self.datadir))
self.file_lst = self.mydir.get_files_from_currentdir(fmt="*/*.DAT")
def get_begin_end(self,) -> list:
# 读取配置文件
for i in range( len(self.raw_wavelength)):
if self.raw_wavelength[i]<self.cfg['retrieve']['beginWL'] \
and self.raw_wavelength[i+1]>self.cfg['retrieve']['beginWL']:
self.begin = i+1
pass
if self.raw_wavelength[i]<self.cfg['retrieve']['endWL'] \
and self.raw_wavelength[i+1]>self.cfg['retrieve']['endWL']:
self.end = i+2
break
self.get_output_wavelength()
msg = "起始波长 : "+ str(self.output_wavelength[0]) +" , 结束波长 : "+ str(self.output_wavelength[-1])
log.info(msg, __name__, '','')
self.__set_msg ("notice", msg )
pub.sendMessage(self.msg)
def get_output_wavelength(self,) :
self.output_wavelength = self.raw_wavelength[self.begin:self.end]
pass
def deal_file_lst(self, ):
for fl in self.file_lst:
log.info(f"-> {fl} ",__name__,"deal_file_lst")
# 判断序列号是否一致file_lst
if not self.__check_sn_from_datafile(fl):
raise MyException( "文件的序列号和系统设置不一致" )
# 判断原始波长是否为空
if self.raw_wavelength == []:
self.__get_raw_wl_from_datafile(self.file_lst[0])
# 获得截取的开始 结束点
self.get_begin_end()
# 纯水系数插值
self.interpo_pure_water()
# 准备储存数据文件
self.__prepare_for_save()
ReadCal.read_columns_sets_by_mark_callback(
fl, FILE_MARK, self.deal_measure_time_data, 1)
# self.__set_msg( "notice", "文件处理完毕" )
# pub.sendMessage( "update", msg = self.msg )
def deal_measure_time_data(self, sn, res_time, res_data):
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")
basis = self.basis[self.begin:self.end]
refl = self.reflectivity[self.begin:self.end]
for i in range(len(res_time)):
data = self.convert_str_2_float_list( res_data[i][0][self.begin:self.end] )
abs_coeff_with_water = self.get_absorption_coeff(
data,basis,refl,self.purewater_after_interp)
data = self.correction_pure_water(abs_coeff_with_water)
# data = data.tolist()
# print(data)
self.mydir.setContent( data , TOKEN, res_time[i] )
self.mydir.writeContent()
self.measure_time = res_time[i]
self.data = data
self.__set_msg( "data", {"time":res_time[i], "data":data } )
pub.sendMessage("update", msg=self.msg)
# pub.sendMessage("update", msg=res_data[i][0][self.begin:self.end])
def __check_sn_from_datafile(self, fpath) -> bool:
# 读取配置文件
sn = ReadCal.readFileSNbyIDDevice(fpath)
if sn == self.ui_sn:
return True
return False
def __get_raw_wl_from_datafile(self, fpath) -> None:
# 读取配置文件
_, raw_wl = ReadCal.read_columns_set_by_mark(fpath, FILE_MARK, 0)
self.raw_wavelength = self.convert_str_2_float_list (raw_wl[0])
self.raw_wavelength_np = np.array(raw_wl[0])
return None
def __prepare_for_save(self,) -> bool:
self.mydir.setBaseDir(self.output_dir)
self.mydir.newDirIfNot()
self.mydir.newFileIfNot(self.ui_sn+SAVE_EXT_NAME)
self.mydir.setHeader(self.output_wavelength, TOKEN, self.ui_sn)
if self.mydir.checkHeader() == 0:
self.mydir.writeHeader()
if self.mydir.checkHeader() == -1:
# self.popDialog(" 文件头不一致, 请备份到其他目录,并在该目录下删除")
raise MyException(" 文件头不一致, 请备份到其他目录,并在该目录下删除")
def interpo_pure_water(self):
self.purewater_after_interp = np.interp(
np.array(self.output_wavelength)
, np.array(self.purewater_wavelength)
, np.array(self.purewater_attenuation)
)
pass
def correction_turbidity(self, data:np.ndarray ):
'''浊度校正, 吸光度
0 : 默认11项平均
1 : 720
2 : 不浊度校正
'''
log.debug( "correction_turbidity .....",__name__, 'correction_turbidity' )
if self.cfg['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
return data - tmp
pass
if self.cfg['algorithm']['A720'] == 1:
count = data.shape[0]
tmp = data[count] - (self.output_wavelength[count]-720) * (data[count] -data[count-1]) \
/ (self.output_wavelength[count]-self.output_wavelength[count-1])
print(f"tmp .... {tmp}")
return data-tmp
pass
if self.cfg['algorithm']['A720'] == 2:
return data
return data
pass
def correction_pure_water(self, data:np.ndarray ):
'''浊度校正
0 : 不变
1 : 减去纯水
'''
if self.cfg['algorithm']['PureWater'] == 0:
return data
pass
if self.cfg['algorithm']['PureWater'] == 1:
return data - self.purewater_after_interp
pass
return data
pass
def __get_cal_info(self ):
log.info(f" == ",__name__,'__get_cal_info')
caldir = self.dir.joinpath(CAL_DIR )
basis_fpath = caldir.joinpath( "Basis aq_" + self.cfg['device']['UISN'] + ".dat")
reflectivity_fpath = caldir.joinpath( "Reflectivity_" + self.cfg['device']['UISN'] + ".dat")
if basis_fpath.exists():
_, res_data = ReadCal.read_columns_sets_by_mark(
basis_fpath, FILE_MARK, 1)
self.basis = self.convert_str_2_float_list( res_data[0][0] )
if reflectivity_fpath.exists():
_, res_data = ReadCal.read_columns_sets_by_mark(
reflectivity_fpath, FILE_MARK, 1)
self.reflectivity = self.convert_str_2_float_list( res_data[0][0] )
def __get_purewater_wl_and_data(self ):
log.debug(f" ok ",__name__,'__get_purewater_wl_and_data')
caldir = self.dir.joinpath(CAL_DIR )
cal_fpath = caldir.joinpath( PURE_WATER_FNAME)
if cal_fpath.exists():
_, res_data = ReadCal.read_columns_sets_by_mark(
cal_fpath, FILE_MARK, 0, 1)
self.purewater_wavelength = self.convert_str_2_float_list( res_data[0][0])
self.purewater_attenuation = self.convert_str_2_float_list(res_data[0][1])
def set_serial(self, )-> None:
self.uart.set_serial_para(
self.cfg['comsetting']['port']
,self.cfg['comsetting']['baudrate']
,self.cfg['comsetting']['bytesize']
,self.cfg['comsetting']['parity']
,self.cfg['comsetting']['stopbit']
)
def set_modbus(self, beginaddress, step)-> None:
self.uart.set_modbus(
self.cfg['register']['slaveaddress']
,self.cfg['register']['functioncode']
,beginaddress
,step
)
def sn_uart_thread(self, func)-> None:
self.set_serial()
self.uart_thread.remove_tasks()
self.set_modbus( self.cfg['register']['SNAddress'], self.cfg['register']['SNLen'] )
self.uart_thread.add_task( self.device_sn, args=(func,) )
self.uart_thread.sequently_execute_tasks()
pass
def wl_uart_thread(self, func)-> None:
if self.devicesn == []:
raise Exception(" 请读取设备序列号!!")
self.res = b''
self.set_serial()
self.uart_thread.remove_tasks()
for i in range(self.cfg['register']['count']):
log.debug(f" -> i {i}", __name__,"wl_uart_thread")
self.set_modbus( self.cfg['register']['WLBeginAddress'] + i*120, 120 )
log.debug(f" command -> {self.uart.command.hex()} ")
self.uart_thread.add_task( self.device_wl, args=() )
self.uart_thread.sequently_execute_tasks()
self.uart_thread.remove_tasks()
# self.uart_thread.add_task_2_act( )
# self.uart_thread.execute_one_act()
self.raw_wavelength = self.convert_buf_2_float(self.res)
# 获得截取的开始 结束点
self.get_begin_end()
self.get_output_wavelength()
msg = "起始波长 : "+str(self.output_wavelength[0]) +" , 结束波长 : "+ str(self.output_wavelength[-1])
log.info(msg)
self.__set_msg ("notice", msg )
pub.sendMessage(self.msg)
func( self.output_wavelength )
# self.__set_msg( "wl", {} )
# pub.sendMessage("update", msg= self.msg)
def log_uart_thread(self, func)-> None:
if self.output_wavelength == [] :
raise Exception("没有波长文件,请读取设备波长!!")
if self.purewater_after_interp == [] :
self.interpo_pure_water()
# 准备测量,保存文件的准备
self.__prepare_for_save()
self.res = b''
self.set_serial()
self.uart_thread.remove_tasks()
for i in range(self.cfg['register']['count']):
self.set_modbus( self.cfg['register']['DataBeginAddress'] + i * 120, 120 )
self.uart_thread.add_task( self.device_log, args=( ) )
self.uart_thread.sequently_execute_tasks()
self.uart_thread.remove_tasks()
pass
data = self.convert_buf_2_float(self.res,FLOAT_RESERVE_BIT)
data = data[self.begin:self.end]
log.info( f"log data : {data}",__name__,'log_uart_thread' )
abs_coeff_with_water = self.get_absorption_coeff(
data,
self.basis[self.begin:self.end],
self.reflectivity[self.begin:self.end],
self.purewater_after_interp )
data = self.correction_pure_water( abs_coeff_with_water )
# 保存文件
tm = time.strftime("%Y-%m-%d %H:%M:%S",time.localtime())
self.mydir.setContent( data , TOKEN, tm )
self.mydir.writeContent()
func(tm,data)
def device_sn(self, func)-> None:
self.res =b''
self.uart.disconnect()
self.uart.connect()
self.uart.write()
self.res = self.uart.OneMeasure()
self.devicesn = self.res[-6:-2].decode()
self.res = b''
func( self.devicesn )
# pub.sendMessage("update",msg=self.msg)
def device_wl(self, )-> None:
# self.res =b''
# log.warning(" -->", __name__, "device_wl")
self.uart.disconnect()
self.uart.connect()
self.uart.write()
tmp = self.uart.OneMeasure()
self.res = self.res + tmp[3:len(tmp)-2]
def device_log(self, )-> None:
# self.res =b''
self.uart.disconnect()
self.uart.connect()
self.uart.write()
tmp = self.uart.OneMeasure()
self.res = self.res + tmp[3:len(tmp)-2]
def convert_buf_2_float(self, buff, bit = 3 ,byteOrder= "big" )-> None:
res = []
log.debug(f" === {len(buff)}== {buff}", __name__, 'convert_buf_2_float')
len_ = len(buff)
if len_%4 != 0:
return res
if byteOrder == "big":
for i in range( int(len_/4) ):
tmp = struct.unpack(">f", buff[i*4: i*4+4] )
res.append( round(tmp[0],bit) )
else:
for i in range( int(len_/4) ):
tmp = struct.unpack(">f", buff[i*4: i*4+4] )
res.append(round(tmp[0],bit))
return res
pass
def convert_str_2_float_list(self, lst )-> None:
res = []
for l in lst:
res.append(float(l))
return res
pass
def set_raw_wavelength_from_device(self, lst):
self.raw_wavelength = lst
pass
def get_absorption_coeff( self, data, refl, basis_aq, abs_coff_pw ):
"""
@description : d 一组数据
"""
r = OSCAR_R
r0 = OSCAR_R0
abs_coeff_with_pw =[]
# log.info( f" do_leastsq -> {len(data)} " )
if len(data) == len( refl) or len(data) == len( basis_aq) or len(data) == len( abs_coff_pw) :
for fa,fb,rou,ab in zip(data, basis_aq,refl, abs_coff_pw ):
Tab = float(fa)/float(fb)
#print( "Tab %s" %Tab)
EXP_ab_r0 = np.exp(-1*float(ab)*r0)
#print ( "Exp_ab_r0 %s" %EXP_ab_r0)
Ps_ab_r = ( 1 - ( 2*float(ab)*r + 1) * np.exp (-2*float(ab)*r) ) /( 2*float(ab)*float(ab)*r*r )
#print ( "Ps_ab_r %s" %Ps_ab_r)
# EXP_aa_r0 = exp(-1*aa*r0)
# Ps_aa_r = ( 1 - ( 2*aa*r + 1) * exp (-2*aa*r) ) /( 2*aa*aa*r*r )
def f(x):
return Tab*EXP_ab_r0*Ps_ab_r - \
np.exp(-1*x*r0)*( 1 - ( 2*x*r + 1) * np.exp (-2*x*r) ) /( 2*x*x*r*r ) - \
float(rou)* Tab *EXP_ab_r0*Ps_ab_r*( 1 - ( 2*x*r + 1) * np.exp (-2*x*r) ) /( 2*x*x*r*r ) + \
float(rou)* np.exp(-1*x*r0)*Ps_ab_r *( 1 - ( 2*x*r + 1) * np.exp (-2*x*r) ) /( 2*x*x*r*r )
result_with_pw = leastsq(f, 1)[0][0]
# print( result_with_pw )
# 添加到数组
abs_coeff_with_pw.append( result_with_pw )
return abs_coeff_with_pw
if __name__ == '__main__':
data = np.array([3,4,5,6])
print(data.shape[0])
print(data[3])
print(data-1)
# if self.syscfg['retrieve']['enable'] == 0:
# self.mydir.setHeader(self.raw_wavelength,TOKEN,self.ui_sn)
# if self.mydir.checkHeader()==0:
# self.mydir.writeHeader()
# if self.mydir.checkHeader()==-1:
# self.popDialog(" 文件头不一致, 请备份到其他目录,并在该目录下删除")
# raise MyException(" 文件头不一致, 请备份到其他目录,并在该目录下删除")
# res_time,res_data = ReadCal.read_columns_sets_by_mark( fl, FILE_MARK, 1 )
# for i in range( len(res_time) ):
# self.__deal_one_measure_time_data(res_time[i], res_data[i])
# pass
# pass
# # 需要插值处理波长
# if self.syscfg['retrieve']['enable'] == 1:
# self.mydir.setHeader(self.new_wavelength.tolist(),TOKEN,self.ui_sn)
# if self.mydir.checkHeader()==0:
# self.mydir.writeHeader()
# if self.mydir.checkHeader()==-1:
# self.popDialog(" 文件头不一致, 请备份到其他目录,并在该目录下删除")
# raise MyException(" 文件头不一致, 请备份到其他目录,并在该目录下删除")
# # res_data 不用带回调的函数callback 会导致多组数据拼接??
# res_time,res_data = ReadCal.read_columns_sets_by_mark( fl, FILE_MARK, 1 )
# log.warning(f" ==== {len(res_time)}" )
# log.warning(res_time)
# log.warning(f" ==== {len(res_data[0])}" )
# log.warning(f" ==== { res_data[0] }" )
# for i in range( len(res_time) ):
# self.__deal_one_measure_time_data(res_time[i], res_data[0][i])
# pass
# pass

File diff suppressed because it is too large Load Diff

@ -0,0 +1,3 @@
beginWL: 360
endWL: 721
interval: 1

@ -0,0 +1,200 @@
import serial
import struct
import time
class Uart(object):
def __init__(self,):
self.ser = serial.Serial()
self.__buf = b''
self.command = b''
self._is_connected = False
self.begin_time = None
pass
def set_serial_para(self, port="COM1",baudrate=9600,bytesize=8,parity="N", stopbit=1, timeout = 4):
self.port = port
self.ser.port = port
self.ser.baudrate = baudrate
self.ser.bytesize = bytesize
self.ser.parity = parity
self.ser.stopbits = stopbit
self.ser.timeout = timeout
def set_modbus(self, slaveaddress=1, functioncode=3, beginaddress=0, step=5 ):
self.slaveaddress = slaveaddress
self.functioncode = functioncode
self.beginaddress = beginaddress
self.step = step
self.command = self.__get_modbus_command()
self.rcv_len = 2*self.step + 5 # 16bit
def connect(self,):
try:
self.ser.open()
if self.ser.isOpen():
self._is_connected = True
self.ser.close()
except Exception as e:
self._is_connected = False
# SerialException(f"KH3000 can not open port : {self.ser.port}")
if self.ser is not None and self.ser.isOpen():
self.ser.close()
return self._is_connected
def disconnect(self,):
if self._is_connected or self.ser.isOpen():
self.ser.close()
self._is_received = False
self._is_connected = False
pass
def write(self,) -> None:
try:
self.ser.open()
if self.ser.isOpen():
self.ser._is_connected = True
except Exception as e:
self.ser. _is_connected = False
if self.ser._is_connected:
self.begin_time = time.time()
self.ser.reset_input_buffer()
self.ser.reset_output_buffer()
# print(f"========= command {self.command.hex() }")
self.ser.write(self.command)
# if isHex:
# data = bytes.fromhex(data)
# self.ser.write(bytes(data))
# else:
# self.ser.write(bytes(data, encoding='utf8')+b'\x0A\x0D')
def receive(self,):
self.flush()
while 1:
if not self._is_receiving:
break
if self.ser.in_waiting: # 这个接收是随机的
for _ in range(self.ser.in_waiting):
# print( type(_serial.read(1)))
temp = self.ser.read(1) # 可以直接读取指定长度
self.__buf = self.__buf + temp
if len(self.__buf) >= self.rcv_len:
break
if time.time() - self.begin_time > self.ser.timeout:
self.__buf = b''
break
self._is_receiving = False
def OneMeasure(self) -> bytes:
if not self.ser.isOpen():
self.ser.open()
self._is_receiving = True
self.__buf = b''
self.receive()
if len(self.__buf)>=self.rcv_len and not self._is_receiving :
return self.__buf
return b''
pass
def reset_input_buffer(self)->None:
self.ser.reset_input_buffer()
pass
def reset_output_buffer(self)->None:
self.ser.reset_output_buffer()
pass
def flush(self)->None:
self.ser.flush()
pass
def IsOpen(self)->bool:
return self._is_connected
pass
def IsReceived(self)->bool:
return self._is_received
pass
def getResult(self)->bytes:
return self.__buf
pass
def add_crc16( self, buf:bytes ):
'''
一般发送命令都是'01030000000A'这样的字符串
输入test2 = '01030000000A'
输出0xc5cd
hexstr[2:].upper() 去掉
'''
crc = 0xFFFF
for pos in buf:
crc ^= pos
for i in range(8):
if ((crc & 1) != 0):
crc >>= 1
crc ^= 0xA001
else:
crc >>= 1
return ((crc & 0xff) << 8) + (crc >> 8)
# return hex(((crc & 0xff) << 8) + (crc >> 8))[2:].upper()
def crc16Check(self,buf:bytes):
if len(buf) > 4 :
crc = self.add_crc16(buf[:-2])
if (crc & 0xff) == buf[-1] and (crc >> 8)== buf[-2]:
return True
else:
return False
else:
return False
def __get_modbus_command(self, ):
res = b''
res = res + self.slaveaddress.to_bytes(1, byteorder="big")
res = res + self.functioncode.to_bytes(1, byteorder="big")
res = res + self.beginaddress.to_bytes(2, byteorder="big")
res = res + self.step.to_bytes(2, byteorder="big")
crc = self.add_crc16(res)
hi = (crc >> 8).to_bytes(1, byteorder="big")
lo = (crc & 0xff).to_bytes(1, byteorder="big")
return res + hi + lo
pass
if __name__ == '__main__':
# 字符串转字节
u = Uart()
s = "01030000000A"
sss = b'\x01\x03\x00\x00\x00\x0A\xC5\xCD'
print(bytes.fromhex(s))
print(bytearray.fromhex(s))
print( u.add_crc16(bytes.fromhex(s)) )
print("00000000000000000000000000000000000")
print(sss[:-2])
if u.crc16Check(sss):
print("TRUE,...")
else:
print("fffffffffffff")
# 数字转字节
a = 1024
b=a.to_bytes(2, byteorder='big') # 2个字节
a.from_bytes(b'\x04\x00', byteorder='big')
# ASCIIunpack
data = "a"
bytes(data, encoding='utf8')
# struct 打包转字节
ss = struct.pack('>H', 8) # unpack
print(ss)
pass

@ -0,0 +1,110 @@
#!/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_Algorithm(wx.Dialog):
"""
@description : 算法配置
"""
def __init__(self, parent, id):
# 串口页面配置
super(UI_Algorithm, 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_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( "algorithm", "A720" )
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( "algorithm", "2" )
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.hbox3 = wx.BoxSizer(wx.HORIZONTAL)
self.staticText3 = wx.StaticText(self.panel, label='纯水: ' ,size=(60, -1))
# self.staticText2_1 = wx.StaticText(self.panel, label='分钟 ' ,size=(60, -1))
self.textCtrl3 = wx.TextCtrl(self.panel, value="",size=(250,25))
tmp = self.get_str_from_config( "algorithm", "3" )
if tmp is not None:
self.textCtrl3.SetValue(tmp)
self.hbox3.Add(self.staticText3, flag=wx.TOP|wx.LEFT, border=5)
self.hbox3.Add(self.textCtrl3,flag=wx.TOP|wx.LEFT, border=5)
# self.hbox2.Add(self.staticText2_1, flag=wx.TOP|wx.LEFT, border=5)
self.sbs.Add(self.hbox3, 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, section, key ):
return str(self.config_yml[section][key])
pass
def set_config_by_section_key_val( self, section, key, val ):
# print(f" {key} current type {type( self.config_yml[section][key] )}")
if type( self.config_yml[section][key] ) == int:
self.config_yml[section][key] = int(val)
elif type( self.config_yml[section][key] ) == float:
self.config_yml[section][key] = float(val)
else:
self.config_yml[section][key] = val
pass
def saveData(self, e):
pass
def OnClose(self, e):
self.Destroy()
def OnSave(self, e):
success = True
# 赋值字典,写入文件
self.set_config_by_section_key_val( 'algorithm',"1",self.textCtrl1.GetValue( ) )
self.set_config_by_section_key_val( 'algorithm',"2",self.textCtrl2.GetValue( ) )
self.set_config_by_section_key_val( 'algorithm',"3",self.textCtrl2.GetValue( ) )
self.config.write_yaml(self.config_yml)
del self.config
if success:
self.EndModal(wx.ID_OK)

@ -0,0 +1,138 @@
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
import wx
from myconfig import MyConfig
from myconfig import YAML_FILE_NAME
class UI_Com_Setting(wx.Dialog):
"""
@description : Com 配置
"""
def __init__(self, parent,id):
# 串口页面配置
super(UI_Com_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_yaml()
# print(self.config_yml['comsetting'])
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("comsetting",'port')
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("comsetting",'baudrate')
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.hbox3 = wx.BoxSizer(wx.HORIZONTAL)
self.staticText3 = wx.StaticText(self.panel, label='数据位: ' ,size=(60, -1))
# self.staticText3_1 = wx.StaticText(self.panel, label='分钟 ' ,size=(60, -1))
self.textCtrl3 = wx.TextCtrl(self.panel, value="",size=(250,25))
tmp = self.get_str_from_config("comsetting",'bytesize')
if tmp is not None:
self.textCtrl3.SetValue(tmp)
self.hbox3.Add(self.staticText3, flag=wx.TOP|wx.LEFT, border=5)
self.hbox3.Add(self.textCtrl3,flag=wx.TOP|wx.LEFT, border=5)
# self.hbox3.Add(self.staticText3_1, flag=wx.TOP|wx.LEFT, border=5)
self.sbs.Add(self.hbox3, flag=wx.TOP|wx.LEFT, border=5)
self.hbox4 = wx.BoxSizer(wx.HORIZONTAL)
self.staticText4 = wx.StaticText(self.panel, label='奇偶性: ' ,size=(60, -1))
# self.staticText3_1 = wx.StaticText(self.panel, label='分钟 ' ,size=(60, -1))
self.textCtrl4 = wx.TextCtrl(self.panel, value="",size=(250,25))
tmp = self.get_str_from_config("comsetting",'parity')
if tmp is not None:
self.textCtrl4.SetValue(tmp)
self.hbox4.Add(self.staticText4, flag=wx.TOP|wx.LEFT, border=5)
self.hbox4.Add(self.textCtrl4,flag=wx.TOP|wx.LEFT, border=5)
self.sbs.Add( self.hbox4, flag=wx.TOP|wx.LEFT, border=5 )
self.hbox5 = wx.BoxSizer(wx.HORIZONTAL)
self.staticText5 = wx.StaticText(self.panel, label='停止位: ' ,size=(60, -1))
# self.staticText3_1 = wx.StaticText(self.panel, label='分钟 ' ,size=(60, -1))
self.textCtrl5 = wx.TextCtrl(self.panel, value="",size=(250,25))
tmp = self.get_str_from_config("comsetting",'stopbit')
if tmp is not None:
self.textCtrl5.SetValue(tmp)
self.hbox5.Add(self.staticText5, flag=wx.TOP|wx.LEFT, border=5)
self.hbox5.Add(self.textCtrl5, flag=wx.TOP|wx.LEFT, border=5)
self.sbs.Add( self.hbox5, 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, section, key ):
return str(self.config_yml[section][key])
pass
def set_config_by_section_key_val( self, section, key, val ):
# print(f" {key} current type {type( self.config_yml[section][key] )}")
if type( self.config_yml[section][key] ) == int:
self.config_yml[section][key] = int(val)
elif type( self.config_yml[section][key] ) == float:
self.config_yml[section][key] = float(val)
else:
self.config_yml[section][key] = val
pass
def saveData( self, e ):
pass
def OnClose( self, e ):
self.Destroy()
def OnSave(self, e):
success = True
# 赋值字典,写入文件
self.set_config_by_section_key_val("comsetting", 'port', self.textCtrl1.GetValue( ))
self.set_config_by_section_key_val("comsetting", 'baudrate', self.textCtrl2.GetValue( ))
self.set_config_by_section_key_val("comsetting", 'bytesize', self.textCtrl3.GetValue( ))
self.set_config_by_section_key_val("comsetting", 'parity', self.textCtrl4.GetValue( ))
self.set_config_by_section_key_val("comsetting", 'stopbit', self.textCtrl5.GetValue( ))
self.config.write_yaml(self.config_yml)
del self.config
if success:
self.EndModal(wx.ID_OK)

@ -0,0 +1,92 @@
#!/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_Filepath_Setting(wx.Dialog):
"""
@description : 文件路径 配置
"""
def __init__(self, parent,id):
# 串口页面配置
super(UI_Filepath_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_yaml()
# self.sensor = self.config_sensor.get(self.did)
# print(self.config_sensor)
# print(self.sensor)
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("filepath","path")
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.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, section, key ):
return str(self.config_yml[section][key])
pass
def set_config_by_section_key_val( self, section, key, val ):
# print(f" {key} current type {type( self.config_yml[section][key] )}")
if type( self.config_yml[section][key] ) == int:
self.config_yml[section][key] = int(val)
elif type( self.config_yml[section][key] ) == float:
self.config_yml[section][key] = float(val)
else:
self.config_yml[section][key] = val
pass
def saveData(self, e):
pass
def OnClose(self, e):
self.Destroy()
def OnSave(self, e):
success = True
# 赋值字典,写入文件
self.set_config_by_section_key_val('filepath',"path",self.textCtrl1.GetValue( ))
self.config_yml.write_yaml(self.config_sensor)
del self.config
if success:
self.EndModal(wx.ID_OK)

@ -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_Log_Setting(wx.Dialog):
"""
@description : Sensor 配置
"""
def __init__(self, parent, id):
# 串口页面配置
super(UI_Log_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_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( "logsetting", "LogInterval" )
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( "logsetting", "RefreshInterval" )
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, section, key ):
return str(self.config_yml[section][key])
pass
def set_config_by_section_key_val( self, section, key, val ):
# print(f" {key} current type {type( self.config_yml[section][key] )}")
if type( self.config_yml[section][key] ) == int:
self.config_yml[section][key] = int(val)
elif type( self.config_yml[section][key] ) == float:
self.config_yml[section][key] = float(val)
else:
self.config_yml[section][key] = val
pass
def saveData(self, e):
pass
def OnClose(self, e):
self.Destroy()
def OnSave(self, e):
success = True
# 赋值字典,写入文件
self.set_config_by_section_key_val('logsetting',"LogInterval",self.textCtrl1.GetValue( ))
self.set_config_by_section_key_val('logsetting',"RefreshInterval",self.textCtrl2.GetValue( ))
self.config.write_yaml(self.config_yml)
del self.config
if success:
self.EndModal(wx.ID_OK)

@ -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_PathSN_Setting(wx.Dialog):
"""
@description : 设置光程 序列号
"""
def __init__(self, parent,id):
# 串口页面配置
super(UI_PathSN_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_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( "device", "UIPath" )
# 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( "device", "UISN" )
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, section, key ):
return str(self.config_yml[section][key])
pass
def set_config_by_section_key_val( self, section, key, val ):
# print(f" {key} current type {type( self.config_yml[section][key] )}")
if type( self.config_yml[section][key] ) == int:
self.config_yml[section][key] = int(val)
elif type( self.config_yml[section][key] ) == float:
self.config_yml[section][key] = float(val)
else:
self.config_yml[section][key] = val
pass
def saveData(self, e):
pass
def OnClose(self, e):
self.Destroy()
def OnSave(self, e):
success = True
# 赋值字典,写入文件
# self.set_config_by_section_key_val('device',"UIPath",self.textCtrl1.GetValue( ))
self.set_config_by_section_key_val('device',"UISN",self.textCtrl2.GetValue( ))
self.config.write_yaml(self.config_yml)
del self.config
if success:
self.EndModal(wx.ID_OK)

@ -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_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( "plotsetting", "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( "plotsetting", "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, section, key ):
return str(self.config_yml[section][key])
pass
def set_config_by_section_key_val( self, section, key, val ):
# print(f" {key} current type {type( self.config_yml[section][key] )}")
if type( self.config_yml[section][key] ) == int:
self.config_yml[section][key] = int(val)
elif type( self.config_yml[section][key] ) == float:
self.config_yml[section][key] = float(val)
else:
self.config_yml[section][key] = val
pass
def saveData(self, e):
pass
def OnClose(self, e):
self.Destroy()
def OnSave(self, e):
success = True
# 赋值字典,写入文件
self.set_config_by_section_key_val('plotsetting',"LineBegin",self.textCtrl1.GetValue( ))
self.set_config_by_section_key_val('plotsetting',"LineInterval",self.textCtrl2.GetValue( ))
self.config.write_yaml(self.config_yml)
del self.config
if success:
self.EndModal(wx.ID_OK)

@ -0,0 +1,60 @@
import wx
# 设置串口参数的对话框类
class About(wx.Dialog):
def __init__(self, *args, **kwds):
# 参数调入后初始化
super(About, self).__init__(*args, **kwds)
self.InitUI()
self.SetSize((400, 400))
self.SetTitle("使用帮助")
def InitUI(self):
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='''\n上海奕枫仪器设备有限公司
电话: 021-54270075
网站: http://www.yi-win.com
邮件: sales@yi-win.com ''' )
self.hbox1.Add(self.staticText1)
self.sbs.Add(self.hbox1)
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='关闭')
self.hbox_0.Add(self.okButton)
self.hbox_0.Add(self.closeButton, flag=wx.LEFT, border=5)
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 saveData(self, e):
pass
def OnClose(self, e):
self.Destroy()
def OnSave(self, e):
self.EndModal(wx.ID_OK)

@ -0,0 +1,58 @@
import wx
# 设置串口参数的对话框类
class Help(wx.Dialog):
def __init__(self, *args, **kwds):
# 参数调入后初始化
super(Help, self).__init__(*args, **kwds)
self.InitUI()
self.SetSize((400, 400))
self.SetTitle("使用帮助")
def InitUI(self):
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='''\n上海奕枫仪器设备有限公司
电话: 021-54270075
网站: http://www.yi-win.com
邮件: sales@yi-win.com ''' )
self.hbox1.Add(self.staticText1)
self.sbs.Add(self.hbox1)
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='关闭')
self.hbox_0.Add(self.okButton)
self.hbox_0.Add(self.closeButton, flag=wx.LEFT, border=5)
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 saveData(self, e):
pass
def OnClose(self, e):
self.Destroy()
def OnSave(self, e):
self.EndModal(wx.ID_OK)

@ -0,0 +1,124 @@
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
import wx
# from configobj import ConfigObj
from myconfig import MyConfig
from myconfig import YAML_FILE_NAME
class UISensor(wx.Dialog):
"""
@description : Sensor 配置
"""
def __init__(self, parent, id, did):
# 参数调入后初始化
self.did = did
super(UISensor, self).__init__( parent, id=id )
self.config = MyConfig()
self.InitUI()
self.SetSize((400, 400))
self.SetTitle(" 设置页面 串口 采集间隔 ")
def InitUI(self):
self.config_sensor = self.config.read_yaml()
# self.sensor = self.config_sensor.get(self.did)
# print(self.config_sensor)
# print(self.sensor)
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='Lsky: ',size=(60, -1), style=wx.ALIGN_CENTRE_VERTICAL )
self.textCtrl1 = wx.TextCtrl(self.panel, value="",size=(250,25) )
tmp = self.getSnByDidAndFunc("Lsky",self.did)
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='Esky: ' ,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.getSnByDidAndFunc("Esky",self.did)
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.hbox3 = wx.BoxSizer(wx.HORIZONTAL)
self.staticText3 = wx.StaticText(self.panel, label='Lwater: ' ,size=(60, -1))
# self.staticText3_1 = wx.StaticText(self.panel, label='分钟 ' ,size=(60, -1))
self.textCtrl3 = wx.TextCtrl(self.panel, value="",size=(250,25))
tmp = self.getSnByDidAndFunc("Lwater",self.did)
if tmp is not None:
self.textCtrl3.SetValue(tmp)
self.hbox3.Add(self.staticText3, flag=wx.TOP|wx.LEFT, border=5)
self.hbox3.Add(self.textCtrl3,flag=wx.TOP|wx.LEFT, border=5)
# self.hbox3.Add(self.staticText3_1, flag=wx.TOP|wx.LEFT, border=5)
self.sbs.Add(self.hbox3, 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 getSnByDidAndFunc(self,func,did):
temp:dict = self.config_sensor.get(did)
for v in temp.values():
if v["FUNC"] == func:
return v["SN"]
return None
pass
def setSnByDidAndFunc(self,func,did,val):
temp:dict = self.config_sensor.get(did)
for k,v in temp.items():
if v["FUNC"] == func:
temp[k]['SN'] =val
self.config_sensor.update({did:temp})
pass
def saveData(self, e):
pass
def OnClose(self, e):
self.Destroy()
def OnSave(self, e):
success = True
# 赋值字典,写入文件
self.setSnByDidAndFunc('Lsky',self.did,self.textCtrl1.GetValue( ))
self.setSnByDidAndFunc('Esky',self.did,self.textCtrl2.GetValue( ))
self.setSnByDidAndFunc('Lwater',self.did,self.textCtrl3.GetValue( ))
print(self.textCtrl3.GetValue( ))
print(self.config_sensor)
self.config.write_yaml(self.config_sensor)
del self.config
if success:
self.EndModal(wx.ID_OK)

@ -0,0 +1,772 @@
import wx
import os
import time
import threading
import numpy as np
from pathlib import Path,PurePath
from wx.lib.pubsub import pub
# from configobj import ConfigObj
from listctrl import Listctrl
# from mypanel import MyPanel
from mypanel import Plot
from uiconfig.ui_com_setting import UI_Com_Setting
from uiconfig.ui_filepath_setting import UI_Filepath_Setting
from uiconfig.ui_pathsn_setting import UI_PathSN_Setting
from uiconfig.ui_plot_setting import UI_Plot_Setting
from uiconfig.ui_log_setting import UI_Log_Setting
from uiconfig.uiabout import About
from uiconfig.uihelp import Help
from myconfig import DeviceType,YAML_FILE_NAME,RETRIEVE_CFG_FILE
from myconfig import TOKEN,DATA_DIR,FILE_MARK,OUTPUT_DIR,SAVE_EXT_NAME
from myconfig import MyConfig
from configuration import Configuration
# from awrams import AWRAMS,HandHeldBuf
from myexception import MyException
from mylogger import log
from mypath import MyDir
from mythread import Mythead
from readcal import ReadCal
from uart import Uart
from oscar import Oscar
from dataplot import DataPlot
# -定义菜单ID,关联Event-------------------------
"""
# 菜单 文件 -- 处理文件
设备 -- 序列 波长 测量
设置 -- 串口 光程 文件路径 绘图参数 采集设置
作图 -- 最后一条曲线 最后七条 指定位置七条
帮助
"""
ID_MEASURE = 1
ID_DEAL_FILE = 2
ID_DEVICE_SN = 3
ID_DEVICE_WL = 4
ID_DEVICE_LOG = 5
ID_COM_SETTING = 6
ID_PATH_SN = 7
ID_FILE_PATH = 8
ID_PLOT_SETTING = 9
ID_LOG_SETTING = 10
ID_DEVICE_STOP = 11
ID_PLOT_ONE = 15
ID_PLOT_SEVEN = 16
ID_PLOT_RULE = 17
ID_HELP = 21
ID_ABOUT = 22
class YiwinFrame( wx.Frame ):
'''将buf类传进来'''
def __init__(self, title, parent, size=(900, 750)):
self.device_id = 2
self.device_type = DeviceType.OSCAR.name
self.raw_wavelength = []
self.new_wavelength = []
self.device_wavelength = []
self.device_data = []
self.output_wavelength = []
self.output_wl_ndarray = np.array([])
self.syscfg = {}
self.sensor_cfg = {}
self.retrieve = {}
self.calinfo_is_ok = False
self.title = title
self.dir :Path = Path()
self.datadir :Path = self.dir.joinpath(DATA_DIR)
self.output_dir:Path = self.datadir.joinpath(OUTPUT_DIR)
self.save_fname :Path = Path()
self.result = ''
self.displayData:list = []
self.interval = 0
self.measure_time = time.strftime("%Y-%m-%d %H:%M:%S",time.localtime())
super(YiwinFrame, self).__init__( parent, title=self.title, size = size )
self.BoxSizer = wx.BoxSizer(wx.HORIZONTAL) # 建立一个Boxsizer
self.SetSizer(self.BoxSizer)
self.Centre(wx.BOTH)
# 建立 listctrl panel 放到BoxSizer
self.listctrl_panel = Listctrl( self ) # 调用自己建立的 Listctrl panel 类
self.BoxSizer.Add( self.listctrl_panel, proportion =-10, border = 2, flag = wx.ALL | wx.EXPAND)
self.list_ctrl = self.listctrl_panel.list_ctrl
# 隐藏 等待show
self.listctrl_panel.Hide()
self.plotpanel = Plot( self ) # 调用自己建立的 Listctrl panel 类
self.BoxSizer.Add( self.plotpanel, proportion =-10, border = 0, flag = wx.ALL | wx.EXPAND)
# self.static_text = self.plotpanel.staticText1
# 隐藏 等待show
self.plotpanel.Show()
self.statusBar = self.CreateStatusBar() # 创建状态栏
self.statusBar.SetFieldsCount(2) # 状态栏分成3个区域
self.statusBar.SetStatusWidths([-1, -1]) # 区域宽度比列,用负数
self.statusBar.SetStatusText(u" 等待接收消息......", 0)
self.__set_menu() # 添加菜单
self.__attach_events() # 菜单事件
self.__set_properties()
# self.__read_config()
self.__setTimer()
log.info(f"system init....",__name__, "__init__")
self.mycfg = MyConfig()
self.mydir = MyDir()
self.mycfg.set_retrieve()
self.__read_config()
self.ui_sn = self.syscfg['device']['UISN']
self.device_sn = ''
self.file_sn = ''
self.interval = self.syscfg['logsetting']['LogInterval']
self.port = self.syscfg['comsetting']['port']
self.uart = Uart()
self.oscar = Oscar()
self.dataplot = DataPlot()
self.plot_pure_water()
pub.subscribe( self.updateDisplay, "update")
pass
def __set_menu(self):
'''
# 设置菜单
'''
self.menubar = wx.MenuBar()
fileMenu = wx.Menu()
fileMenu.Append(ID_DEAL_FILE, u'&处理文件', '...')
self.menubar.Append(fileMenu, u'&文件 ')
deviceMenu = wx.Menu()
deviceMenu.Append(ID_DEVICE_SN, u'&序列号', '...')
deviceMenu.AppendSeparator()
deviceMenu.Append(ID_DEVICE_WL, u'&波长', '...')
deviceMenu.AppendSeparator()
deviceMenu.Append(ID_DEVICE_LOG, u'&采集数据', '...')
deviceMenu.AppendSeparator()
deviceMenu.Append(ID_DEVICE_STOP, u'&停止采集', '...')
self.menubar.Append(deviceMenu, u'&设备 ')
settingMenu = wx.Menu()
settingMenu.Append(ID_COM_SETTING, u'&串口设置', '...')
settingMenu.AppendSeparator()
settingMenu.Append(ID_PATH_SN, u'&序列号', ' ')
settingMenu.AppendSeparator()
settingMenu.Append(ID_FILE_PATH, u'&文件路径', ' ')
settingMenu.AppendSeparator()
settingMenu.Append(ID_PLOT_SETTING, u'&绘图设置', ' ')
settingMenu.AppendSeparator()
settingMenu.Append(ID_LOG_SETTING, u'&采集设置', ' ')
self.menubar.Append(settingMenu, u'&系统设置')
plotMenu = wx.Menu()
plotMenu.Append( ID_PLOT_ONE, u'&最后一条', '...' )
plotMenu.AppendSeparator()
plotMenu.Append( ID_PLOT_SEVEN, u'&最后七条', '...' )
plotMenu.AppendSeparator()
plotMenu.Append( ID_PLOT_RULE, u'&指定七条', '...' )
self.menubar.Append(plotMenu, u'&绘图 ')
aboutMenu = wx.Menu()
aboutMenu.Append( ID_HELP, u'&帮助', 'help...' )
aboutMenu.AppendSeparator()
aboutMenu.Append( ID_ABOUT, u'&关于我们', '关于我们...' )
self.menubar.Append( aboutMenu, u'&帮助')
self.SetMenuBar(self.menubar)
pass
def __set_properties(self):
self.SetSize((800, 600))
# self.SetTitle(u'传感器数据采集--上海奕枫仪器设备有限公司')
self.Centre()
def __attach_events(self):
'''
# 绑定菜单事件
'''
self.Bind(wx.EVT_MENU, self.OnDealFile, id = ID_DEAL_FILE)
self.Bind(wx.EVT_MENU, self.OnDeviceSN, id = ID_DEVICE_SN)
self.Bind(wx.EVT_MENU, self.OnDeviceWL, id = ID_DEVICE_WL)
self.Bind(wx.EVT_MENU, self.OnDeviceLog, id = ID_DEVICE_LOG)
self.Bind(wx.EVT_MENU, self.OnDeviceStop, id = ID_DEVICE_STOP)
self.Bind(wx.EVT_MENU, self.OnComSetting, id = ID_COM_SETTING)
self.Bind(wx.EVT_MENU, self.OnPathSNSetting, id = ID_PATH_SN)
self.Bind(wx.EVT_MENU, self.OnFilePathSetting, id = ID_FILE_PATH)
self.Bind(wx.EVT_MENU, self.OnPlotSetting, id = ID_PLOT_SETTING)
self.Bind(wx.EVT_MENU, self.OnLogSetting, id = ID_LOG_SETTING)
self.Bind(wx.EVT_MENU, self.OnPlotOne, id = ID_PLOT_ONE)
self.Bind(wx.EVT_MENU, self.OnPlotSeven, id = ID_PLOT_SEVEN)
self.Bind(wx.EVT_MENU, self.OnPlotRule, id = ID_PLOT_RULE)
self.Bind(wx.EVT_MENU, self.OnHelpConfig, id = ID_HELP)
self.Bind(wx.EVT_MENU, self.OnAboutConfig, id = ID_ABOUT)
pass
def __setTimer(self):
self.timer = wx.Timer(self) #创建定时器,菜单以后
self.Bind(wx.EVT_TIMER, self.OnTimer, self.timer) #绑定一个定时器事件
pass
def updateDisplay(self,msg):
log.debug(f" updateDisplay 。。 {msg['data']}")
if msg['type'] == "notice":
self.__update_notice(msg['data'])
pass
if msg['type'] == "sn":
self.__update_sn(msg['data'])
pass
if msg['type'] == "wl":
self.__update_wl(msg['data'])
pass
if msg['type'] == "log":
self.__update_log(msg['data'] )
print(f" ...log update ...{msg['data']} " )
pass
if msg['type'] == "data":
# log.info(f" ... update .{msg['data']}........... " )
self.__update_data(msg['data'])
pass
pass
def __update_sn(self,sn):
if sn != self.ui_sn:
self.alterStatus_0(f" sn: {sn} 与系统sn {self.ui_sn} 一致")
self.popDialog(f" sn: {sn} 与系统sn {self.ui_sn} 一致")
raise MyException(f" sn: {sn} 与系统sn {self.ui_sn} 一致")
else:
self.alterStatus_0(f" sn: {sn} 与系统sn {self.ui_sn} 不一致")
pass
def __update_notice(self,msg):
log.debug(f" msg : {msg}")
self.alterStatus_0(msg)
pass
def __update_wl(self,wl):
log.debug(f" 获得的波长成功 : {wl}")
self.output_wavelength = wl
self.alterStatus_0( f" 获得的波长成功 " )
pass
def __update_log(self,d):
log.info(f" 获得的数据 {d}")
self.alterStatus_0( d)
def __update_data( self, d ):
'''对于文件过来的数据'''
log.debug(f" ", __name__," __update_data")
self.plotpanel.clear_past()
self.plotpanel.set_title_x_y( *self.plotpanel.measure_legend )
self.plotpanel.plot_one(
d['time']
,np.array(self.oscar.output_wavelength)
,np.array(d['data'])
)
pass
def OnStart( self, event ):
log.info( f" OnStart....interval: { self.interval } minutes, port: { self.port} " )
interval_ms = int(self.interval) * 60 * 1000
self.timer.Start( interval_ms ) # 开始监测
def OnStop( self ,event ):
self.timer.Stop()
pass
def OnTimer(self, event):
''' 定时器实现 '''
# log.info( f"OnTimer .... " )
self.__OnDeviceLog( )
pass
def __read_config(self,):
# 读取配置文件
self.syscfg = self.mycfg.read_yaml()
retrieve = self.mycfg.read_rtv_yaml()
self.syscfg.update( { "retrieve" : retrieve } )
def OnDealFile(self, e)-> None:
self.__OnDeviceStop()
log.info( f"OnDealFile: 处理测量文件", __name__, "", "" )
# 线程守护
self.mt = Mythead()
self.oscar.set_cfg(self.syscfg)
try:
self.oscar.get_data_files()
self.mt.set_task( self.oscar.deal_file_lst )
self.mt.start()
self.alterStatus_0(" 处理完所有文件" )
except Exception as e:
self.alterStatus_0(e )
self.popDialog( e )
pass
def OnDeviceSN(self, e)-> None:
self.__OnDeviceStop()
log.info(f"OnDeviceSN: 获取device sn ", __name__, "", "")
# self.mt = Mythead()
self.oscar.set_cfg(self.syscfg)
self.oscar.set_serial()
# self.oscar.set_modbus(self.syscfg['register']['SNAddress'], self.syscfg['register']['SNLen'])
try:
self.oscar.sn_uart_thread( self.get_device_sn )
except Exception as e:
self.alterStatus_0(e )
self.popDialog( e )
self.alterStatus_0(" SN 匹配一致" )
pass
def get_device_sn(self,sn):
self.device_sn = sn
if self.device_sn != self.ui_sn:
log.error( f" 设备SN {self.device_sn} 与系统设置 {self.ui_sn}不一致 错误 " )
pass
else:
log.info(" sn 匹配成功 ! ")
pass
def OnDeviceWL(self, e)-> None:
self.__OnDeviceStop()
log.info(f"OnDeviceWL: 获得device wavelength ... ", __name__, "", "")
if self.device_sn != '':
self.oscar.set_cfg( self.syscfg )
self.oscar.set_serial()
try:
self.oscar.wl_uart_thread( self.get_device_wl )
except Exception as e:
self.alterStatus_0(e )
self.popDialog( e )
self.alterStatus_0(" 获取波长成功!" )
else:
self.popDialog('请获取设备序列号SN信息再试')
pass
def get_device_wl(self, wl_buf):
if len(wl_buf) != 0:
self.output_wavelength = wl_buf
self.output_wl_ndarray = np.array(self.output_wavelength)
else:
log.error( " 获取设备波长出错 " )
raise MyException( " 获取设备波长出错 " )
pass
def OnDeviceLog(self, e)-> None:
self.__OnDeviceStop()
log.info( f"OnDeviceLog: 采集数据 定时器采集", __name__, "", "" )
# !!!! 判断是否有波长和sn
if self.output_wavelength == []:
self.alterStatus_0( " 没有设备波长信息,请获取设备波长")
self.popDialog( " 没有设备波长信息,请获取设备波长")
raise MyException(" 没有设备波长信息,请获取设备波长")
self.__OnDeviceLog()
# 如何整点获取,如何快速获取
self.timer.Start( int(self.interval) * 60 * 1000 )
pass
def __OnDeviceLog(self,)-> None:
self.device_data = b''
self.mt = Mythead()
self.oscar.set_cfg( self.syscfg )
self.oscar.set_serial()
try:
self.oscar.log_uart_thread( self.get_device_data )
except Exception as e:
print(e)
self.alterStatus_0(e )
self.popDialog( e )
pass
def get_device_data( self,tm, data_buf ):
if len(data_buf) != 0:
self.device_data = self.oscar.convert_buf_2_float( data_buf ,8 )
self.plotpanel.clear_past()
self.plotpanel.set_title_x_y( *self.plotpanel.measure_legend )
self.plotpanel.plot_one(
tm
, self.output_wl_ndarray
,np.array(data_buf)
)
else:
log.error( " 采集设备数据出错 " )
raise MyException(" 采集设备数据出错 ")
pass
def OnDeviceStop(self, e)-> None:
self.__OnDeviceStop()
pass
def __OnDeviceStop(self, )-> None:
if self.timer.IsRunning():
self.timer.Stop()
pass
def plot_pure_water(self,):
# self.dataplot.set_file_path()
self.__OnDeviceStop()
self.plotpanel.set_title_x_y( *self.plotpanel.purewater_legend )
time_ = time.strftime("%Y-%m-%d %H:%M:%S",time.localtime())
wl = np.array(self.oscar.purewater_wavelength)
att = np.array(self.oscar.purewater_attenuation)
self.plotpanel.plot_one(time_, wl, att)
pass
def OnPlotOne(self,e):
self.__OnDeviceStop()
self.plotpanel.set_title_x_y( *self.plotpanel.measure_legend )
self.dataplot.set_file_path( self.output_dir.joinpath(self.ui_sn+SAVE_EXT_NAME) )
self.dataplot.set_token(TOKEN)
# !! 判断波长,获得波长
wavelength:str = self.dataplot.get_first_line().strip('\n').strip('\r')
self.output_wavelength = wavelength.split(TOKEN)[1:]
self.output_wl_ndarray = np.array(self.output_wavelength).astype(np.float64)
line = self.dataplot.get_multi_by_x_m_n(1,1,1)
line = line[0].strip('\n').strip('\r').split(TOKEN)
tm = line[0]
line = np.array(line[1:]).astype(np.float64)
self.plotpanel.axes.clear()
self.plotpanel.plot_one( tm, self.output_wl_ndarray, line )
self.alterStatus_0( f" plot {tm}")
pass
def OnPlotSeven(self,e):
self.__OnDeviceStop()
self.plotpanel.set_title_x_y( *self.plotpanel.measure_legend )
times = []
lines = []
log.debug( f'+++ ',__name__, 'OnPlotSeven' )
self.dataplot.set_file_path( self.output_dir.joinpath( self.ui_sn+SAVE_EXT_NAME ) )
self.dataplot.set_token(TOKEN)
# !! 判断波长,获得波长
wavelength:str = self.dataplot.get_first_line().strip('\n').strip('\r')
self.output_wavelength = wavelength.split(TOKEN)[1:]
self.output_wl_ndarray = np.array(self.output_wavelength).astype(np.float64)
line_7 = self.dataplot.get_multi_by_x_m_n(1,1,7)
# log.warning( f'+++ {line_7} ',__name__, 'OnPlotSeven' )
for line in line_7:
line = line.strip('\n').strip('\r').split(TOKEN)
tm = line[0]
line = np.array(line[1:]).astype(np.float64)
times.append(tm)
lines.append( line )
self.plotpanel.axes.clear()
self.plotpanel.plot_multi( times, self.output_wl_ndarray, lines )
self.alterStatus_0( f" plot 7 ")
pass
def OnPlotRule(self,e):
self.__OnDeviceStop()
self.plotpanel.set_title_x_y( *self.plotpanel.measure_legend )
times = []
lines = []
log.debug( f'+++ ',__name__, 'OnPlotSeven' )
self.dataplot.set_file_path( self.output_dir.joinpath( self.ui_sn+SAVE_EXT_NAME ) )
self.dataplot.set_token(TOKEN)
# !! 判断波长,获得波长
wavelength:str = self.dataplot.get_first_line().strip('\n').strip('\r')
self.output_wavelength = wavelength.split(TOKEN)[1:]
self.output_wl_ndarray = np.array(self.output_wavelength).astype(np.float64)
line_7 = self.dataplot.get_multi_by_x_m_n(1,1,7)
# log.warning( f'+++ {line_7} ',__name__, 'OnPlotSeven' )
for line in line_7:
line = line.strip('\n').strip('\r').split(TOKEN)
tm = line[0]
line = np.array(line[1:]).astype(np.float64)
times.append( tm )
lines.append( line )
self.plotpanel.axes.clear()
self.plotpanel.plot_multi( times, self.output_wl_ndarray, lines )
self.alterStatus_0( f" plot designated ")
pass
def OnComSetting(self,e):
with UI_Com_Setting(
self,
-1 ) as Dialog_Sensor_Setting:
Dialog_Sensor_Setting.CenterOnParent()
resultLog = Dialog_Sensor_Setting.ShowModal()
if resultLog == wx.ID_OK:
log.info( " COM config dialog confirm, call back " )
self.__read_config()
pass
def OnPathSNSetting(self,e):
with UI_PathSN_Setting(
self,
-1 ) as Dialog_Sensor_Setting:
Dialog_Sensor_Setting.CenterOnParent()
resultLog = Dialog_Sensor_Setting.ShowModal()
if resultLog == wx.ID_OK:
log.info( " PathSN config dialog confirm, call back " )
self.__read_config()
pass
def OnFilePathSetting(self,e):
with UI_Filepath_Setting(
self,
-1 ) as Dialog_Sensor_Setting:
Dialog_Sensor_Setting.CenterOnParent()
resultLog = Dialog_Sensor_Setting.ShowModal()
if resultLog == wx.ID_OK:
log.info( " FilePath config dialog confirm, call back " )
self.__read_config()
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 OnLogSetting(self,e):
with UI_Log_Setting(
self,
-1 ) as Dialog_Sensor_Setting:
Dialog_Sensor_Setting.CenterOnParent()
resultLog = Dialog_Sensor_Setting.ShowModal()
if resultLog == wx.ID_OK:
log.info( " Log config dialog confirm, call back " )
self.__read_config()
pass
def OnHelpConfig(self, e):
with Help(
self,
-1,
"") as Dialog_Help:
resultLog = Dialog_Help.ShowModal()
if resultLog == wx.ID_OK:
log.info("Help info")
pass
def OnAboutConfig(self, e):
with About(
self,
-1,
"") as Dialog_About:
resultLog = Dialog_About.ShowModal()
if resultLog == wx.ID_OK:
log.info("Aboutus")
pass
def OnOther(self, e):
pass
def OnQuit(self, e):
self.Close()
def alterStatus_0(self,msg):
self.statusBar.SetStatusText( msg, 0 )
def popDialog(self, msg, msg_type=u"错误提示"):
with wx.MessageDialog( self, msg, msg_type, wx.OK )as dlg:
dlg.ShowModal()
# 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
# def __get_data_files(self,) -> list:
# # 读取配置文件
# file_lst = []
# self.mydir.setBaseDir( Path(self.datadir) )
# file_lst = self.mydir.get_files_from_currentdir(fmt= "*/*.DAT")
# return file_lst
# def __check_sn_from_datafile(self,fpath) -> bool:
# # 读取配置文件
# sn = ReadCal.readFileSNbyIDDevice(fpath)
# if sn == self.ui_sn:
# return True
# return False
# def __get_raw_wl_from_datafile(self,fpath) -> list:
# # 读取配置文件
# _,raw_wl = ReadCal.read_columns_set_by_mark(fpath, FILE_MARK,0)
# return raw_wl
# def __deal_file_lst(self,file_lst):
# for fl in file_lst:
# # 判断序列号是否一致file_lst
# if not self.__check_sn_from_datafile(fl):
# self.onNotify("文件的序列号和系统设置不一致" )
# self.popDialog(" 文件的序列号和系统设置不一致")
# raise MyException("文件的序列号和系统设置不一致")
# # 判断原始波长是否为空
# if self.raw_wavelength == []:
# res = self.__get_raw_wl_from_datafile(file_lst[0])
# self.raw_wavelength = res[0]
# # 处理输出文件
# self.mydir.setBaseDir(self.output_dir)
# self.mydir.newDirIfNot()
# self.mydir.newFileIfNot(self.ui_sn+SAVE_EXT_NAME)
# if self.syscfg['retrieve']['enable'] == 0:
# self.mydir.setHeader(self.raw_wavelength,TOKEN,self.ui_sn)
# if self.mydir.checkHeader()==0:
# self.mydir.writeHeader()
# if self.mydir.checkHeader()==-1:
# self.popDialog(" 文件头不一致, 请备份到其他目录,并在该目录下删除")
# raise MyException(" 文件头不一致, 请备份到其他目录,并在该目录下删除")
# res_time,res_data = ReadCal.read_columns_sets_by_mark( fl, FILE_MARK, 1 )
# for i in range( len(res_time) ):
# self.__deal_one_measure_time_data(res_time[i], res_data[i])
# pass
# pass
# # 需要插值处理波长
# if self.syscfg['retrieve']['enable'] == 1:
# self.mydir.setHeader(self.new_wavelength.tolist(),TOKEN,self.ui_sn)
# if self.mydir.checkHeader()==0:
# self.mydir.writeHeader()
# if self.mydir.checkHeader()==-1:
# self.popDialog(" 文件头不一致, 请备份到其他目录,并在该目录下删除")
# raise MyException(" 文件头不一致, 请备份到其他目录,并在该目录下删除")
# # res_data 不用带回调的函数callback 会导致多组数据拼接??
# res_time,res_data = ReadCal.read_columns_sets_by_mark( fl, FILE_MARK, 1 )
# log.warning(f" ==== {len(res_time)}" )
# log.warning(res_time)
# log.warning(f" ==== {len(res_data[0])}" )
# log.warning(f" ==== { res_data[0] }" )
# for i in range( len(res_time) ):
# self.__deal_one_measure_time_data(res_time[i], res_data[0][i])
# pass
# pass
# def __deal_one_measure_time_data(self,res_time,res_data):
# if self.syscfg['retrieve']['enable'] == 0:
# self.mydir.setContent(res_data ,TOKEN,res_time )
# self.mydir.writeContent()
# # 插值处理
# if self.syscfg['retrieve']['enable'] == 1:
# # tmp_data = np.interp( self.new_wavelength, np.array(self.raw_wavelength) , np.array(res_data) )
# x = self.new_wavelength
# xp = np.array(self.raw_wavelength).astype(np.float32)
# fp = np.array(res_data).astype(np.float32)
# log.warning(f" {x}")
# log.warning(f" {xp.shape }")
# log.warning(f" { fp.shape }")
# tmp_data = np.interp( x, xp , fp )
# # tmp_data = np.interp( self.new_wavelength.tolist(), self.raw_wavelength , res_data[0] )
# self.mydir.setContent( tmp_data ,TOKEN, res_time )
# self.mydir.writeContent()
# pass
# def __deal_one_file(self,fpath):
# res_time,res_data = ReadCal.read_columns_sets_by_mark( fpath, FILE_MARK, 1 )
# for i in range( len(res_time) ):
# if self.syscfg['retrieve']['enable'] == 0:
# self.mydir.setContent(res_data[i],TOKEN,res_time[i])
# self.mydir.writeContent()
# # 插值处理
# if self.syscfg['retrieve']['enable'] == 1:
# self.mydir.setContent(res_data[i],TOKEN,res_time[i])
# self.mydir.writeContent()
# pass
# pass
# def __set_serial(self, )-> None:
# self.uart.set_serial_para(
# self.syscfg['comsetting']['port']
# ,self.syscfg['comsetting']['baudrate']
# ,self.syscfg['comsetting']['bytesize']
# ,self.syscfg['comsetting']['parity']
# ,self.syscfg['comsetting']['stopbit']
# )
# def __set_modbus(self, beginaddress, step)-> None:
# self.uart.set_modbus(
# self.syscfg['register']['slaveadress']
# ,self.syscfg['register']['functioncode']
# ,beginaddress
# ,step
# )
Loading…
Cancel
Save