TextPlot Class, fixed

This is the TextPlot class, with a corrected vertical plot method. The "main()" test function is also corrected; and it allows the user to input the x range, and plots a more visually interesting function.

Corrections are marked by comments that start "###".

# -*- 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:
        ###
        ### ADJUST VALUES!!!
        ###
        self.nrows = nrows - 5  # space for y-axis, prompts
        self.ncols = ncols - 19 # space for x-, y- labels
        #----

    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

        ###
        ### NEED THESE!
        ###
        self.xmin, self.xmax = self.pairs[0][0], self.pairs[-1][0]
        self.ymin, self.ymax = min(ylist), max(ylist)
    #----

    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)
                    ###
                    ### USE (ymin,ymax), NOT (ya,yb) !!!
                    ###
                    #col = int( interpolate(y_c, ya, yb, 0, self.ncols) )
                    col = int( interpolate(y_c, self.ymin, self.ymax, 0, self.ncols) )

                    print('{:7.2f}| '.format(x_r), end='')
                    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()
    ###
    ### THESE WERE REVERSED!
    ###
    #rows = shape[0]
    #columns = shape[1]
    rows = shape[1]
    columns = shape[0] - 10     # leave space for row label

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

    ###
    ### The tp2 object isn't needed...
    ###
    ### height = int(input('How many rows? '))
    ### width = int(input('How many columns? '))
    ### tp2 = TextPlot(height, width)

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

    ###
    ### THERE WAS A POOR CHOICE OF X-RANGE !!!
    ###
    ### xdata = [ (.1 * x - 10)  for x in range(100) ]

    # Let user select the x-range
    if len(argv) == 3:
        xmin, xmax = float(argv[1]), float(argv[2])
    else:
        xmin = input('xmin (-20): ')
        if len(xmin) > 0:
            xmin = float(xmin)
        else:
            xmin = -20
        xmax = input('xmax (-10): ')
        if len(xmax) > 0:
            xmax = float(xmax)
        else:
            xmax = 60
    xrange = xmax - xmin
    xdata = [ (xmin + xrange*x/100)  for x in range(100) ]

    # Mildly interesting function:
    ydata = [ (x**3 - 50*x**2 + 25*x)  for x in xdata ]

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

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

Sample output

$  python ./textplot-class.py

shape is 73 rows of 146 columns
['whatever...', 'High their!']
xmin (-20):
xmax (-10):
 -20.00| *
 -18.92| -------*
 -17.83| ---------------*
 -16.75| ---------------------*
 -15.66| ----------------------------*
 -14.58| ---------------------------------*
 -13.49| --------------------------------------*
 -12.41| -------------------------------------------*
 -11.32| -----------------------------------------------*
 -10.24| ---------------------------------------------------*
  -9.15| ------------------------------------------------------*
  -8.07| ---------------------------------------------------------*
  -6.98| -----------------------------------------------------------*
  -5.90| -------------------------------------------------------------*
  -4.81| ---------------------------------------------------------------*
  -3.73| ----------------------------------------------------------------*
  -2.64| -----------------------------------------------------------------*
  -1.56| ------------------------------------------------------------------*
  -0.47| ------------------------------------------------------------------*
   0.61| ------------------------------------------------------------------*
   1.70| ------------------------------------------------------------------*
   2.78| ------------------------------------------------------------------*
   3.87| -----------------------------------------------------------------*
   4.95| ----------------------------------------------------------------*
   6.04| ---------------------------------------------------------------*
   7.12| --------------------------------------------------------------*
   8.21| ------------------------------------------------------------*
   9.29| -----------------------------------------------------------*
  10.38| ---------------------------------------------------------*
  11.46| -------------------------------------------------------*
  12.55| -----------------------------------------------------*
  13.63| ---------------------------------------------------*
  14.72| -------------------------------------------------*
  15.80| -----------------------------------------------*
  16.89| ---------------------------------------------*
  17.97| -------------------------------------------*
  19.06| -----------------------------------------*
  20.14| ---------------------------------------*
  21.23| -------------------------------------*
  22.31| -----------------------------------*
  23.40| ----------------------------------*
  24.48| --------------------------------*
  25.57| ------------------------------*
  26.65| -----------------------------*
  27.74| ----------------------------*
  28.82| ---------------------------*
  29.91| --------------------------*
  30.99| -------------------------*
  32.08| -------------------------*
  33.16| -------------------------*
  34.25| -------------------------*
  35.33| -------------------------*
  36.42| --------------------------*
  37.50| ---------------------------*
  38.59| -----------------------------*
  39.67| -------------------------------*
  40.76| ---------------------------------*
  41.84| -----------------------------------*
  42.93| --------------------------------------*
  44.01| ------------------------------------------*
  45.10| ----------------------------------------------*
  46.18| --------------------------------------------------*
  47.27| -------------------------------------------------------*
  48.35| ------------------------------------------------------------*
  49.44| ------------------------------------------------------------------*
  50.52| ------------------------------------------------------------------------*
  51.61| -------------------------------------------------------------------------------*
  52.69| ---------------------------------------------------------------------------------------*
  53.78| -----------------------------------------------------------------------------------------------*
  54.86| --------------------------------------------------------------------------------------------------------*
  55.95| -----------------------------------------------------------------------------------------------------------------*
  57.03| ---------------------------------------------------------------------------------------------------------------------------*
  58.12| --------------------------------------------------------------------------------------------------------------------------------------*
==================================================================================================================================================
$