Skip to content

Commit

Permalink
refactor: added new constraint class for interpolation
Browse files Browse the repository at this point in the history
  • Loading branch information
rabii-chaarani committed May 10, 2024
1 parent d450060 commit 30f5ab3
Show file tree
Hide file tree
Showing 8 changed files with 196 additions and 31 deletions.
15 changes: 10 additions & 5 deletions FoldOptLib/builders/fold_frame_builder.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,24 @@
from .structural_frame_builder import StructuralFrameBuilder
from ..datatypes import ConstraintType, InterpolationConstraints
from .structural_frame_builder import Builder
from ..input import OptData
from ..datatypes import CoordinateType, InterpolationConstraints
from LoopStructural import LoopInterpolator, BoundingBox
import numpy


class FoldFrameBuilder(StructuralFrameBuilder):
class FoldFrameBuilder(Builder):

def __init__(self, constraints: InterpolationConstraints, bounding_box: BoundingBox):
def __init__(self, constraints: OptData, bounding_box: BoundingBox):
super().__init__(constraints, bounding_box)

def build_axial_surface_field(self):
pass

self.set_constraints()

def build_fold_axis_field(self):
pass

def build_x_axis_field(self):
pass

def build(self):
pass
23 changes: 13 additions & 10 deletions FoldOptLib/builders/structural_frame_builder.py
Original file line number Diff line number Diff line change
@@ -1,26 +1,29 @@
from base_builder import BaseBuilder
from ..datatypes import ConstraintType, InterpolationConstraints
from ..input import OptData
from ..datatypes import CoordinateType, InterpolationConstraints
from LoopStructural import LoopInterpolator, BoundingBox
import numpy
from typing import Union, Any


class StructuralFrameBuilder(BaseBuilder):
class Builder(BaseBuilder):

def __init__(self, constraints: InterpolationConstraints, bounding_box: BoundingBox):
def __init__(self, constraints: Union[InterpolationConstraints, OptData], bounding_box: BoundingBox):
self.constraints = constraints
self.bounding_box = bounding_box
self.interpolator = LoopInterpolator(
self.bounding_box,
dimensions=3,
nelements=1000
)

def set_constraints(self):
self.interpolator.fit(
values=self.constraints[ConstraintType.VALUE],
tangent_vectors=self.constraints[ConstraintType.TANGENT],
normal_vectors=self.constraints[ConstraintType.NORMAL],
)
#TODO:Restart from here

# def set_constraints(self, type: Union[CoordinateType, Any]):
# self.interpolator.fit(
# values=self.constraints[type.VALUE],
# tangent_vectors=self.constraints[type.TANGENT],
# normal_vectors=self.constraints[type.NORMAL],
# )

def evaluate_scalar_value(self, locations: numpy.ndarray) -> numpy.ndarray:
return self.interpolator.evaluate_scalar_value(locations)
Expand Down
2 changes: 1 addition & 1 deletion FoldOptLib/datatypes/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from .probability_distributions import NormalDistribution, VonMisesFisherDistribution
from .input_geological_knowledge import InputGeologicalKnowledge
from .enums import KnowledgeType, OptimisationType, ObjectiveType, DataType, SolverType, ConstraintType
from .enums import *
from .interpolation_constraints import InterpolationConstraints
2 changes: 1 addition & 1 deletion FoldOptLib/datatypes/enums.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ class RotationType(IntEnum):
AXIS = 1


class ConstraintType(IntEnum):
class CoordinateType(IntEnum):
VALUE = 0
TANGENT = 1
NORMAL = 2
Expand Down
12 changes: 6 additions & 6 deletions FoldOptLib/datatypes/interpolation_constraints.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from dataclasses import dataclass
from typing import Union, Optional
from enums import ConstraintType
from enums import CoordinateType
import numpy
import beartype

Expand Down Expand Up @@ -28,11 +28,11 @@ class InterpolationConstraints:
gradient_constraints: Optional[Union[list, numpy.ndarray]] = None

@beartype.beartype
def __getitem__(self, constraint_type: ConstraintType):
def __getitem__(self, constraint_type: CoordinateType):
constraints = {
ConstraintType.VALUE: self.value_constraints,
ConstraintType.TANGENT: self.tangent_constraints,
ConstraintType.NORMAL: self.normal_constraints,
ConstraintType.GRADIENT: self.gradient_constraints
CoordinateType.VALUE: self.value_constraints,
CoordinateType.TANGENT: self.tangent_constraints,
CoordinateType.NORMAL: self.normal_constraints,
CoordinateType.GRADIENT: self.gradient_constraints
}
return constraints[constraint_type]
8 changes: 4 additions & 4 deletions FoldOptLib/fold_modelling/engine.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,14 +115,14 @@ def process_axial_surface_proposition(self, axial_normal: np.ndarray) -> pd.Data
# normalise axial surface normal
axial_normal /= np.linalg.norm(axial_normal)
# create a dataset from the axial surface normal
dataset = create_dataset(axial_normal, self.points, name='s1', coord=0)
dataset = create_dataset(axial_normal, self.points, name='sn', coord=0)

assert len(self.points) == len(self.gradient_data), "coordinates must have the same length as data"

# rotate the axial normal by 90 degrees to create the Y axis of the fold frame
y = rotate_vector(axial_normal, np.pi / 2, dimension=3)
# create a dataset from the Y axis of the fold frame
y_coord = create_dataset(y, self.points, name='s1', coord=1)
y_coord = create_dataset(y, self.points, name='sn', coord=1)

# append the two datasets together
dataset = pd.concat([dataset, y_coord])
Expand Down Expand Up @@ -152,7 +152,7 @@ def build_fold_frame(self, axial_normal: np.ndarray) -> None:
self.model.data = dataset

# create and add a fold frame to the model
self.axial_surface = self.model.create_and_add_fold_frame('s1',
self.axial_surface = self.model.create_and_add_fold_frame('sn',
buffer=0.6,
solver='pyamg',
nelements=1e3,
Expand All @@ -177,7 +177,7 @@ def create_and_build_fold_event(self) -> FoldEvent:
The created fold event.
"""
# create a fold frame object from the axial surface
foldframe = FoldFrame('s1', self.axial_surface)
foldframe = FoldFrame('sn', self.axial_surface)

# calculate the gradient of the axial surface
s1g = self.axial_surface[0].evaluate_gradient(self.scaled_points)
Expand Down
1 change: 1 addition & 0 deletions FoldOptLib/input/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
from .input_data_checker import CheckInputData
from .input_data_processor import InputDataProcessor
from .data_storage import InputData, OptData
164 changes: 160 additions & 4 deletions FoldOptLib/input/data_storage.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
from dataclasses import dataclass
from ..datatypes import KnowledgeType, DataType, InputGeologicalKnowledge
from dataclasses import dataclass, field
from ..datatypes import KnowledgeType, DataType, InputGeologicalKnowledge, CoordinateType, InterpolationConstraints, CoordinateType
from ..objective_functions import GeologicalKnowledgeFunctions
from LoopStructural import BoundingBox
import pandas
import numpy
import beartype
from typing import List

@dataclass
class InputData:
Expand All @@ -22,10 +23,11 @@ def foliations(self):
def number_of_foliations(self):
return len(self.foliations())

def get_foliations(self, feature_name):
@beartype.beartype
def get_foliations(self, feature_name: str):
return self.data[self.data['feature_name'] == feature_name]


@beartype.beartype
def __getitem__(self, data_type: DataType):

data_map = {
Expand All @@ -36,4 +38,158 @@ def __getitem__(self, data_type: DataType):


return data_map[data_type]


@beartype.beartype
@dataclass
class OptData:
"""
Class representing optimisation data.
Attributes
----------
data : pandas.DataFrame
The input data.
constraints : List[InterpolationConstraints]
The interpolation constraints.
Methods
-------
set_constraints(constraints: InterpolationConstraints, constraint_type: ConstraintType):
Set the interpolation constraints for a given constraint type.
axial_normals():
Get the axial normals from the data.
y_normals():
Get the y normals from the data.
set_axial_surface_field_constraints():
Set the axial surface field constraints.
set_fold_axis_field_constraints():
Set the fold axis field constraints.
_getitem__(constraint_type: ConstraintType):
Get the interpolation constraints for a given constraint type.
"""
data : pandas.DataFrame
constraints: List[InterpolationConstraints] = field(default_factory=lambda: [None] * len(CoordinateType), init=False)


def set_constraints(
self,
constraints: InterpolationConstraints,
constraint_type: CoordinateType
):
"""
Set the interpolation constraints for a given constraint type.
Parameters
----------
constraints : InterpolationConstraints
The interpolation constraints.
constraint_type : ConstraintType
The type of constraint.
"""
self.constraints[constraint_type] = constraints


def axial_normals(self):
"""
Get the axial normals from the data.
Returns
-------
pandas.DataFrame
The axial normals.
"""

return self.data[self.data['feature_name'] == 'sn' and self.data['coord'] == CoordinateType.AXIAL_FOLIATION_FIELD]


def y_normals(self):
"""
Get the y normals from the data.
Returns
-------
pandas.DataFrame
The y normals.
"""

return self.data[self.data['feature_name'] == 'sn' and self.data['coord'] == CoordinateType.FOLD_AXIS_FIELD]


def set_axial_surface_field_constraints(self):
"""
Set the axial surface field constraints.
"""
try:
value_constraints = self.axial_normals[['X', 'Y', 'Z', 'value']].to_numpy()
except:
mean_x, mean_y, mean_z = self.axial_normals[['X', 'Y', 'Z']].mean()
value_constraints = numpy.array([mean_x, mean_y, mean_z, 0.0])

normal_constraints = self.axial_normals[['X', 'Y', 'Z', 'gx', 'gy', 'gz']].to_numpy()

ic = InterpolationConstraints(
value=value_constraints,
normal_constraints=normal_constraints
)

self.set_constraints(ic, CoordinateType.AXIAL_SURFACE_FIELD)


def set_fold_axis_field_constraints(self):
"""
Set the fold axis field constraints.
"""
try:
value = self.y_normals[['X', 'Y', 'Z', 'value']].to_numpy()
except:
mean_x, mean_y, mean_z = self.axial_normals[['X', 'Y', 'Z']].mean()
value = numpy.array([mean_x, mean_y, mean_z, 0.0])

normal_constraints = self.y_normals[['X', 'Y', 'Z', 'gx', 'gy', 'gz']].to_numpy()

ic = InterpolationConstraints(
value=value,
normal_constraints=normal_constraints
)

self.set_constraints(ic, CoordinateType.FOLD_AXIS_FIELD)



def _getitem__(
self,
constraint_type: CoordinateType
):

"""
Get the interpolation constraints for a given constraint type.
Parameters
----------
constraint_type : ConstraintType
The type of constraint.
Returns
-------
InterpolationConstraints
The interpolation constraints.
"""
if self.constraints[constraint_type] is None:

if constraint_type is CoordinateType.AXIAL_SURFACE_FIELD:

self.set_axial_surface_field_constraints()

return self.constraints[constraint_type]

if constraint_type is CoordinateType.FOLD_AXIS_FIELD:

self.set_fold_axis_field_constraints()

return self.constraints[constraint_type]

if self.constraints[constraint_type] is not None:

return self.constraints[constraint_type]

0 comments on commit 30f5ab3

Please sign in to comment.