ATLAS Offline Software
Loading...
Searching...
No Matches
perfmonmt-refit.py
Go to the documentation of this file.
1#!/usr/bin/env python3
2
3# Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
4
5import argparse
6import json
7import numpy
8import sys
9
10# Helper for range parsing
11def parse_range(string):
12 result = string.split(',')
13 if len(result) != 2 or not result[0].isnumeric() or not result[1].isnumeric() or int(result[0]) >= int(result[1]):
14 print(f"Invalid input range {string} (must be N,M w/ N/M as numbers and M>N)...")
15 sys.exit(1)
16 else:
17 return result
18
19# Main function
20if '__main__' in __name__:
21
22 # Parse the user input
23 parser = argparse.ArgumentParser(description = 'Script to re-fit PerfMonMTSvc measurements')
24
25 parser.add_argument('-i', '--input', type = str, required = True,
26 help = 'PerfMonMTSvc JSON file')
27 parser.add_argument('-r', '--range', type = parse_range, dest = 'range',
28 help = 'A comma comma-separated list that determines the '
29 'minimum and maximum event numbers over which one wants '
30 'to perform the fit (e.g. 10,100)')
31 parser.add_argument('-f', '--slice', type = float, dest = 'slice',
32 help = 'A (python) slice defining the event-range over '
33 'to which one wants to perform the fit from the end '
34 '(default: 0.8, i.e. last 80 percent of the events)')
35 parser.add_argument('-o', '--observable', dest = 'obs', nargs = '?', default = 'pss',
36 choices = ['vmem', 'rss', 'pss', 'swap', 'cpuTime', 'wallTime'],
37 help = 'Variable to fit')
38 parser.add_argument('-m', '--minimal', dest = 'minimal', action = 'store_true',
39 help = 'Prints only the result')
40 parser.add_argument('-d', '--debug', dest = 'debug', action = 'store_true',
41 help = 'Enables debug printouts')
42
43 args = parser.parse_args()
44
45 # Check the argument settings
46 # User needs to pick either a range or a slice
47 if args.range and args.slice:
48 print('Please specify either range or slice fitting - not both, quitting...')
49 sys.exit(1)
50 # If neither a slice nor a range provided, set a slice
51 if not args.range and not args.slice:
52 args.slice = 0.8
53 # The slice range should be >0. and <1.
54 if args.slice and (float(args.slice) > 1. or float(args.slice) < 0.):
55 print('Slice cannot be outside [0, 1], resetting to 1...')
56 args.slice = 1.
57
58 # Load the data, perform the fit, and print the requested information
59 with(open(args.input)) as json_file:
60
61 data = json.load(json_file)
62
63 # Check if data exist
64 if 'eventLevel' not in data or args.obs not in data['eventLevel']['1']:
65 print('Data do not contain the necessary information, please check'
66 ' the input file or the provided observable...')
67 sys.exit(1)
68
69 # Fill the arrays
70 x, y = [], []
71
72 for entry in sorted(data['eventLevel'], key=float):
73 x.append(entry)
74 y.append(data['eventLevel'][entry][args.obs])
75
76 # Find the units
77 units = 'ms/event' if 'time' in args.obs.lower() else 'kb/event'
78
79 # Find the indices over which the fit will be performed
80 if args.range:
81 if (args.range[0] not in x or args.range[1] not in x):
82 print(f"Provided range parameters {args.range} are not in data, will use slicing w/ 0.8...")
83 idx_min = round(0.2*len(x))
84 idx_max = len(x)-1
85 else:
86 idx_min = x.index(args.range[0])
87 idx_max = x.index(args.range[1])
88 else:
89 idx_min = round((1-args.slice)*len(x))
90 idx_max = len(x)-1
91
92 # Print some debug information if asked for
93 if args.debug:
94 print(f"DEBUG:: Inputs were {args.range} and {args.slice}")
95 print(f"DEBUG:: Original data has {len(x)} points:")
96 print(f"DEBUG:: >> x : {x}")
97 print(f"DEBUG:: >> y : {y}")
98 print(f"DEBUG:: Computed minimum and maximum indices are {idx_min} and {idx_max}, respectively")
99 print(f"DEBUG:: Sliced data has {len(x[idx_min:idx_max+1])} points:")
100 print(f"DEBUG:: >> x : {x[idx_min:idx_max+1]}")
101 print(f"DEBUG:: >> y : {y[idx_min:idx_max+1]}")
102
103 # Perform the fit
104 n_tot = len(x[idx_min:idx_max+1]) # Total number of points used in the fit
105 coeffs = numpy.lib.polyfit( numpy.array(x[idx_min:idx_max+1], numpy.float),
106 numpy.array(y[idx_min:idx_max+1], numpy.float) , deg = 1 )
107
108 # Print the final result
109 if not args.minimal:
110 print('='*70)
111 print(f" [ Begin - End ] : Slope of {args.obs} in {units} using {n_tot} points")
112 print('='*70)
113 print(f" [ {x[idx_min]:>5} - {x[idx_max]:>5} ] : {coeffs[0]:^.2f}")
114 print('='*70)
115 else:
116 print(f"{x[idx_min]},{x[idx_max]},{coeffs[0]:^.2f}")
void print(char *figname, TCanvas *c1)