Module and inline calls ========================= Functions in Pingwyn can be called in two different ways. You can either call them as part of the pingwyn module, i.e. ``pg.function()``, or you can call them inline on Pingwyn types, e.g. ``image.function()``. Whilst this appears to serve identical purposes, there is a significant difference between these two methods of calling. .. hint:: If you are ever unsure on which type of function call to use, it is better to use module calls, i.e. ``pg.function()``. Module calls ------------ Module calls, i.e. ``pg.function()``, are the default way of calling Pingwyn functions. In these types of calls, you put in an object, and an altered object is returned. Within the function, a copy of the input object is made. In this way, you are left with the unmodified input object and a modified output object. As an example: .. code-block:: python3 im1 = pg.Image(...) im2 = pg.align_rows(im1) print(im1 is im2) The resulting code should print ``False``, and the contents of both images should be different. Inline calls ------------ Inline calls, i.e. ``object.function()``, is an alternative way of calling a subset of all Pingwyn functions. The main reason for calling functions in this way is to minimise memory usage. Inline functions alter the object that the function is called on, rather than creating a new object or making a copy: .. code-block:: python3 im1 = pg.Image(...) im2 = im1.align_rows() print(im1 is im2) The resulting code should print ``True``, as ``im1`` and ``im2`` refer to the same location in memory. :func:`pingwyn.align_rows` has altered the content of ``im1`` in-place. .. note:: All functions take an object as an input. Often, this is the first argument of a function. When using inline function calls, the input object does not need to be provided, as this is referenced by the object upon which the function is called. See the examples above, where ``align_rows()`` takes an Image object as an argument in the module call, but not in the inline call. .. caution:: Inline calls will also modify objects if you iterate over them. So, in a for loop, such as ``for im in images``, an inline call on ``im`` will also modify the respective entry in the ``images`` iterable. A benefit of inline calls is that functions can be chained on a single line. This makes it possible to quickly perform multiple functions: .. code-block:: python3 im2 = im1.remove_plane().align_rows().clip() The order of operations follows Python's defaults, which means left to right. In this example, first the plane is removed, then the rows are aligned and finally the image is clipped. .. note:: Not all Pingwyn functions have an inline variant. Given that the goal of inline function calls is memory management, it makes little sense for some functions to have an inline call. This is due to the fact that some functions, such as :func:`pingwyn.affine_correct`, must create a new object in order to function properly. The reason for this is down to the fact that Numpy arrays, which are the basis for all Pingwyn types, cannot change in shape/length after they are created.