def _history_plot(title, dates, measurements, output): fig, ax = plt.subplots(figsize=(10, 5)) dates = [matplotlib.dates.date2num(d) for d in dates] if len(dates) > len(set(dates)): log.warning('Non-unique dates in history plot') locator = matplotlib.dates.AutoDateLocator() formatter = matplotlib.dates.AutoDateFormatter(locator) formatter.scaled[1 / 24] = '%y-%m-%d %H:%M' formatter.scaled[1 / (24 * 60)] = '%y-%m-%d %H:%M' formatter.scaled[1 / (24 * 60 * 60)] = '%y-%m-%d %H:%M:%S' ax.set_title(title) ax.xaxis.set_major_locator(locator) ax.xaxis.set_major_formatter(formatter) style = next(iter(plt.rcParams['axes.prop_cycle'])) ax.fill_between(dates, measurements.min, measurements.max, alpha=0.2, **style) ax.fill_between(dates, measurements.q1, measurements.q3, alpha=0.5, **style) ax.plot(dates, measurements.q2, '|-', **style) ax.set_ylim(bottom=0) ax.set_ylabel('Time [s]') fig.autofmt_xdate() fig.tight_layout() fig.savefig(output, dpi=300) log.debug(f'Successfully written history plot to {output}') plt.close(fig)
def _retreive_outputs(rundir, commands, task_id): command = [ 'sacct', '--jobs', f'{task_id}', '--format', 'jobid,exitcode', '--parsable2', '--noheader' ] for i in range(1, 7): try: output = run(command) except subprocess.CalledProcessError: time.sleep(1) continue infos = [o.split('|')[1] for o in output.splitlines() if '.batch' in o] if len(infos) > 1: raise RuntimeError(f'Unexpected sacct output: {output}') elif len(infos) == 1: exitcode = int(infos[0].split(':')[0]) if exitcode != 0: log.warning('Batch job finished with non-zero exitcode', exitcode) break time.sleep(i**2) else: raise RuntimeError('Could not get exit code of job') time.sleep(5) with open(_stderr_file(rundir), 'r') as outfile: stderr = outfile.read() log.debug('Raw job stderr', stderr) stderr = stderr.split('%RETURNCODE%\n')[:-1] stderr, exitcodes = zip(*(o.split('%PYUTILS%') for o in stderr)) exitcodes = [int(exitcode) for exitcode in exitcodes] with open(_stdout_file(rundir), 'r') as outfile: stdout = outfile.read() log.debug('Raw job stdout', stdout) stdout = stdout.split('%PYUTILS%\n')[:-1] return list(zip(exitcodes, stdout, stderr))
def history(results, key='job', limit=None): """Plots run time history of all results. Depending on the argument `job`, The results are either ordered by commit/build time or job time (i.e. when the job was run). Args: results: List of `result.Result` objects. key: Either 'job' or 'build'. limit: Optionally limits the number of plotted results to the given number, i.e. only displays the most recent results. If `None`, all given results are plotted. """ # get date/time either from the commit/build or job (when job was run) def get_datetime(result): if key == 'build': datetime = result.runinfo.datetime elif key == 'job': datetime = result.datetime else: raise ValueError('"key" argument must be "build" or "job"') return time.local_time(datetime) # sort results by desired reference time results = sorted(results, key=get_datetime) # if limit is not None: if not isinstance(limit, int) or limit <= 0: raise ValueError('"limit" must be a positive integer') results = results[-limit:] data = result.percentiles_by_stencil(results, [0, 25, 50, 75, 100]) dates = [matplotlib.dates.date2num(get_datetime(r)) for r in results] if len(dates) > len(set(dates)): log.warning('Non-unique datetimes in history plot') fig, ax = plt.subplots(figsize=figsize(2, 1)) locator = matplotlib.dates.AutoDateLocator() formatter = matplotlib.dates.AutoDateFormatter(locator) formatter.scaled[1 / 24] = '%y-%m-%d %H:%M' formatter.scaled[1 / (24 * 60)] = '%y-%m-%d %H:%M' formatter.scaled[1 / (24 * 60 * 60)] = '%y-%m-%d %H:%M:%S' ax.xaxis.set_major_locator(locator) ax.xaxis.set_major_formatter(formatter) colors = discrete_colors(len(data[0])) for color, stencil, mint, q1, q2, q3, maxt in zip(colors, *data): ax.fill_between(dates, mint, maxt, alpha=0.2, color=color) ax.fill_between(dates, q1, q3, alpha=0.5, color=color) ax.plot(dates, q2, '|-', label=stencil.title(), color=color) ax.legend(loc='upper left') fig.autofmt_xdate() fig.tight_layout() return fig