Simplified Analysis Integration Example¶
In this example we will add an ExponentCalculator
class and integrate it into
django_analyses.
Interface Creation¶
By default, interfaces are expected to be classes and expose a run()
method which
returns a dictionary of output keys and values. Therefore, an ExponentCalculator
class might look something like this:
class ExponentCalculator:
def __init__(self, base: float, exponent: float):
self.base = base
self.exponent = exponent
def run(self) -> dict:
return {"result": self.base ** self.exponent}
Analysis Creation¶
The ExponentCalculator
class is one possible implementation of exponentiation.
Let’s define this procedure as a new available analysis:
>>> from django_analyses.models import Analysis
>>> definition = {
>>> "title": "Exponentiation",
>>> "description": "Calculate <base> in the power of <exponent>.",
>>> }
>>> analysis = Analysis.objects.create(**definition)
Analysis Version Creation¶
Now, we can create an AnalysisVersion
instance to represent the ExponentCalculator
class we’ve created:
>>> from django_analyses.models import AnalysisVersion
>>> definition = {
>>> "title": "built-in",
>>> "description": "Calculate the exponent of a number using Python's built-in power operator.",
>>> }
>>> analysis_version = AnalysisVersion.objects.create(**definition)
Input Specification¶
The ExponentCalculator
class expects two float
type input values which are
assigned in its initialization: base
and exponent
.
InputSpecification
instances are
created with an association to a specific Analysis
(this prevents name clashes between input or output definitions for different analyses)
and may be used for a number of its
AnalysisVersion
instances.
>>> from django_analyses.models import FloatInputDefinition, InputSpecification
>>> definition = {
>>> "base": {
>>> "type": FloatInputDefinition,
>>> "required": True,
>>> "description": "Floating point number to be raised by <exponent>.",
>>> },
>>> "exponent": {
>>> "type": FloatInputDefinition,
>>> "required": True,
>>> "description": "Floating point number to raise <base> by.",
>>> },
>>> }
>>> analysis = Analysis.objects.get(title="Exponentiation")
>>> input_specification, created = InputSpecification.objects.from_dict(analysis, definition)
>>> input_specification
<InputSpecification:
[Exponentiation]
base Float
exponent Float
>
>>> created
True
Output Specification¶
The OutputSpecification
may be created very similarly:
>>> from django_analyses.models import FloatOutputDefinition, OutputSpecification
>>> definition = {
>>> "result": {
>>> "type": FloatOutputDefinition,
>>> "description": "Product of <base> multiplied <exponent> times.",
>>> }
>>> }
>>> analysis = Analysis.objects.get(title="Exponentiation")
>>> output_specification, created = OutputSpecification.objects.from_dict(analysis, definition)
>>> output_specification
<OutputSpecification
[Exponentiation]
result Float
>
>>> created
True
Interface Integration¶
At this stage our new analysis is ready to be “plugged-in”. Interfaces are queried from
the ANALYSIS_INTERFACES
dictionary in the project’s settings.py. Analyses are
expected to be registered as
ANALYSIS_INTERFACES["analysis_title"]["analysis_version_title"]
, so in our case:
from exponent_calculator import ExponentCalculator
...
ANALYSIS_INTERFACES = {"Exponentiation": {"built-in": ExponentCalculator}}