ChannelPainter.py 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. from .DataStream import EChPosmap as pos_map, day_stamp, span_days, time_border, calc_interval
  2. from .ChannelReader import ChannelReader
  3. from collections import defaultdict
  4. from matplotlib.figure import Figure
  5. from matplotlib import ticker
  6. from io import BytesIO
  7. import numpy as np
  8. from .algorithm import calc_chratios
  9. import time as time
  10. import logging
  11. logger = logging.getLogger('painter')
  12. def allpathes(reader: ChannelReader, tuple_pathes: dict, days: list, spec=None):
  13. count = len(days)
  14. show_detail = True if len(list(tuple_pathes.keys())) == 1 else False
  15. if show_detail == False:
  16. all_datas = reader.init_data(count)
  17. else:
  18. all_datas = None
  19. for name, tup in tuple_pathes.items():
  20. ch_datas = reader.init_data(count)
  21. for _card_type, _spec in tup:
  22. if spec is not None and _spec != spec:
  23. continue
  24. if show_detail:
  25. detail_datas = reader.init_data(count)
  26. else:
  27. detail_datas = None
  28. for i, day in enumerate(days):
  29. data = reader.read(day, name, _card_type, _spec)
  30. if data is not None:
  31. column_pos = i * 86400
  32. view = ch_datas[:, column_pos:column_pos + 86400]
  33. view += data
  34. if show_detail:
  35. view = detail_datas[:, column_pos:column_pos + 86400]
  36. view += data
  37. if show_detail:
  38. yield name, _card_type, _spec, detail_datas
  39. if all_datas is not None:
  40. all_datas += ch_datas
  41. yield name, None, None, ch_datas
  42. if show_detail == False:
  43. yield 'all', None, None, all_datas
  44. class ChannelPainter(object):
  45. def __init__(self, start_time: int, end_time: int, chnames: set = None, card_types: set = None, spec: int = None):
  46. self._reader = ChannelReader()
  47. _start_time, _end_time, self._chnames, self._card_types, self._spec = start_time, end_time, chnames, card_types, spec
  48. start_time = self._reader.near_stamp(_start_time,True)
  49. end_time = self._reader.near_stamp(_end_time,False)
  50. stime = lambda t: time.strftime('%d-%H:%M:%S', time.localtime(t))
  51. logger.debug("start_time=%s end_time=%s",stime(start_time) ,stime(end_time))
  52. interval = calc_interval(start_time, end_time)
  53. start_time = time_border(interval, start_time, True)
  54. end_time = time_border(interval, end_time, False)
  55. self._days = span_days(start_time, end_time)
  56. self._start_time = start_time
  57. self._end_time = end_time
  58. self._interval = interval
  59. pass
  60. def _fig_funs(self):
  61. def create():
  62. fig = Figure(figsize=(19, 8))
  63. ax = fig.subplots()
  64. ax.set_title('success ratio')
  65. ax.set(xlabel='time', ylabel='ratio')
  66. return ax, fig
  67. def flush(ax, fig, ticks, lables):
  68. ax.yaxis.set_major_formatter(ticker.PercentFormatter(xmax=1, decimals=4))
  69. ax.set_xticks(ticks=ticks)
  70. ax.set_xticklabels(lables)
  71. fig.autofmt_xdate()
  72. ax.grid()
  73. fig.subplots_adjust(left=0.1, right=0.8, top=0.95, bottom=0.1)
  74. ax.legend(bbox_to_anchor=(1, 1), loc='upper left')
  75. buf = BytesIO()
  76. fig.savefig(buf, format="png")
  77. return buf
  78. return create, flush
  79. def paint(self):
  80. reader = ChannelReader()
  81. tuple_pathes = reader.many_tuple_path(self._days, self._chnames, self._card_types, self._spec)
  82. gen = allpathes(self._reader, tuple_pathes, self._days, self._spec)
  83. if len(self._days) == 0:
  84. return []
  85. day_stamp = self._days[0]
  86. fig_create, fig_flush = self._fig_funs()
  87. ax, fig = fig_create()
  88. x = np.array([d - self._start_time for d in range(self._start_time, self._end_time)])
  89. window = np.ones(10) / 10
  90. for _chname, _card_type, _spec, _data in gen:
  91. succ, count, y = calc_chratios(_data, pos_map, self._start_time - day_stamp, self._end_time - day_stamp)
  92. print(_chname)
  93. # y = np.convolve(y, window, 'same')
  94. ax.plot(x, y, ls='-', label=self._label(chname=_chname, succ=succ, count=count, card_type=_card_type, spec=_spec))
  95. ticks = [d - self._start_time for d in range(self._start_time, self._end_time + 1, self._interval)]
  96. xlables = [time.strftime('%d-%H:%M:%S', time.localtime(d + self._start_time)) for d in ticks]
  97. return fig_flush(ax, fig, ticks, xlables)
  98. def _label(self, chname, succ, count, card_type=None, spec=None):
  99. _card_type = None
  100. if card_type == 1:
  101. _card_type = 'SY'
  102. elif card_type == 2:
  103. _card_type = 'SH'
  104. elif card_type == 4:
  105. _card_type = 'YD'
  106. elif card_type == 5:
  107. _card_type = 'LT'
  108. elif card_type == 6:
  109. _card_type = 'DX'
  110. elif card_type == 7:
  111. _card_type = 'TH'
  112. lable = f"{chname}"
  113. if _card_type is not None:
  114. lable += f"-{_card_type}"
  115. if spec is not None:
  116. lable += f"-{spec}"
  117. if count > 0:
  118. ratio = round(succ * 100 / count, 2)
  119. else:
  120. ratio = 0.00
  121. lable += f":{ratio}%={succ}/{count}"
  122. return lable