Commit 66b1f69b authored by Mario Hock's avatar Mario Hock

subplots

plots multiple files into one image, arguments can be given per subplot
parent dae310cd
......@@ -12,6 +12,7 @@
import matplotlib
import matplotlib.pyplot as plt
import os
import copy
from cnl_library import CNLParser, calc_ema, merge_lists, pretty_json, get_common_base_time
import cnl_plot
......@@ -71,13 +72,13 @@ def set_tick_labels( ax, x_minutes=True, adapt_net_yticks=True ):
#
def plot_net(ax, cnl_file, args):
# parameters
legend_outside = False
legend_outside = False # TODO make no legend and legend outside possible
alpha = args.opacity if args.transparent_net else 1.0
smooth = args.smooth_net
# axes
ax.set_ylim(top=args.net_scale)
#ax.set_ylabel('Throughput (Bit/s)', fontsize=layout.fontsize.axis_labels)
#ax.set_ylabel('Throughput (Bit/s)', fontsize=layout.fontsize.axis_labels) ## TODO make fontsize choosable
ax.set_ylabel('Throughput (Bit/s)')
ax.set_xlabel('Time (s)')
......@@ -85,17 +86,18 @@ def plot_net(ax, cnl_file, args):
color=args.color, ema_only=True if smooth else False, smooth=smooth)
# Legend
if ( legend_outside ):
offset = matplotlib.transforms.ScaledTranslation(0, -20, matplotlib.transforms.IdentityTransform())
trans = ax.transAxes + offset
l = ax.legend( loc='upper left', bbox_to_anchor=(0, 0), ncol=int(len(cnl_file.net_col_names)/2),
bbox_transform = trans,
fancybox=False, shadow=False#,
#fontsize=layout.fontsize.legend
)
else:
l = ax.legend(loc=args.legend_pos)
if ( args.legend_pos != None ):
if ( legend_outside ):
offset = matplotlib.transforms.ScaledTranslation(0, -20, matplotlib.transforms.IdentityTransform())
trans = ax.transAxes + offset
l = ax.legend( loc='upper left', bbox_to_anchor=(0, 0), ncol=int(len(cnl_file.net_col_names)/2),
bbox_transform = trans,
fancybox=False, shadow=False#,
#fontsize=layout.fontsize.legend
)
else:
l = ax.legend(loc=args.legend_pos)
ax.set_xlim(xmin=args.x_min)
......@@ -103,29 +105,68 @@ def plot_net(ax, cnl_file, args):
def plot(cnl_file, args):
def plot(subplot_args, common_base_time=0):
fig, ax = plt.subplots()
plot_net(ax, cnl_file, args)
for args in subplot_args:
nics, nic_fields = net_fields_to_plot(args)
## Plot all files (with a common base time)
#
for filename in args.files:
cnl_file = cnl_plot.parse_cnl_file(filename, nic_fields, nics)
## show some output
print( filename )
#print( pretty_json(cnl_file.get_general_header()) )
#print()
prepare_x_values(cnl_file)
cnl_file.x_values = [ x - common_base_time for x in cnl_file.x_values ]
## * Plot *
plot_net(ax, cnl_file, args)
## Format tick labels
set_tick_labels(ax, False, True)
## output ##
args = subplot_args[0]
# Show / hardcopy plot
if ( args.output == "live" ):
#plt.title(filename)
plt.show()
else:
## output-filename is given explicitly
if ( args.output_filename ):
filename = args.output_filename
## otherwise, the original filename is used (with adapted filename extension)
else:
filename = args.files[0]
## if output_dir is given, strip the original path from the filename (if there is any)
if ( args.output_dir ):
os.makedirs(args.output_dir, exist_ok=True)
out_filename = args.output_dir + "/" + os.path.basename(filename) #+ "." + args.output
else:
out_filename = filename #+ "." + args.output
## replace filename extension to the output format
out_filename = os.path.splitext(out_filename)[0] + "." + args.output
## * save file *
plt.savefig(out_filename, format=args.output)
print(out_filename)
......@@ -134,11 +175,37 @@ def plot(cnl_file, args):
def merge_args(sub_args, args):
"""
merges [sub_args] over [args] into [merged_args]:
For every element that exist in both, the one from [sub_args] is used
"""
merged_args = copy.copy(args)
merged_args.subplots = None
merged_args_dict = merged_args.__dict__
sub_args_dict = sub_args.__dict__
for key in sub_args_dict:
#print( key, sub_args_dict[key] )
if ( sub_args_dict[key] != None ):
merged_args_dict[key] = sub_args_dict[key]
return merged_args
## MAIN ##
if __name__ == "__main__":
## Command line arguments
### Command line arguments
import argparse
import shlex
## NOTE: most args are copied from cnl_plot
......@@ -148,78 +215,115 @@ if __name__ == "__main__":
DEFAULT_X_MIN = -5.0
DEFAULT_X_MAX = None
parser = argparse.ArgumentParser()
# NOTE: currently only one file is supported...
parser.add_argument("files", nargs='+')
parser.add_argument("-ref", "--reference-files", nargs='+', default=list(),
help="These files will be used to find a common base time, but will no be plotted.")
## These arguments can be given within a "--subplots"-argument as well as when "--subplots" isn't used at all
def add_subplot_args(parser):
## NOTE: The merging algorithm could get confused, if arguments with default-values are put in here!
# (Maybe "nargs='?'" can be used in this case...)
parser.add_argument("files", nargs='*')
#parser.add_argument("files")
## make it pretty
parser.add_argument("-s", "--send-only", action="store_true")
parser.add_argument("-r", "--receive-only", action="store_true")
parser.add_argument("--nics", nargs='*')
parser.add_argument("-nl", "--nic-labels", nargs='*')
parser.add_argument("-c", "--color", type=str, nargs='*',
help="see: http://matplotlib.org/api/colors_api.html")
## These arguments can't be given within "--subplots"
def add_unique_args(parser):
parser.add_argument("-ref", "--reference-files", nargs='+', default=list(),
help="These files will be used to find a common base time, but will not be plotted.")
parser.add_argument("-nsc", "--net-scale", type=float, default=DEFAULT_Y_RANGE,
help="[Gbit/s]; Default: 10")
parser.add_argument("--opacity", type=float, default=DEFAULT_OPACITY,
help="Default: 0.7")
parser.add_argument("-tn", "--transparent-net", action="store_true")
## TODO smoothing could be interesting for individual subplots, too..
parser.add_argument("-sn", "--smooth-net", nargs='?', const=DEFAULT_ALPHA, type=float,
metavar="ALPHA",
help = "Smooth transmission rates with exponential moving average. (Disabled by default. When specified without parameter: ALPHA=0.1)" )
parser.add_argument("-o", "--output", default = "live",
help="Set output type. Choices: live, pdf, Default: live")
parser.add_argument("-nsc", "--net-scale", type=float, default=DEFAULT_Y_RANGE,
help="[Gbit/s]; Default: 10")
parser.add_argument("--opacity", type=float, default=DEFAULT_OPACITY,
help="Default: 0.7")
parser.add_argument("-tn", "--transparent-net", action="store_true")
parser.add_argument("-sn", "--smooth-net", nargs='?', const=DEFAULT_ALPHA, type=float,
metavar="ALPHA",
help = "Smooth transmission rates with exponential moving average. (Disabled by default. When specified without parameter: ALPHA=0.1)" )
parser.add_argument("-of", "--output-filename",
help="Sets the filename of output explicitly (helpful when subplots are used).")
parser.add_argument("-o", "--output", default = "live",
help="Set output type. Choices: live, pdf, Default: live")
parser.add_argument("-d", "--output-dir")
parser.add_argument("-d", "--output-dir")
## make it pretty
parser.add_argument("--x-min", type=float, default=DEFAULT_X_MIN)
parser.add_argument("--x-max", type=float, default=DEFAULT_X_MAX)
## make it pretty
parser.add_argument("-s", "--send-only", action="store_true")
parser.add_argument("-r", "--receive-only", action="store_true")
parser.add_argument("--nics", nargs='*')
parser.add_argument("-nl", "--nic-labels", nargs='*')
parser.add_argument("-l", "--legend-pos", type=int,
help="see: http://matplotlib.org/api/pyplot_api.html#matplotlib.pyplot.legend")
parser.add_argument("--x-min", type=float, default=DEFAULT_X_MIN)
parser.add_argument("--x-max", type=float, default=DEFAULT_X_MAX)
parser.add_argument("-l", "--legend-pos", type=int, default=0,
help="see: http://matplotlib.org/api/pyplot_api.html#matplotlib.pyplot.legend")
## subplots
parser.add_argument("-sub", "--subplots", type=str, nargs='*',
help="Use this if you want to draw multiple plots into the same image. (Arguments must not start with '-'.)")
parser.add_argument("-c", "--color", type=str, nargs='*',
help="see: http://matplotlib.org/api/colors_api.html")
# Create general parser
parser = argparse.ArgumentParser()
add_subplot_args(parser)
add_unique_args(parser)
args = parser.parse_args()
## process argiments
## adjust arguments
args.net_scale *= 10**9 # --> multiply by 10**9 to get Gbit/s
nics, nic_fields = net_fields_to_plot(args)
## Subplots: Read the arguments given as argument to "--subplots" and merge the result
subplot_args = list()
subplot_args.append(args)
### Preparations
reference = list(args.files)
reference.extend(args.reference_files)
common_base_time = get_common_base_time(reference)
if args.subplots:
# Create subplot parser
subplot_parser = argparse.ArgumentParser()
add_subplot_args(subplot_parser)
for subcmd in args.subplots:
sub_argv = shlex.split(subcmd)
sub_args = subplot_parser.parse_args(sub_argv)
merged_args = merge_args(sub_args, args)
subplot_args.append(merged_args)
# XXX debug
#print( sub_args )
#print()
#print( merged_args )
## Plot all files (with a common base time)
#
for filename in args.files:
cnl_file = cnl_plot.parse_cnl_file(filename, nic_fields, nics)
## show some output
print( filename )
print( pretty_json(cnl_file.get_general_header()) )
print()
prepare_x_values(cnl_file)
cnl_file.x_values = [ x - common_base_time for x in cnl_file.x_values ]
## Find common base time
reference = list()
reference.extend(args.reference_files)
for args in subplot_args:
reference.extend(args.files)
common_base_time = get_common_base_time(reference)
### Plotting
### Plotting
plot(subplot_args, common_base_time)
plot(cnl_file, args)
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment