PLEP | 6 |
---|---|
author(s) | Drew Leonard |
contact email | [email protected] |
date created | 2018-01-16 |
date last revised | 2018-01-31 |
type | standard |
status | accepted |
DOI | 10.5281/zenodo.1460977 |
The current implementation of PlasmaPy's Plasma
object does not
adequately fulfill the intended use case. Plasma physics is a broad
discipline which makes use of many different kinds of data structure
from a variety of sources and a variety of purposes. If PlasmaPy is to
provide useful tools for all plasma physicists, its core data object
therefore needs to be appropriately flexible. This PLEP therefore
presents a new more general framework for the Plasma
object.
The existing Plasma class was written primarily for use in simulations
and can only be instantiated with astropy
Quantities as input. This
is largely because it was originally intended for use with an entirely
different package and flexibility was not a significant issue. So far no
major problems have arisen from this lack of flexibility, but as
PlasmaPy grows its user-base and its functionality it will have to be
able to load, store and analyse a wide variety of different kinds of
plasma. The Plasma
class as it is currently written will not be able
to do these things.
There are a few ways in which PlasmaPy might deal with multiple different kinds of plasma. One would be to implement multiple classes with different methods of instantiation and with attributes and methods appropriate for the kind of plasma. Another would be to continue using a single class but to build in all functionality needed for every kind of plasma we would wish to be able to work with.
Of these options, both have some drawbacks. The latter would result in the class being extremely difficult to develop and maintain, and likely also problematic to use productively. On the other hand, the former allows each class to be more focused, but requires maintaining them all separately. It would also introduce a slightly different user experience for each different type of plasma.
The proposed solution is a compromise between these two methods, similar
to that used by SunPy for its core
Map object. In
this model each kind of plasma would have its own subclass, allowing
these to provide functionality specific to that plasma. The user
interface to these classes would be handled exclusively by a Plasma
metaclass which would also define common or default functionality. When
instantiated, the metaclass would create and return the appropriate
subclass based on the input.
This approach gives the advantages of reducing the development and maintenance burden compared to using multiple completely separate classes by centralising common functionality, while also allowing arbitrarily specific plasma subclasses. In addition to these development benefits, presenting the user with a single interface for any plasma reduces cognitive overhead for learners and increases the reusability of code.
This section will describe the suggested approach to implement the above structure.
At the core of this implementation will be the main Plasma
metaclass. This metaclass should inherit from Python's abstract base
class, which allows a
class definition to include abstract methods and properties. The
presence of these definitions in the metaclass enforces them in any
class which inherits from it. Such an arrangement lets us use the
Plasma
metaclass to determine the desired default structure for any
Plasma
subclasses. For instance, if we decide every type of plasma
needs coordinate information, we would define the relevant attributes in
the Plasma
metaclass as abstract properties. Different types of
plasma would then be represented by subclasses of Plasma
, which
would be required to define these coordinate properties as well.
The metaclass's properties can define default behaviour which can then be replaced or expanded on by the subclass, or they can contain no functionality and serve only to determine structure. In either case the metaclass allows us to define things which must be present for all plasmas, and so fulfils the aim of defining a consistent user experience across different plasma types in an easily maintainable way.
The instantiation of a plasma subclass should be handled by a class factory. This is a function or a method of a class which takes user input and returns an instance of the appropriate class. Again, this furthers the aim of unifying user experience, since the user only ever needs to use the class factory rather than directly instantiating any particular subclass.
To achieve this, the metaclass should keep a registry of valid subclasses, which can be instantiated by the factory. Each subclass in this registry is checked by some validation function which selects a single subclass based on the user's input, then uses that input to instantiate that subclass and return the instance. Alternatively the registry can be kept by the factory rather than the metaclass.
This PLEP will not maintain backward compatibility.