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
CodePudding user response:
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:
Parsing Dictionary-Like Key-Value Pairs Using Argparse in Python | Sumit’s Dreams of Electric Sheeps
Officiala documentation - example with custom action
class FooAction(argparse.Action)
at the end of action