Skip to content

Commit

Permalink
refactor!: modules rewritten with new structure
Browse files Browse the repository at this point in the history
  • Loading branch information
rabii-chaarani committed May 17, 2024
1 parent cadb5fc commit ee17ea1
Show file tree
Hide file tree
Showing 20 changed files with 491 additions and 442 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -158,3 +158,4 @@ cython_debug/
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/
bin/act
19 changes: 15 additions & 4 deletions FoldOptLib/__init__.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,20 @@
# from .fold_modelling import FoldModel, BaseFoldFrameBuilder
from .datatypes import KnowledgeType, OptimisationType, ObjectiveType, DataType, NormalDistribution, \
VonMisesFisherDistribution
from .datatypes import (
KnowledgeType,
OptimisationType,
ObjectiveType,
DataType,
NormalDistribution,
VonMisesFisherDistribution,
InputGeologicalKnowledge
)
from .helper import utils
from .input import CheckInputData, InputDataProcessor
from .objective_functions import GeologicalKnowledgeFunctions, VonMisesFisher, LeastSquaresFunctions, \
ObjectiveFunction, is_axial_plane_compatible
from .objective_functions import (
GeologicalKnowledgeFunctions,
VonMisesFisher,
LeastSquaresFunctions,
ObjectiveFunction
)
from .optimisers import FourierSeriesOptimiser, AxialSurfaceOptimiser
from .splot import SPlotProcessor
32 changes: 28 additions & 4 deletions FoldOptLib/builders/builder.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from base_builder import BaseBuilder
from .base_builder import BaseBuilder

from ..datatypes import InterpolationConstraints, ConstraintType
from LoopStructural import LoopInterpolator, BoundingBox
Expand All @@ -8,11 +8,11 @@

class Builder(BaseBuilder):

def __init__(self, bounding_box: BoundingBox):
self.bounding_box = bounding_box
def __init__(self, boundingbox: BoundingBox):
self.boundingbox = boundingbox

self.interpolator = LoopInterpolator(
self.bounding_box,
self.boundingbox,
dimensions=3,
nelements=1000
)
Expand All @@ -32,4 +32,28 @@ def evaluate_scalar_value(self, locations: numpy.ndarray) -> numpy.ndarray:
def evaluate_gradient(self, locations: numpy.ndarray) -> numpy.ndarray:

return self.interpolator.evaluate_gradient(locations)

def min(self):
"""Calculate the min value of the fold frame
in the model
Returns
-------
minimum, float
min value of the feature evaluated on a regular grid in the model domain
"""

return numpy.nanmin(self.evaluate_scalar_value(self.boundingbox.regular_grid((10, 10, 10))))

def max(self):
"""Calculate the maximum value of the geological feature
in the model
Returns
-------
maximum, float
max value of the feature evaluated on a regular grid in the model domain
"""

return numpy.nanmax(self.evaluate_scalar_value(self.boundingbox.regular_grid((10, 10, 10))))

12 changes: 11 additions & 1 deletion FoldOptLib/datatypes/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,14 @@
from .probability_distributions import NormalDistribution, VonMisesFisherDistribution
from .input_geological_knowledge import InputGeologicalKnowledge
from .enums import *
from .enums import (
KnowledgeType,
FitType,
DataType,
ObjectiveType,
OptimisationType,
OptimiserType,
SolverType,
ConstraintType,
CoordinateType
)
from .interpolation_constraints import InterpolationConstraints
5 changes: 3 additions & 2 deletions FoldOptLib/datatypes/enums.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,13 @@ class SolverType(IntEnum):
PARTICLE_SWARM = 3


class RotationType(IntEnum):
class FitType(IntEnum):
LIMB = 0
AXIS = 1
AXIAL_SURFACE = 2


class CoordinateType(IntEnum):
class ConstraintType(IntEnum):
VALUE = 0
TANGENT = 1
NORMAL = 2
Expand Down
10 changes: 7 additions & 3 deletions FoldOptLib/datatypes/input_geological_knowledge.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,15 @@ class InputGeologicalKnowledge:
axial_surface: Optional[VonMisesFisherDistribution] = None

def __post_init__(self):
if len(self.axial_surface.mu) == 2:
self.axial_surface.mu = strike_dip_to_vector(self.axial_surface.mu[0], self.axial_surface.mu[1])
if self.axial_surface is not None:

if len(self.axial_surface.mu) == 2:
self.axial_surface.mu = strike_dip_to_vector(self.axial_surface.mu[0], self.axial_surface.mu[1])

def __call__(self, input_knowledge: KnowledgeType):
def __getitem__(self, input_knowledge: KnowledgeType):

knowledge_map = {

KnowledgeType.ASYMMETRY: self.asymmetry,
KnowledgeType.AXIAL_TRACE: self.axial_trace,
KnowledgeType.WAVELENGTH: self.fold_wavelength,
Expand All @@ -34,3 +37,4 @@ def __call__(self, input_knowledge: KnowledgeType):
}

return knowledge_map[input_knowledge]

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 CoordinateType
from ..datatypes.enums import ConstraintType
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: CoordinateType):
def __getitem__(self, constraint_type: ConstraintType):
constraints = {
CoordinateType.VALUE: self.value_constraints,
CoordinateType.TANGENT: self.tangent_constraints,
CoordinateType.NORMAL: self.normal_constraints,
CoordinateType.GRADIENT: self.gradient_constraints
ConstraintType.VALUE: self.value_constraints,
ConstraintType.TANGENT: self.tangent_constraints,
ConstraintType.NORMAL: self.normal_constraints,
ConstraintType.GRADIENT: self.gradient_constraints
}
return constraints[constraint_type]
18 changes: 9 additions & 9 deletions FoldOptLib/datatypes/probability_distributions.py
Original file line number Diff line number Diff line change
@@ -1,27 +1,27 @@
from dataclasses import dataclass
from typing import Union, Optional
from typing import Union, Optional, List
import numpy
import beartype


@beartype.beartype
@dataclass
class Bounds:
lower_bound: Optional[Union[int, float, list, numpy.ndarray]] = None
upper_bound: Optional[Union[int, float, list, numpy.ndarray]] = None
lower_bound: Optional[Union[int, float, List, numpy.ndarray]] = None
upper_bound: Optional[Union[int, float, List, numpy.ndarray]] = None


@beartype.beartype
@dataclass
class NormalDistribution:
mu: Union[int, float, list, numpy.ndarray]
sigma: Union[int, float, list, numpy.ndarray]
weight: Optional[Union[int, float, list, numpy.ndarray]] = 1.
mu: Union[int, float]
sigma: Union[int, float]
weight: Optional[Union[int, float]] = 1.0


@beartype.beartype
@dataclass
class VonMisesFisherDistribution:
mu: Union[int, float, list, numpy.ndarray]
kappa: Union[int, float, list, numpy.ndarray]
weight: Optional[Union[int, float, list, numpy.ndarray]] = 1.
mu: Union[List, numpy.ndarray]
kappa: Union[int, float]
weight: Optional[Union[int, float]] = 1.0
62 changes: 42 additions & 20 deletions FoldOptLib/fold_modelling/engine.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@
# from ..helper._helper import *
from ..helper.utils import *
from ..builders import FoldFrameBuilder
from ..datatypes import DataType, InterpolationConstraints, ConstraintType, CoordinateType, InputGeologicalKnowledge, KnowledgeType, RotationType
from ..datatypes import DataType, InterpolationConstraints, ConstraintType, CoordinateType, InputGeologicalKnowledge, KnowledgeType, FitType
from ..input import InputDataProcessor, OptData, InputData
from ..from_loopstructural._fold import FoldEvent
from ..from_loopstructural._fold_frame import FoldFrame
from LoopStructural import BoundingBox
from .base_engine import BaseEngine
from ..optimisers.fourier_optimiser import FourierSeriesOptimiser
from ..optimisers import FourierSeriesOptimiser
from LoopStructural import BoundingBox
from LoopStructural.utils._transformation import EuclideanTransformation

import gc

def fold_function(params):
Expand Down Expand Up @@ -68,20 +70,29 @@ def __init__(self, data: InputData,
**kwargs : dict
additional keyword arguments
"""
data_processor = InputDataProcessor(data)
self.data = data_processor.get_data()
self.geological_knowledge = geological_knowledge
self.bounding_box = bounding_box

self.raw_data = data
self.bounding_box = data[DataType.BOUNDING_BOX]
self.geological_knowledge = data[DataType.GEOLOGICAL_KNOWLEDGE]
self.dimensions = dimensions
self.model = None
self.gradient_data = self.data[['gx', 'gy', 'gz']].to_numpy()
self.points = self.data[['X', 'Y', 'Z']].to_numpy() # coordinates of the data points
assert len(self.points) == len(self.gradient_data), "coordinates must have the same length as data"
self.kwargs = kwargs
self.axial_surface = None
self.scaled_points = None


self.kwargs = kwargs

def set_data(self, data: InputData) -> None:
"""
Process the data by extracting the gradient data from the data DataFrame.
Returns
-------
None
"""
data_processor = InputDataProcessor(data)
self.data = data_processor.get_data()

def initialise_model(self) -> None:
"""
Expand All @@ -94,8 +105,9 @@ def initialise_model(self) -> None:
-------
None
"""
self.model = GeologicalModel(self.bounding_box[0, :], self.bounding_box[1, :])
self.scaled_points = self.model.scale(self.points)
self.set_data(self.raw_data)
# self.model = GeologicalModel(self.bounding_box[0, :], self.bounding_box[1, :])
self.scaled_points = EuclideanTransformation(dimensions=self.dimensions)(self.points)

def process_axial_surface_proposition(self, axial_normal: np.ndarray) -> pd.DataFrame:

Expand All @@ -120,14 +132,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='sn', coord=0)
dataset = create_dataset(axial_normal, self.scaled_points, name='sn', coord=0)

assert len(self.points) == len(self.gradient_data), "coordinates must have the same length as data"
assert len(self.scaled_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='sn', coord=1)
y_coord = create_dataset(y, self.scaled_points, name='sn', coord=1)


# append the two datasets together
Expand Down Expand Up @@ -177,7 +189,7 @@ def create_and_build_fold_event(self) -> FoldEvent:
foldframe = FoldFrame('sn', self.axial_surface)

# calculate the gradient of the axial surface
s1g = self.axial_surface[0].evaluate_gradient(self.scaled_points)
s1g = self.axial_surface[CoordinateType.AXIAL_FOLIATION_FIELD].evaluate_gradient(self.scaled_points)

# normalise the gradient
s1g /= np.linalg.norm(s1g, axis=1)[:, None]
Expand Down Expand Up @@ -313,16 +325,26 @@ def fit_fourier_series(self, fold_frame_coordinate: np.ndarray, rotation_angle:

# Check the type of knowledge and generate x accordingly
if knowledge_type == 'fold_axis_rotation_angle':
x = np.linspace(self.axial_surface[1].min(), self.axial_surface[1].max(), 100)
else:
x = np.linspace(self.axial_surface[0].min(), self.axial_surface[0].max(), 100)
self.geological_knowledge.fittypeflag[FitType.LIMB] = True
x = np.linspace(
self.axial_surface[CoordinateType.AXIAL_FOLIATION_FIELD].min(),
self.axial_surface[CoordinateType.AXIAL_FOLIATION_FIELD].max(),
100
)
if knowledge_type == 'fold_axis_rotation_angle':
self.geological_knowledge.fittypeflag[FitType.AXIS] = True
x = np.linspace(
self.axial_surface[CoordinateType.FOLD_AXIS_FIELD].min(),
self.axial_surface[CoordinateType.FOLD_AXIS_FIELD].max(),
100
)

# Create a FourierSeriesOptimiser instance
fourier_optimiser = FourierSeriesOptimiser(fold_frame_coordinate, rotation_angle, x)

if self.geological_knowledge is not None:

opt = fourier_optimiser.optimise(geological_knowledge=self.geological_knowledge[knowledge_type])
opt = fourier_optimiser.optimise()

return opt.x

Expand Down
1 change: 0 additions & 1 deletion FoldOptLib/helper/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
from ._helper import *
from .utils import *
Loading

0 comments on commit ee17ea1

Please sign in to comment.