import numpy as np import argparse from matplotlib import pyplot as plt from os import sys def graph_from_csv(filename, multiline=False, clean_fn=lambda x: x.strip(), independent_convert_fn=lambda x: int(x), dependent_convert_fn=lambda x: int(x), xlabel="", ylabel="", title="", xscale="linear", yscale="linear", approximate=False, approximate_size=1, xbase=10, ybase=10): """ Generates a graph from a CSV file. Supports multiple sets of the same independent variable. Created by Hunter Henrichsen, 2020. Params: filename -- The CSV file to read. multiline -- Whether to average (using np.mean()) the datasets that share an independent variable. clean_fn -- The function run on each line to clean it before splitting on commas. independent_convert_fn -- The function to convert the independent variable to the desired type. dependent_convert_fn -- The function to convert the dependent variable to the desired type. """ data = {} # Read data. with open(filename, 'r') as file: header = file.readline() columns = clean_fn(header).split(',') for i in range(1, len(columns)): data[i] = { 'name': columns[i], 'data': {}, } while line := file.readline(): split_line = clean_fn(line).split(',') for i in range(1, len(split_line)): iv = independent_convert_fn(split_line[0]) if iv not in data[i]['data']: data[i]['data'][iv] = [] data[i]['data'][iv].append(dependent_convert_fn(split_line[i])) file.close() # Process data to averaged. if not multiline: for key in data: current_set = data[key] for n in data[key]['data']: dataset = data[key]['data'][n] data[key]['data'][n] = np.mean(dataset) # Begin plotting. plt.title(title) plt.xscale(xscale, basex=xbase) plt.yscale(yscale, basey=ybase) plt.xlabel(xlabel) plt.ylabel(ylabel) for key in data: current_set = data[key] lists = sorted(current_set['data'].items()) x, y = zip(*lists) if approximate: approx = np.polyfit(np.log(x) if xscale == "log" else x, np.log(y) if yscale == "log" else y, approximate_size) print(current_set['name'], "Approximation: (" + str(ybase ** approx[1]) + ")x^" + str(approx[0])) plt.plot(x, y, label=current_set['name']) plt.legend() plt.show() if __name__ == "__main__": parser = argparse.ArgumentParser(description='Transforms a CSV file into a matplotlib graph.') parser.add_argument('--xscale', action='store', nargs='?', default='linear') parser.add_argument('--yscale', action='store', nargs='?', default='linear') parser.add_argument('--xbase', action='store', nargs='?', default=10, type=int) parser.add_argument('--ybase', action='store', nargs='?', default=10, type=int) parser.add_argument('--xlabel', action='store', nargs='?', default='') parser.add_argument('--ylabel', action='store', nargs='?', default='') parser.add_argument('--title', action='store', nargs='?', default='') parser.add_argument('--approximate', action='store_true', default=False) parser.add_argument('--approximateSize', action='store', default=1, type=int) parser.add_argument('filename', nargs=1, type=str) args = parser.parse_args() print(args) graph_from_csv(args.filename[0], multiline=False, xscale=args.xscale, xbase=args.xbase, yscale=args.yscale, ybase=args.ybase, xlabel=args.xlabel, ylabel=args.ylabel, title=args.title, approximate=args.approximate, approximate_size=args.approximateSize)