Source code for openlifu.bf.focal_patterns.focal_pattern
from __future__ import annotations
from abc import ABC, abstractmethod
from dataclasses import dataclass
from typing import Annotated
from openlifu.bf import focal_patterns
from openlifu.geo import Point
from openlifu.util.annotations import OpenLIFUFieldData
from openlifu.util.units import getunittype
[docs]
@dataclass
class FocalPattern(ABC):
"""
Abstract base class for representing a focal pattern
"""
target_pressure: Annotated[float, OpenLIFUFieldData("Target pressure", "Target pressure of the focal pattern in given units")] = 1.0
"""Target pressure of the focal pattern in given units"""
units: Annotated[str, OpenLIFUFieldData("Pressure units", "Pressure units")] = "Pa"
"""Pressure units"""
def __post_init__(self):
if self.target_pressure <= 0:
raise ValueError("Target pressure must be greater than 0")
if not isinstance(self.units, str):
raise TypeError("Units must be a string")
if getunittype(self.units) != 'pressure':
raise ValueError(f"Units must be a pressure unit, got {self.units}")
[docs]
@abstractmethod
def get_targets(self, target: Point):
"""
Get the targets of the focal pattern
:param target: Target point of the focal pattern
:returns: List of target points
"""
pass
[docs]
@abstractmethod
def num_foci(self):
"""
Get the number of foci in the focal pattern
:returns: Number of foci
"""
pass
[docs]
def to_dict(self):
"""
Convert the focal pattern to a dictionary
:returns: Dictionary of the focal pattern parameters
"""
d = self.__dict__.copy()
d['class'] = self.__class__.__name__
return d
[docs]
@staticmethod
def from_dict(d):
"""
Create a focal pattern from a dictionary
:param d: Dictionary of the focal pattern parameters
:returns: FocalPattern object
"""
d = d.copy()
short_classname = d.pop("class")
module_dict = focal_patterns.__dict__
class_constructor = module_dict[short_classname]
return class_constructor(**d)