I would like to pass optional arguments to a matplotlib script running from the command line.
I have the following:
import numpy as np import matplotlib.pyplot as plt import matplotlib matplotlib.use('Agg') import pandas as pd import argparse parser = argparse.ArgumentParser(description="Plot x,y data in python") parser.add_argument('-xF',"--x", type=str, metavar='', required=True, help="x-Data") parser.add_argument('-yF', "--y", type=str, metavar='', required=True, help="y-Data") parser.add_argument('-o', "--options", nargs="+", default=[], help="Options for plotting") args = parser.parse_args() def plot(x, y, xlabel, ylabel, name, legend=None, otherArgs=None): xData = pd.read_csv(x) yData = pd.read_csv(y) plt.figure() plt.plot(xData, yData, label=legend, *(otherArgs), zorder=1) plt.tight_layout() plt.savefig("tst.tiff") if __name__ == '__main__': plot(args.x, args.y, args.options)
However, currently I am not able to do so. Is there any way to pass under the optional arguments other parameters to the plot functions? Set colors, markers, etc.. ?
Best Regards
Advertisement
Answer
If you will run as
-o color=red marker=o
then you will get list
["color=red", "marker=o"]
and you can use split("=")
and dict()
args.options = dict(x.split('=') for x in args.options)
to get it as dictionary
{"color":"red", "marker":"o"}
And then you can use **
to put dictionary
plt.plot(..., **otherArgs)
and it will accept it as correct parameters.
Minimal working code:
For test I put argumenst directly in sys.argv
– so I can run it without writing parameters in console.
EDIT: it needs dictionary default={}
instead of default=[]
import numpy as np import matplotlib.pyplot as plt import matplotlib #matplotlib.use('Agg') import pandas as pd import argparse # --- functions --- def plot(x, y, xlabel='X', ylabel='Y', name='Name', legend=None, otherArgs=None): xData = [1,2,3] yData = [3,1,1] plt.figure() plt.plot(xData, yData, label=legend, **otherArgs, zorder=1) plt.tight_layout() #plt.savefig("tst.tiff") plt.show() # --- main --- if __name__ == '__main__': import sys sys.argv += ['--x', '1', '--y', '2', '-o', 'color=red', 'marker=o'] parser = argparse.ArgumentParser(description="Plot x,y data in python") parser.add_argument('-xF',"--x", type=str, metavar='', required=True, help="x-Data") parser.add_argument('-yF', "--y", type=str, metavar='', required=True, help="y-Data") parser.add_argument('-o', "--options", nargs="+", default={}, help="Options for plotting") # `default={}` instead of `default=[]` args = parser.parse_args() print('[args.options] before:', args.options) args.options = dict(x.split('=') for x in args.options) print('[args.options] after :', args.options) plot(args.x, args.y, otherArgs=args.options)
Console:
[args.options] before: ['color=green', 'marker=o'] [args.options] after : {'color': 'green', 'marker': 'o'}
EDIT:
I found also method to create own class based on argparse.Action
and later assign it to action
in add_param(..., action=...)
class keyvalue(argparse.Action): def __call__(self, parser, namespace, values, option_string): #print(parser) #print(values) #print(option_string) print('[namespace] before:', namespace) data = dict() for value in values: key, val = value.split('=') data[key] = val setattr(namespace, self.dest, data) print('[namespace] after :', namespace)
parser.add_argument('-o', "--options", nargs="+", default={}, action=keyvalue)
Full working code
import argparse import matplotlib.pyplot as plt #matplotlib.use('Agg') #import pandas as pd # --- functions --- def plot(x, y, xlabel='X', ylabel='Y', name='Name', legend=None, otherArgs=None): xData = [1,2,3] yData = [3,1,1] plt.figure() plt.plot(xData, yData, label=legend, **otherArgs, zorder=1) plt.tight_layout() #plt.savefig("tst.tiff") plt.show() class keyvalue(argparse.Action): def __call__(self, parser, namespace, values, option_string): #print(parser) #print(values) #print(option_string) print('[namespace] before:', namespace) data = dict() for value in values: key, val = value.split('=') data[key] = val setattr(namespace, self.dest, data) print('[namespace] after :', namespace) # --- main --- if __name__ == '__main__': import sys sys.argv += ['--x', '1', '--y', '2', '-o', 'color=green', 'marker=o'] parser = argparse.ArgumentParser(description="Plot x,y data in python") parser.add_argument('-xF',"--x", type=str, metavar='', required=True, help="x-Data") parser.add_argument('-yF', "--y", type=str, metavar='', required=True, help="y-Data") parser.add_argument('-o', "--options", nargs="+", default={}, help="Options for plotting", action=keyvalue) args = parser.parse_args() print('[args.options] before:', args.options) plot(args.x, args.y, otherArgs=args.options)
Source:
Officiala documentation – example with custom action
class FooAction(argparse.Action)
at the end of action