123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100 |
- from datetime import datetime, timedelta
- import json
- from typing import Any, Dict, List, Tuple
- import numpy
- from labours.burndown import import_pandas
- from labours.plotting import apply_plot_style, deploy_plot, get_plot_path, import_pyplot
- from labours.utils import default_json, floor_datetime, parse_date
- def load_ownership(
- header: Tuple[int, int, int, int, float],
- sequence: List[Any],
- contents: Dict[Any, Any],
- max_people: int,
- order_by_time: bool,
- ):
- pandas = import_pandas()
- start, last, sampling, _, tick = header
- start = datetime.fromtimestamp(start)
- start = floor_datetime(start, tick)
- last = datetime.fromtimestamp(last)
- people = []
- for name in sequence:
- people.append(contents[name].sum(axis=1))
- people = numpy.array(people)
- date_range_sampling = pandas.date_range(
- start + timedelta(seconds=sampling * tick),
- periods=people[0].shape[0],
- freq="%dD" % sampling,
- )
- if people.shape[0] > max_people:
- chosen = numpy.argpartition(-numpy.sum(people, axis=1), max_people)
- others = people[chosen[max_people:]].sum(axis=0)
- people = people[chosen[: max_people + 1]]
- people[max_people] = others
- sequence = [sequence[i] for i in chosen[:max_people]] + ["others"]
- print("Warning: truncated people to the most owning %d" % max_people)
- if order_by_time:
- appearances = numpy.argmax(people > 0, axis=1)
- if people.shape[0] > max_people:
- appearances[-1] = people.shape[1]
- else:
- appearances = -people.sum(axis=1)
- if people.shape[0] > max_people:
- appearances[-1] = 0
- order = numpy.argsort(appearances)
- people = people[order]
- sequence = [sequence[i] for i in order]
- for i, name in enumerate(sequence):
- if len(name) > 40:
- sequence[i] = name[:37] + "..."
- return sequence, people, date_range_sampling, last
- def plot_ownership(args, repo, names, people, date_range, last):
- if args.output and args.output.endswith(".json"):
- data = locals().copy()
- del data["args"]
- data["type"] = "ownership"
- if args.mode == "all" and args.output:
- output = get_plot_path(args.output, "people")
- else:
- output = args.output
- with open(output, "w") as fout:
- json.dump(data, fout, sort_keys=True, default=default_json)
- return
- matplotlib, pyplot = import_pyplot(args.backend, args.style)
- polys = pyplot.stackplot(date_range, people, labels=names)
- if names[-1] == "others":
- polys[-1].set_hatch("/")
- pyplot.xlim(
- parse_date(args.start_date, date_range[0]), parse_date(args.end_date, last)
- )
- if args.relative:
- for i in range(people.shape[1]):
- people[:, i] /= people[:, i].sum()
- pyplot.ylim(0, 1)
- legend_loc = 3
- else:
- legend_loc = 2
- ncol = 1 if len(names) < 15 else 2
- legend = pyplot.legend(loc=legend_loc, fontsize=args.font_size, ncol=ncol)
- apply_plot_style(
- pyplot.gcf(), pyplot.gca(), legend, args.background, args.font_size, args.size
- )
- if args.mode == "all" and args.output:
- output = get_plot_path(args.output, "people")
- else:
- output = args.output
- deploy_plot("%s code ownership through time" % repo, output, args.background)
|