MerchantCumRatioPainter.py 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. from .DataStream import EMchPosmap as pos_map, span_days, time_border, calc_interval
  2. from .MerchantReader import MerchantReader
  3. from .MerchantPainter import MerchantPainter, allpathes
  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_mchratios, calc_morder_send
  9. import time as time
  10. import logging
  11. logger = logging.getLogger('MerchantCumRatioPainter')
  12. class MerchantCumRatioPainter(MerchantPainter):
  13. def __init__(self, start_time: int, end_time: int, mchids: set = None, card_types: set = None, spec: int = None, filter_wave: int = None):
  14. self._reader = MerchantReader()
  15. self._mchids, self._card_types, self._spec, self._filter_wave = mchids, card_types, spec, filter_wave
  16. self._days, self._start_time, self._end_time, self._interval = self.calc_time(self._reader, start_time, end_time)
  17. pass
  18. def _fig_funs(self):
  19. def create():
  20. fig = Figure(figsize=(19, 8))
  21. ax = fig.subplots()
  22. ax.set_title('success ratio')
  23. ax.set(xlabel='time', ylabel='ratio')
  24. return ax, fig
  25. def flush(ax, fig, xticks=None, xlables=None, yticks=None, ylables=None):
  26. ax.yaxis.set_major_formatter(ticker.PercentFormatter(xmax=1, decimals=4))
  27. if xticks is not None:
  28. ax.set_xticks(ticks=xticks)
  29. if xlables is not None:
  30. ax.set_xticklabels(xlables)
  31. if yticks is not None:
  32. ax.set_yticks(ticks=yticks)
  33. if ylables is not None:
  34. ax.set_yticklabels(ylables)
  35. fig.autofmt_xdate()
  36. ax.grid()
  37. fig.subplots_adjust(left=0.1, right=0.8, top=0.95, bottom=0.1)
  38. ax.legend(bbox_to_anchor=(1, 1), loc='upper left')
  39. buf = BytesIO()
  40. fig.savefig(buf, format="png")
  41. return buf
  42. return create, flush
  43. def paint(self):
  44. tuple_pathes = self._reader.many_tuple_path(self._days, self._mchids, self._card_types, self._spec)
  45. gen = allpathes(self._reader, tuple_pathes, self._days, self._spec)
  46. if len(self._days) == 0:
  47. return BytesIO()
  48. day_stamp = self._days[0]
  49. fig_create, fig_flush = self._fig_funs()
  50. ax, fig = fig_create()
  51. x = np.array([d - self._start_time for d in range(self._start_time, self._end_time)])
  52. if self._filter_wave is not None and self._filter_wave > 1:
  53. window = np.ones(self._filter_wave) / self._filter_wave
  54. else:
  55. window = None
  56. mchid_ratios = []
  57. for _mchid, _card_type, _spec, _data in gen:
  58. succ, count, y = calc_mchratios(_data, pos_map, self._start_time - day_stamp, self._end_time - day_stamp)
  59. y = np.convolve(y, window, 'same') if window is not None else y
  60. label, ratio = self._label(chname=_mchid, succ=succ, count=count, card_type=_card_type, spec=_spec)
  61. ax.plot(x, y, ls='-', label=label)
  62. if _card_type is None and _spec is None and type(_mchid) is int:
  63. mchid_ratios.append((_mchid, ratio))
  64. xticks = [d - self._start_time for d in range(self._start_time, self._end_time + 1, self._interval)]
  65. xlables = [time.strftime('%d-%H:%M:%S', time.localtime(d + self._start_time)) for d in xticks]
  66. buf = fig_flush(ax, fig, xticks=xticks, xlables=xlables)
  67. mchid_ratios = sorted(mchid_ratios, key=lambda x: (x[1], x[0]), reverse=True)
  68. result = []
  69. for mchid,ratio in mchid_ratios:
  70. result.append(f'{mchid}:{ratio}')
  71. return buf, result