ownership.py 3.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. from datetime import datetime, timedelta
  2. import json
  3. import numpy
  4. from labours.burndown import import_pandas
  5. from labours.plotting import apply_plot_style, deploy_plot, get_plot_path, import_pyplot
  6. from labours.utils import default_json, floor_datetime, parse_date
  7. def load_ownership(header, sequence, contents, max_people, order_by_time):
  8. pandas = import_pandas()
  9. start, last, sampling, _, tick = header
  10. start = datetime.fromtimestamp(start)
  11. start = floor_datetime(start, tick)
  12. last = datetime.fromtimestamp(last)
  13. people = []
  14. for name in sequence:
  15. people.append(contents[name].sum(axis=1))
  16. people = numpy.array(people)
  17. date_range_sampling = pandas.date_range(
  18. start + timedelta(seconds=sampling * tick), periods=people[0].shape[0],
  19. freq="%dD" % sampling)
  20. if people.shape[0] > max_people:
  21. chosen = numpy.argpartition(-numpy.sum(people, axis=1), max_people)
  22. others = people[chosen[max_people:]].sum(axis=0)
  23. people = people[chosen[:max_people + 1]]
  24. people[max_people] = others
  25. sequence = [sequence[i] for i in chosen[:max_people]] + ["others"]
  26. print("Warning: truncated people to the most owning %d" % max_people)
  27. if order_by_time:
  28. appearances = numpy.argmax(people > 0, axis=1)
  29. if people.shape[0] > max_people:
  30. appearances[-1] = people.shape[1]
  31. else:
  32. appearances = -people.sum(axis=1)
  33. if people.shape[0] > max_people:
  34. appearances[-1] = 0
  35. order = numpy.argsort(appearances)
  36. people = people[order]
  37. sequence = [sequence[i] for i in order]
  38. for i, name in enumerate(sequence):
  39. if len(name) > 40:
  40. sequence[i] = name[:37] + "..."
  41. return sequence, people, date_range_sampling, last
  42. def plot_ownership(args, repo, names, people, date_range, last):
  43. if args.output and args.output.endswith(".json"):
  44. data = locals().copy()
  45. del data["args"]
  46. data["type"] = "ownership"
  47. if args.mode == "all" and args.output:
  48. output = get_plot_path(args.output, "people")
  49. else:
  50. output = args.output
  51. with open(output, "w") as fout:
  52. json.dump(data, fout, sort_keys=True, default=default_json)
  53. return
  54. matplotlib, pyplot = import_pyplot(args.backend, args.style)
  55. polys = pyplot.stackplot(date_range, people, labels=names)
  56. if names[-1] == "others":
  57. polys[-1].set_hatch("/")
  58. pyplot.xlim(parse_date(args.start_date, date_range[0]), parse_date(args.end_date, last))
  59. if args.relative:
  60. for i in range(people.shape[1]):
  61. people[:, i] /= people[:, i].sum()
  62. pyplot.ylim(0, 1)
  63. legend_loc = 3
  64. else:
  65. legend_loc = 2
  66. ncol = 1 if len(names) < 15 else 2
  67. legend = pyplot.legend(loc=legend_loc, fontsize=args.font_size, ncol=ncol)
  68. apply_plot_style(pyplot.gcf(), pyplot.gca(), legend, args.background,
  69. args.font_size, args.size)
  70. if args.mode == "all" and args.output:
  71. output = get_plot_path(args.output, "people")
  72. else:
  73. output = args.output
  74. deploy_plot("%s code ownership through time" % repo, output, args.background)