human
Solve the following python programming problem given the following code:
# Implement the class here:

class SquareImage(object):
    
    def __init__(self, filename=None):
        # To simplify this exercise, set the size of the image to a constant
        # (Each image was specifically written to have size 72 by 72)
        self.Nx = self.Ny = 72
        
        self.x = np.linspace(1, 0, self.Nx)
        self.y = np.linspace(1, 0, self.Ny)

        if filename is None:
            self.z = np.zeros([self.Nx, self.Ny])
        else:
            self.z = np.loadtxt(filename, skiprows=4).reshape(self.Nx, self.Ny)
    
    def add_image(self, image):
        """Add the z values of another 72 by 72 image image to this instance"""
        # Could add a defensive check here 
        assert(np.shape(image.z) == (self.Nx, self.Ny)), 'Image sizes are not equal!'
        
        # Add the image z value to self:
        self.z += image.z

    def plot(self):
        """Plots the contour z against x and y coordinates"""
        fig = plt.figure()
        ax = fig.add_subplot(111, aspect='equal')
        ax.contourf(self.x, self.y, self.z, cmap=cm.Greys_r)
        plt.show()

# The image file names
names = ['img1.pgm', 'img2.pgm', 'img3.pgm', 'img4.pgm']
files = [os.path.join('data', name) for name in names]

# Instantiate the class and plot each picture. 
imgs = []
for f in files:
    image = SquareImage(f)
    print(image)
    imgs.append(image)           # objects are first class instances: add to a list
    image.plot()
    
Given the above code, generate some markdown instructions for it.
assistant
#Here is the Python program you requested.

Task breakdown
Create a SquareImage class which reads (portable greymap, '.pgm') image data from a file. The class should implement the following:

The Initialiser method __init__(self, ...), which takes a string filename as an argument and

stores $Nx$ and $Ny$ as instance attributes, both equal to 72 (this isn't robust, but simplifies the exercise)

calculates and stores $x$ and $y$ as instance attrbutes. These are again the regularly spaced pixel $x$ and $y$ values from 1 to 0 (image colour values in pgm files start from top right pixel) - use linspace from 1 to 0 with $Nx$ and $Ny$ points respectively

Read and store image grey levels in filename as an instance attribute, $z$. The line for extracting this data from the files is the same as before,

np.loadtxt(filename, skiprows=4).reshape(self.Nx, self.Ny)



An add_image method which takes an image argument, and adds the z component of image to self.z

don't forget to add self as the first argument! Instance methods require us to be specific


A plot method which takes no extra arguments, and plots the current instance attributes $z$ as a contour vs $x$ and $y$ (also instance attributes). As this exercise is not testing your matplotlib, we provide the code for the function here:

fig = plt.figure()
ax = fig.add_subplot(111, aspect='equal')
ax.contourf(self.x, self.y, self.z, cmap=cm.Greys_r)
plt.show()