Textplot Class

This is the TextPlot class, as developed on Friday. The file also includes a "main()" function to test the class.

As it stands, the vertical plot method has a scaling problem. (The "main()" function also has a problem, unrelated to the class itself — it switchs the number of rows and the number of columns, making the graphs look bad.) See the "fixed" version of the class for a properly functioning plot method.

# -*- coding: utf-8 -*-
"""
Created on Fri Apr 16 11:07:15 2021

@author: rmontant
"""

def interpolate(xmid, xa, xb, ya, yb):
    frac = (xmid - xa) / (xb - xa)
    return ya + frac * (yb - ya)
#--------

class TextPlot:
    z = ['whatever...'] # this has nothing to do with plotting....

    def __init__(self, nrows, ncols):
        # copy the local values into the object itself:
        self.nrows = nrows
        self.ncols = ncols
        #----

    def set_data(self, xlist, ylist):
        '''Do NOT assume that xlist is sorted, but
        DO assume that xlist and ylist are matched to each other'''
        self.pairs = []
        for n in range( len(xlist) ):
            self.pairs.append( (xlist[n], ylist[n]) )
        self.pairs.sort()    # put them in smallest-x to biggest-x order
    #----

    def vertical_plot(self):
        xmin = self.pairs[0][0]
        xmax = self.pairs[-1][0]
        for row in range(self.nrows):
            x_r = interpolate(row, 0, self.nrows, xmin, xmax)
            for i in range(1, len(self.pairs) ):
                xa = self.pairs[i-1][0]
                ya = self.pairs[i-1][1]
                xb = self.pairs[i][0]
                yb = self.pairs[i][1]
                if xa <= x_r <= xb:
                    y_c = interpolate(x_r, xa, xb, ya, yb)
                    col = int( interpolate(y_c, ya, yb, 0, self.ncols) )
                    for c in range(col):
                        print('.', end='')
                    print('*')
                    break    # ... out of the for inner "i ..." loop
        print('-' * self.nrows)
    #----

    def report_shape(self):
        print('shape is {:d} rows of {:d} columns'. \
              format(self.nrows, self.ncols))
        print(self.z)   # no good reason for this
    #----
#--------


def main(argv=[__name__]):
    import shutil
    shape = shutil.get_terminal_size()
    rows = shape[0]
    columns = shape[1]

    # create a TextPlot:
    tp1 = TextPlot(rows, columns)
    tp1.z.append('High their!')

    height = int(input('How many rows? '))
    width = int(input('How many columns? '))
    tp2 = TextPlot(height, width)

    print()
    tp1.report_shape()
    tp2.report_shape()

    xdata = [ (.1 * x - 10)  for x in range(100) ]
    ydata = [ (x**2 - 2*x + 3)  for x in xdata ]

    tp1.set_data(xdata, ydata)
    tp1.vertical_plot()
#--------

if __name__ == '__main__':
    import sys
    sys.exit( main(sys.argv) )
#--------