Component

Component#

An MRFM experiment typically consists of several components, such as a resonator, a magnet, and a sample. The parameters and related calculations of components can be encapsulated into an object to simplify the input process.

The ComponentBase class is an abstract dataclass with a formatted metadata output. It allows users to define the base unit of a parameter as a dataclass field. Python dataclass is used to simplify the definition process.

Create a component class#

To create a component dataclass, simply inherit from ComponentBase and define the fields as dataclass fields.

For example, to create a cantilever class that stores the cantilever frequency “f_c” and cantilever spring constant “k_c”, we can inherit the ComponentBase class and define the attributes as follows:

from mrfmsim.component import ComponentBase
from dataclasses import dataclass

@dataclass
class Cantilever(ComponentBase):
    f_c: float
    k_c: float


>>> cantilever = Cantilever(f_c=3000, k_c=1.0)
>>> cantilever.f_c
3000
>>> cantilever.k_c
1.0

>>> cantilever # dataclass output
Cantilever(f_c=3000, k_c=100.0)
>>> print(cantilever) # formatted output
Cantilever(f_c=3000
    k_c=100.000)

If we want additional attributes through calculation, instead of defining __init__ method, we can define a __post_init__ method. To specify that these are not instantiation variables, we specify that they are init=False in the dataclass field. See post-init processing.

from dataclasses import field
import numpy as np

@dataclass
class Cantilever(ComponentBase):
    k_c: float
    f_c: float = 5000
    omega: float = field(init=False)

    def __post_init__(self):
        self.omega = 2 * np.pi * self.f_c

>>> cantilever = Cantilever(k_c=100.0)
>>> cantilever.omega
31415.926535897932

>>> print(cantilever)
Cantilever(f_c=5000
    k_c=100.000
    omega=31415.927)

In the above code, the cantilever frequency defaults to 5000 Hz.

To add units and formatted string output for the attributes, we can add “unit” and “format” to the dataclass field’ metadata.

@dataclass
class Cantilever(ComponentBase):
    k_c: float = field(metadata={"unit": "aN/nm", "format": ".3e"})
    f_c: float = field(metadata={"unit": "Hz", "format": ".3e"}, default=3000)
    omega: float = field(init=False, metadata={"unit": "rad/s", "format": ".3f"})

    def __post_init__(self):
        self.omega = 2 * np.pi * self.f_c

>>> cantilever = Cantilever(k_c=100.0)
>>> print(cantilever)
Cantilever(k_c=1.000e+02 aN/nm
    f_c=3000 Hz
    omega=18849.556 rad/s)