diff --git a/docs/geos_posp_docs/PVplugins.rst b/docs/geos_posp_docs/PVplugins.rst deleted file mode 100644 index 66a3b583..00000000 --- a/docs/geos_posp_docs/PVplugins.rst +++ /dev/null @@ -1,14 +0,0 @@ -Paraview plugins -================ - -Paraview plugins were developed using Python 3.9.13 and are compatible with Paraview v5.12.0. - -The plugins include: - -* Visualization plugins to plot Mohr's circles and cross plots using Paraview Python View. - - -PVMohrCirclePlot plugin ---------------------------------- - -.. automodule:: PVplugins.PVMohrCirclePlot diff --git a/docs/geos_posp_docs/visu.PVUtils.rst b/docs/geos_posp_docs/visu.PVUtils.rst deleted file mode 100644 index 6603a216..00000000 --- a/docs/geos_posp_docs/visu.PVUtils.rst +++ /dev/null @@ -1,37 +0,0 @@ -PVUtils Package -=============== - -This packages consists of utilities for Paraview. - - -geos_posp.visu.PVUtils.DisplayOrganizationParaview module ------------------------------------------------------------- - -.. automodule:: geos_posp.visu.PVUtils.DisplayOrganizationParaview - :members: - :undoc-members: - :show-inheritance: - -geos_posp.visu.PVUtils.checkboxFunction module -------------------------------------------------- - -.. automodule:: geos_posp.visu.PVUtils.checkboxFunction - :members: - :undoc-members: - :show-inheritance: - -geos_posp.visu.PVUtils.paraviewTreatments module ---------------------------------------------------- - -.. automodule:: geos_posp.visu.PVUtils.paraviewTreatments - :members: - :undoc-members: - :show-inheritance: - -geos_posp.visu.PVUtils.matplotlibOptions module ----------------------------------------------------------- - -.. automodule:: geos_posp.visu.PVUtils.matplotlibOptions - :members: - :undoc-members: - :show-inheritance: \ No newline at end of file diff --git a/docs/geos_posp_docs/visualization.rst b/docs/geos_posp_docs/visualization.rst deleted file mode 100644 index f63db3ec..00000000 --- a/docs/geos_posp_docs/visualization.rst +++ /dev/null @@ -1,9 +0,0 @@ -Visualization -============= - -.. toctree:: - :maxdepth: 4 - - PVplugins - - visu \ No newline at end of file diff --git a/docs/geos_posp_docs/visu.mohrCircles.rst b/docs/geos_pv_docs/mohrCircles.rst similarity index 62% rename from docs/geos_posp_docs/visu.mohrCircles.rst rename to docs/geos_pv_docs/mohrCircles.rst index 30e9a721..4a72b422 100644 --- a/docs/geos_posp_docs/visu.mohrCircles.rst +++ b/docs/geos_pv_docs/mohrCircles.rst @@ -3,18 +3,18 @@ Mohr's Circle Package This package includes utilities to compute and plot Mohr's Circles using the Python View from Paraview. -geos_posp.visu.mohrCircles.functionsMohrCircle module +geos.pv.utils.mohrCircles.functionsMohrCircle module -------------------------------------------------------- -.. automodule:: geos_posp.visu.mohrCircles.functionsMohrCircle +.. automodule:: geos.pv.utils.mohrCircles.functionsMohrCircle :members: :undoc-members: :show-inheritance: -geos_posp.visu.mohrCircles.plotMohrCircles module +geos.pv.utils.mohrCircles.plotMohrCircles module -------------------------------------------------- -.. automodule:: geos_posp.visu.mohrCircles.plotMohrCircles +.. automodule:: geos.pv.utils.mohrCircles.plotMohrCircles :members: :undoc-members: :show-inheritance: diff --git a/docs/geos_pv_docs/processing.rst b/docs/geos_pv_docs/processing.rst index 726100fd..cb071caf 100644 --- a/docs/geos_pv_docs/processing.rst +++ b/docs/geos_pv_docs/processing.rst @@ -5,7 +5,7 @@ The plugins include: * A reader that parse GEOS output log file; * 3D mesh cleanning plugins; * Processing plugins to compute additional geomechanical properties; -* Visualization plugins to plot Mohr's circles (currently in `geos_posp`) and cross plots using Paraview Python View. +* Visualization plugins to plot Mohr's circles and cross plots using Paraview Python View. PVAttributeMapping @@ -103,4 +103,10 @@ PVGeomechanicsWorkflowVolumeWell plugin PVGeomechanicsCalculator plugin --------------------------------------- -.. automodule:: geos.pv.plugins.PVGeomechanicsCalculator \ No newline at end of file +.. automodule:: geos.pv.plugins.PVGeomechanicsCalculator + + +PVMohrCirclePlot plugin +--------------------------------- + +.. automodule:: geos.pv.plugins.PVMohrCirclePlot diff --git a/docs/geos_pv_docs/pyplotUtils.rst b/docs/geos_pv_docs/pyplotUtils.rst index 6b2b36c4..155eea78 100644 --- a/docs/geos_pv_docs/pyplotUtils.rst +++ b/docs/geos_pv_docs/pyplotUtils.rst @@ -10,4 +10,4 @@ geos.pv.pyplotUtils.matplotlibOptions module .. automodule:: geos.pv.pyplotUtils.matplotlibOptions :members: :undoc-members: - :show-inheritance: \ No newline at end of file + :show-inheritance: diff --git a/docs/geos_pv_docs/utilities.rst b/docs/geos_pv_docs/utilities.rst index 052d49e6..c3d83c45 100644 --- a/docs/geos_pv_docs/utilities.rst +++ b/docs/geos_pv_docs/utilities.rst @@ -11,3 +11,5 @@ Utilities pythonViewUtils utils + + mohrCircles diff --git a/geos-posp/pyproject.toml b/geos-posp/pyproject.toml index ddd3d062..e1c05a89 100644 --- a/geos-posp/pyproject.toml +++ b/geos-posp/pyproject.toml @@ -7,7 +7,7 @@ include-package-data = true [tool.setuptools.packages.find] where = ["src"] -include = ["geos_posp*", "PVplugins*"] +include = ["geos_posp*"] exclude = ['tests*'] [project] @@ -90,5 +90,4 @@ source = ["geos-posp"] omit = [ "*/pyvistaUtils/*", "*/visu/*", - "*/PVplugins/*", ] \ No newline at end of file diff --git a/geos-posp/src/PVplugins/__init__.py b/geos-posp/src/PVplugins/__init__.py deleted file mode 100644 index 37e7c3cf..00000000 --- a/geos-posp/src/PVplugins/__init__.py +++ /dev/null @@ -1,13 +0,0 @@ -import os -import sys - -# Add other packages path to sys path -dir_path = os.path.dirname( os.path.realpath( __file__ ) ) -python_root = '../../..' - -python_modules = ( 'geos-posp', 'geos-utils', 'geos-geomechanics', 'geos-mesh', 'geos-processing' ) - -for m in python_modules: - m_path = os.path.abspath( os.path.join( dir_path, python_root, m, 'src' ) ) - if m_path not in sys.path: - sys.path.insert( 0, m_path ) diff --git a/geos-posp/src/PVplugins/py.typed b/geos-posp/src/PVplugins/py.typed deleted file mode 100644 index e69de29b..00000000 diff --git a/geos-posp/src/geos_posp/visu/PVUtils/DisplayOrganizationParaview.py b/geos-posp/src/geos_posp/visu/PVUtils/DisplayOrganizationParaview.py deleted file mode 100644 index 249ec4b8..00000000 --- a/geos-posp/src/geos_posp/visu/PVUtils/DisplayOrganizationParaview.py +++ /dev/null @@ -1,192 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 -# SPDX-FileCopyrightText: Copyright 2023-2024 TotalEnergies. -# SPDX-FileContributor: Alexandre Benedicto -# ruff: noqa: E402 # disable Module level import not at top of file -from typing import Any - -from paraview.simple import ( # type: ignore[import-not-found] - AssignViewToLayout, CreateLayout, CreateView, Delete, GetLayoutByName, GetLayouts, GetViews, GetViewsInLayout, - RemoveLayout, SetActiveView, -) -from typing_extensions import Self - - -def buildNewLayoutWithPythonView() -> Any: # noqa: ANN401 - """Create a new PythonView layout.""" - # create a new layout - organization: DisplayOrganizationParaview = DisplayOrganizationParaview() - layout_names: list[ str ] = organization.getLayoutsNames() - nb_layouts: int = len( layout_names ) - layoutName: str = "Layout #" + str( nb_layouts + 1 ) - # increment layout index until the layout name is a new one - cpt: int = 1 - while layoutName in layout_names: - layoutName = "Layout #" + str( nb_layouts + cpt ) - cpt += 1 - organization.addLayout( layoutName ) - - # add a new python view to the layout - organization.addViewToLayout( "PythonView", layoutName, 0 ) - return organization.getLayoutViews()[ layoutName ][ 0 ] - - -class DisplayOrganizationParaview: - """Object to manage Paraview layouts.""" - - def __init__( self: Self ) -> None: - """Keeps track of Paraview layouts and views when created or removed.""" - self._layouts_keys: list[ Any ] = [] - self._layout_names: list[ str ] = [] - self._views_cpt: int = 0 - self._layout_views: dict[ str, Any ] = {} - self._views_name: dict[ str, Any ] = {} - self.initLayouts() - self.initLayoutViews() - - def initLayouts( self: Self ) -> None: - """Initialize layouts.""" - self._layouts_keys = list( GetLayouts().keys() ) - self._layouts_names = [] - for layout_tuple in self._layouts_keys: - self._layouts_names.append( layout_tuple[ 0 ] ) - - def getLayoutsKeys( self: Self ) -> list[ Any ]: - """Get layout keys. - - Returns: - list[Any]: list of layout keys. - """ - return self._layouts_keys - - def getLayoutsNames( self: Self ) -> list[ str ]: - """Get layout names. - - Returns: - list[str]: list of layout names. - """ - return self._layouts_names - - def getNumberLayouts( self: Self ) -> int: - """Get the number of layouts. - - Returns: - int: number of layouts. - """ - return len( self._layouts_keys ) - - def getViewsCpt( self: Self ) -> int: - """Get the number of views. - - Returns: - int: number of views. - """ - return self._views_cpt - - def addOneToCpt( self: Self ) -> None: - """Increment number of views.""" - self._views_cpt += 1 - - def initLayoutViews( self: Self ) -> None: - """Initialize layout views.""" - self._views_name = {} - self._layout_views = {} - all_views: list[ Any ] = GetViews() - layouts_keys: list[ Any ] = self.getLayoutsKeys() - layout_names: list[ str ] = self.getLayoutsNames() - for i in range( self.getNumberLayouts() ): - self._layout_views[ layout_names[ i ] ] = [] - views_in_layout = GetViewsInLayout( GetLayouts()[ layouts_keys[ i ] ] ) - for view in all_views: - if view in views_in_layout: - self._layout_views[ layout_names[ i ] ].append( view ) - name_view: str = "view" + str( self.getViewsCpt() ) - self._views_name[ name_view ] = view - self.addOneToCpt() - - def getLayoutViews( self: Self ) -> dict[ str, Any ]: - """Get layout views. - - Returns: - dict[Any:Any]: dictionnary of layout views. - """ - return self._layout_views - - def getViewsName( self: Self ) -> dict[ str, Any ]: - """Get view names. - - Returns: - list[str]: list of view names. - """ - return self._views_name - - def updateOrganization( self: Self ) -> None: - """Update layouts.""" - self._views_cpt = 0 - self.initLayouts() - self.initLayoutViews() - - def addLayout( self: Self, new_layout_name: str ) -> None: - """Add a layout. - - Args: - new_layout_name (str): name of the new layout. - """ - if new_layout_name not in self.getLayoutsNames(): - CreateLayout( new_layout_name ) - else: - print( f'This layout name "{new_layout_name}" is already used, please pick a new one.\n' ) - self.updateOrganization() - - def removeLayout( self: Self, layout_name: str ) -> None: - """Remove a layout. - - Args: - layout_name (str): name of the layout to remove. - """ - if layout_name not in self.getLayoutsNames(): - RemoveLayout( GetLayoutByName( layout_name ) ) - else: - print( f'This layout name "{layout_name}" does not exist.' ) - self.updateOrganization() - - def addViewToLayout( self: Self, viewType: str, layout_name: str, position: int ) -> None: - """Add a view to a layout. - - Args: - viewType (str): type of view. - layout_name (str): name of the layout. - position (int): position of the view. - """ - SetActiveView( None ) - layout_to_use = GetLayoutByName( layout_name ) - new_view = CreateView( viewType ) - AssignViewToLayout( view=new_view, layout=layout_to_use, hint=position ) - self.updateOrganization() - - def RemoveViewFromLayout( self: Self, view_name: str, layout_name: str, position: int ) -> None: - """Remove a view from a layout. - - Args: - view_name (str): name of view. - layout_name (str): name of the layout. - position (int): position of the view. - """ - views_name: dict[ str, Any ] = self.getViewsName() - view_to_delete = views_name[ view_name ] - SetActiveView( view_to_delete ) - Delete( view_to_delete ) - del view_to_delete - layout_to_use = GetLayoutByName( layout_name ) - layout_to_use.Collapse( position ) - self.updateOrganization() - - def SwapCellsInLayout( self: Self, layout_name: str, position1: int, position2: int ) -> None: - """Swap views in a layout. - - Args: - layout_name (str): name of the layout. - position1 (int): first position of the view. - position2 (int): second position of the view. - """ - layout_to_use = GetLayoutByName( layout_name ) - layout_to_use.SwapCells( position1, position2 ) diff --git a/geos-posp/src/geos_posp/visu/PVUtils/checkboxFunction.py b/geos-posp/src/geos_posp/visu/PVUtils/checkboxFunction.py deleted file mode 100644 index 6e0a250e..00000000 --- a/geos-posp/src/geos_posp/visu/PVUtils/checkboxFunction.py +++ /dev/null @@ -1,22 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 -# SPDX-FileCopyrightText: Copyright 2023-2024 TotalEnergies. -# SPDX-FileContributor: Alexandre Benedicto -# ruff: noqa -# type: ignore -def createModifiedCallback( anobject ): - """Helper for the creation and use of vtkDataArraySelection in ParaView. - - Args: - anobject: any object. - """ - import weakref - - weakref_obj = weakref.ref( anobject ) - anobject = None - - def _markmodified( *args, **kwars ): - o = weakref_obj() - if o is not None: - o.Modified() - - return _markmodified diff --git a/geos-posp/src/geos_posp/visu/PVUtils/matplotlibOptions.py b/geos-posp/src/geos_posp/visu/PVUtils/matplotlibOptions.py deleted file mode 100644 index 311678ce..00000000 --- a/geos-posp/src/geos_posp/visu/PVUtils/matplotlibOptions.py +++ /dev/null @@ -1,88 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 -# SPDX-FileCopyrightText: Copyright 2023-2024 TotalEnergies. -# SPDX-FileContributor: Martin Lemay -# ruff: noqa: E402 # disable Module level import not at top of file - -from enum import Enum - -from typing_extensions import Self - - -class OptionSelectionEnum( Enum ): - - def __init__( self: Self, displayName: str, optionValue: str ) -> None: - """Define the enumeration to options for Paraview selectors. - - Args: - displayName (str): name displayed in the selector - optionValue (str): value used by matplotlib. - - Defaults to None (same optionName as displayName) - """ - self.displayName: str = displayName - self.optionValue: str = optionValue - - -class LegendLocationEnum( OptionSelectionEnum ): - BEST = ( "best", "best" ) - UPPER_LEFT = ( "upper left", "upper left" ) - UPPER_CENTER = ( "upper center", "upper center" ) - UPPER_RIGHT = ( "upper right", "upper right" ) - CENTER_LEFT = ( "center left", "center left" ) - CENTER = ( "center", "center" ) - CENTER_RIGHT = ( "center right", "center right" ) - LOWER_LEFT = ( "lower left", "lower left" ) - LOWER_CENTER = ( "lower center", "lower center" ) - LOWER_RIGHT = ( "lower right", "lower right" ) - - -class FontStyleEnum( OptionSelectionEnum ): - NORMAL = ( "normal", "normal" ) - ITALIC = ( "italic", "italic" ) - OBLIQUE = ( "oblique", "oblique" ) - - -class FontWeightEnum( OptionSelectionEnum ): - NORMAL = ( "normal", "normal" ) - BOLD = ( "bold", "bold" ) - HEAVY = ( "heavy", "heavy" ) - LIGHT = ( "light", "light" ) - - -class LineStyleEnum( OptionSelectionEnum ): - NONE = ( "None", "None" ) - SOLID = ( "solid", "-" ) - DASHED = ( "dashed", "--" ) - DASHDOT = ( "dashdot", "-." ) - DOTTED = ( "dotted", ":" ) - - -class MarkerStyleEnum( OptionSelectionEnum ): - NONE = ( "None", "" ) - POINT = ( "point", "." ) - CIRCLE = ( "circle", "o" ) - TRIANGLE = ( "triangle", "^" ) - SQUARE = ( "square", "s" ) - STAR = ( "star", "*" ) - DIAMOND = ( "diamond", "D" ) - PLUS = ( "plus", "+" ) - X = ( "x", "x" ) - - -def optionEnumToXml( enumObj: OptionSelectionEnum ) -> str: - """Creates an enumeration domain from an OptionSelectionEnum object. - - Dedicated to the dropdown widgets of paraview plugin. - - Args: - enumObj (OptionSelectionEnum): Enumeration values to put in the dropdown - widget. - - Returns: - str: the XML string. - """ - xml: str = """""" - for i, unitObj in enumerate( list( enumObj ) ): # type: ignore[call-overload] - xml += f"""""" - xml += """""" - return xml diff --git a/geos-posp/src/geos_posp/visu/PVUtils/paraviewTreatments.py b/geos-posp/src/geos_posp/visu/PVUtils/paraviewTreatments.py deleted file mode 100644 index 239df5f8..00000000 --- a/geos-posp/src/geos_posp/visu/PVUtils/paraviewTreatments.py +++ /dev/null @@ -1,588 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 -# SPDX-FileCopyrightText: Copyright 2023-2024 TotalEnergies. -# SPDX-FileContributor: Alexandre Benedicto, Martin Lemay -# ruff: noqa: E402 # disable Module level import not at top of file -from enum import Enum -from typing import Any, Union - -import numpy as np -import numpy.typing as npt -import pandas as pd # type: ignore[import-untyped] -from geos.utils.GeosOutputsConstants import ( - ComponentNameEnum, - GeosMeshOutputsEnum, -) -from packaging.version import Version - -# TODO: remove this condition when all codes are adapted for Paraview 6.0 -import vtk -if Version( vtk.__version__ ) >= Version( "9.5" ): - from vtkmodules.vtkFiltersParallel import vtkMergeBlocks -else: - from paraview.modules.vtkPVVTKExtensionsMisc import ( # type: ignore[import-not-found] - vtkMergeBlocks, ) - -from paraview.simple import ( # type: ignore[import-not-found] - FindSource, GetActiveView, GetAnimationScene, GetDisplayProperties, GetSources, servermanager, -) -from vtkmodules.vtkCommonCore import ( - vtkDataArray, - vtkDataArraySelection, - vtkDoubleArray, - vtkPoints, -) -from vtkmodules.vtkCommonDataModel import ( - vtkCompositeDataSet, - vtkDataObject, - vtkMultiBlockDataSet, - vtkPolyData, - vtkTable, - vtkUnstructuredGrid, -) - -from geos.mesh.utils.arrayHelpers import ( - getArrayInObject, - isAttributeInObject, -) - -# valid sources for Python view configurator -# TODO: need to be consolidated -HARD_CODED_VALID_PVC_TYPE: set[ str ] = { "GeosLogReader", "RenameArrays" } - - -def vtkTableToDataframe( table: vtkTable ) -> pd.DataFrame: - """From a vtkTable, creates and returns a pandas dataframe. - - Args: - table (vtkTable): vtkTable object. - - Returns: - pd.DataFrame: Pandas dataframe. - """ - data: list[ dict[ str, Any ] ] = [] - for rowIndex in range( table.GetNumberOfRows() ): - rowData: dict[ str, Any ] = {} - for colIndex in range( table.GetNumberOfColumns() ): - colName: str = table.GetColumnName( colIndex ) - cellValue: Any = table.GetValue( rowIndex, colIndex ) - # we have a vtkVariant value, we need a float - cellValueF: float = cellValue.ToFloat() - rowData[ colName ] = cellValueF - data.append( rowData ) - df: pd.DataFrame = pd.DataFrame( data ) - return df - - -def vtkPolyDataToPointsDataframe( polydata: vtkPolyData ) -> pd.DataFrame: - """Creates a pandas dataframe containing points data from vtkPolyData. - - Args: - polydata (vtkPolyData): vtkPolyData object. - - Returns: - pd.DataFrame: Pandas dataframe containing the points data. - """ - points: vtkPoints = polydata.GetPoints() - assert points is not None, "Points is undefined." - nbrPoints: int = points.GetNumberOfPoints() - data: dict[ str, Any ] = { - "Point ID": np.empty( nbrPoints ), - "PointsX": np.empty( nbrPoints ), - "PointsY": np.empty( nbrPoints ), - "PointsZ": np.empty( nbrPoints ), - } - for pointID in range( nbrPoints ): - point: tuple[ float, float, float ] = points.GetPoint( pointID ) - data[ "Point ID" ][ pointID ] = pointID - data[ "PointsX" ][ pointID ] = point[ 0 ] - data[ "PointsY" ][ pointID ] = point[ 1 ] - data[ "PointsZ" ][ pointID ] = point[ 2 ] - pointData = polydata.GetPointData() - nbrArrays: int = pointData.GetNumberOfArrays() - for i in range( nbrArrays ): - arrayToUse = pointData.GetArray( i ) - arrayName: str = pointData.GetArrayName( i ) - subArrayNames: list[ str ] = findSubArrayNames( arrayToUse, arrayName ) - # Collect the data for each sub array - for ind, name in enumerate( subArrayNames ): - data[ name ] = np.empty( nbrPoints ) - for k in range( nbrPoints ): - # Every element of the tuple correspond to one distinct - # sub array so we only need one value at a time - value: float = arrayToUse.GetTuple( k )[ ind ] - data[ name ][ k ] = value - df: pd.DataFrame = pd.DataFrame( data ).set_index( "Point ID" ) - return df - - -def vtkUnstructuredGridCellsToDataframe( grid: vtkUnstructuredGrid ) -> pd.DataFrame: - """Creates a pandas dataframe containing points data from vtkUnstructuredGrid. - - Args: - grid (vtkUnstructuredGrid): vtkUnstructuredGrid object. - - Returns: - pd.DataFrame: Pandas dataframe. - """ - cellIdAttributeName = GeosMeshOutputsEnum.VTK_ORIGINAL_CELL_ID.attributeName - cellData = grid.GetCellData() - numberCells: int = grid.GetNumberOfCells() - data: dict[ str, Any ] = {} - for i in range( cellData.GetNumberOfArrays() ): - arrayToUse = cellData.GetArray( i ) - arrayName: str = cellData.GetArrayName( i ) - subArrayNames: list[ str ] = findSubArrayNames( arrayToUse, arrayName ) - # Collect the data for each sub array - for ind, name in enumerate( subArrayNames ): - data[ name ] = np.empty( numberCells ) - for k in range( numberCells ): - # Every element of the tuple correspond to one distinct - # sub array so we only need one value at a time - value: float = arrayToUse.GetTuple( k )[ ind ] - data[ name ][ k ] = value - df: pd.DataFrame = pd.DataFrame( data ).astype( { cellIdAttributeName: int } ) - - # set cell ids as index - - # df = df.astype({cellIdAttributeName: int}) - return df.set_index( cellIdAttributeName ) - - -def vtkToDataframe( dataset: vtkDataObject ) -> pd.DataFrame: - """Creates a dataframe containing points data from vtkTable or vtkPolyData. - - Args: - dataset (Any): dataset to convert if possible. - - Returns: - pd.DataFrame: if the dataset is in the right format. - """ - if isinstance( dataset, vtkTable ): - return vtkTableToDataframe( dataset ) - elif isinstance( dataset, vtkPolyData ): - return vtkPolyDataToPointsDataframe( dataset ) - elif isinstance( dataset, vtkUnstructuredGrid ): - return vtkUnstructuredGridCellsToDataframe( dataset ) - else: - raise AssertionError( f"Invalid dataset format {type(dataset)}. " + - "Supported formats are: vtkTable, vtkpolyData and vtkUnstructuredGrid" ) - - -def findSubArrayNames( vtkArray: vtkDataArray, arrayName: str ) -> list[ str ]: - """Get sub array names from multi array attributes. - - Because arrays in ParaView can be of multiple dimensions, - it can be difficult to convert these arrays to numpy arrays. - Therefore, we can split the original array into multiple sub - one dimensional arrays. In that case, new sub names need to be - derived from the original array to be used. - - Args: - vtkArray (vtkDataArray): Array from vtk library. - arrayName (str): Name of the array. - - Returns: - list[str]: Sub array names from original array name. - """ - # The ordering of six elements can seem odd but is adapted to - # Geos output format of stress as : - # sigma11, sigma22, sigma33, sigma23, sigma13, sigma12 - sixComponents: tuple[ str, str, str, str, str, str ] = ComponentNameEnum.XYZ.value - nbrComponents: int = vtkArray.GetNumberOfComponents() - subArrayNames: list[ str ] = [] - if nbrComponents == 1: - subArrayNames.append( arrayName ) - elif nbrComponents < 6: - for j in range( nbrComponents ): - subArrayNames.append( arrayName + "_" + sixComponents[ j ] ) - else: - for j in range( nbrComponents ): - subArrayNames.append( arrayName + "_" + str( j ) ) - return subArrayNames - - -def getDataframesFromMultipleVTKSources( sourceNames: set[ str ], commonColumn: str ) -> list[ pd.DataFrame ]: - """Creates the dataframe from each source if they have the commonColumn. - - Args: - sourceNames (set[str]): list of sources. - commonColumn (str): common column name. - - Returns: - list[pd.DataFrame]: output dataframe. - """ - # indexSource: int = commonColumn.rfind("__") - # commonColumnNoSource: str = commonColumn[:indexSource] - validDataframes: list[ pd.DataFrame ] = [] - for name in sourceNames: - source = FindSource( name ) - assert source is not None, "Source is undefined." - dataset = servermanager.Fetch( source ) - assert dataset is not None, "Dataset is undefined." - currentDF: pd.DataFrame = vtkToDataframe( dataset ) - if commonColumn in currentDF.columns: - dfModified = currentDF.rename( - columns={ col: col + "__" + name - for col in currentDF.columns if col != commonColumn } ) - validDataframes.append( dfModified ) - else: - print( f"The source <<{name}>> could not be used" + " to plot because the variable named <<" + - f"{commonColumn}>> could not be found." ) - return validDataframes - - -def mergeDataframes( dataframes: list[ pd.DataFrame ], commonColumn: str ) -> pd.DataFrame: - """Merge all dataframes into a single one by using the common column. - - Args: - dataframes (list[pd.DataFrame]): List of dataframes from - getDataframesFromMultipleVTKSources. - commonColumn (str): Name of the only common column between - all of the dataframes. - - Returns: - pd.DataFrame: Merged dataframes into a single one by 'outer' - on the commonColumn. - """ - assert len( dataframes ) > 0 - if len( dataframes ) == 1: - return dataframes[ 0 ] - else: - df0: pd.DataFrame = dataframes[ 0 ] - df1: pd.DataFrame = dataframes[ 1 ] - merged: pd.DataFrame = df0.merge( df1, on=commonColumn, how="outer" ) - if len( dataframes ) > 2: - for df in dataframes[ 2: ]: - merged = merged.merge( df, on=commonColumn, how="outer" ) - return merged - - -def addDataframeColumnsToVtkPolyData( polyData: vtkPolyData, df: pd.DataFrame ) -> vtkPolyData: - """Add columns from a dataframe to a vtkPolyData. - - Args: - polyData (vtkPolyData): vtkPolyData before modifcation. - df (pd.DataFrame): Pandas dataframe. - - Returns: - vtkPolyData: vtkPolyData with new arrays. - """ - for column_name in df.columns: - column = df[ column_name ].values - array = vtkDoubleArray() - array.SetName( column_name ) - array.SetNumberOfValues( polyData.GetNumberOfPoints() ) - for i in range( polyData.GetNumberOfPoints() ): - array.SetValue( i, column[ i ] ) - polyData.GetPointData().AddArray( array ) - - # Update vtkPolyData object - polyData.GetPointData().Modified() - polyData.Modified() - return polyData - - -# Functions to help the processing of PythonViewConfigurator - - -def getPossibleSourceNames() -> set[ str ]: - """Get the list of valid source names for PythonViewConfigurator. - - In PythonViewConfigurator, multiple sources can be considered as - valid inputs. We want the user to know the names of every of these - sources that can be used to plot data. This function therefore identifies - which source names are valid to be used later as sources. - - Returns: - set[str]: Source names in the paraview pipeline. - """ - # get all sources different from PythonViewConfigurator - validNames: set[ str ] = set() - for k in GetSources(): - sourceName: str = k[ 0 ] - source = FindSource( sourceName ) - if ( source is not None ) and ( "PythonViewConfigurator" not in source.__str__() ): - dataset = servermanager.Fetch( source ) - if dataset.IsA( "vtkPolyData" ) or dataset.IsA( "vtkTable" ): - validNames.add( sourceName ) - return validNames - - -def usefulSourceNamesPipeline() -> set[ str ]: - """Get the list of valid pipelines for PythonViewConfigurator. - - When using the PythonViewConfigurator, we want to check if the sources - in the ParaView pipeline are compatible with what the filter can take as - input. So this function scans every sources of the pipeline and if it - corresponds to one of the hardcoded valid types, we keep the name. - They are right now : ["GeosLogReader", "RenameArrays"] - - Returns: - set[str]: [sourceName1, ..., sourceNameN] - """ - usefulSourceNames: set[ str ] = set() - allSourceNames: set[ str ] = { n[ 0 ] for n, s in GetSources().items() } - for name in allSourceNames: - source = FindSource( name ) - if type( source ).__name__ in HARD_CODED_VALID_PVC_TYPE: - usefulSourceNames.add( name ) - return usefulSourceNames - - -def getDatasFromSources( sourceNames: set[ str ] ) -> dict[ str, pd.DataFrame ]: - """Get the data from input sources. - - Args: - sourceNames (set[str]): [sourceName1, ..., sourceNameN] - - Returns: - dict[[str, pd.DataFrame]]: dictionary where source names are keys and - dataframe are values. - { sourceName1: servermanager.Fetch(FindSource(sourceName1)), - ... - sourceNameN: servermanager.Fetch(FindSource(sourceNameN)) } - """ - usefulDatas: dict[ str, Any ] = {} - for name in sourceNames: - dataset = servermanager.Fetch( FindSource( name ) ) - usefulDatas[ name ] = dataset - return usefulDatas - - -def usefulVisibleDatasPipeline() -> dict[ str, Any ]: - """Get the list of visible pipelines. - - When using the PythonViewConfigurator, we want to collect the data of - each source that is visible in the paraview pipeline and that is - compatible as input data for the filter. Therefore, only certain types of - sources will be considered as valid. They are right now : - ["GeosLogReader", "RenameArrays"] - - Finally, if the sources are visible and valid, we access their data and - return the names of the source and their respective data. - - Returns: - dict[str, 'vtkInformation']: dictionary of source names and data from - pipeline. - { sourceName1: servermanager.Fetch(FindSource(sourceName1)), - ... - sourceNameN: servermanager.Fetch(FindSource(sourceNameN)) } - """ - usefulDatas: dict[ str, Any ] = {} - sourceNamesVisible: set[ str ] = set() - for n, s in GetSources().items(): - if servermanager.GetRepresentation( s, GetActiveView() ) is not None: - displayProperties = GetDisplayProperties( s, view=GetActiveView() ) - if ( displayProperties is not None ) and ( displayProperties.Visibility == 1 ): - sourceNamesVisible.add( n[ 0 ] ) - - for name in sourceNamesVisible: - source = FindSource( name ) - if type( source ).__name__ in HARD_CODED_VALID_PVC_TYPE: - usefulDatas[ name ] = servermanager.Fetch( FindSource( name ) ) - return usefulDatas - - -def isFilter( sourceName: str ) -> bool: - """Identify if a source name can link to a filter in the ParaView pipeline. - - Args: - sourceName (str): name of a source object in the pipeline - - Returns: - bool: True if filter, False instead. - """ - source: Any = FindSource( sourceName ) - if source is None: - print( f"sourceName <<{sourceName}>> does not exist in the pipeline" ) - return False - else: - try: - test: Any = source.GetClientSideObject().GetInputAlgorithm() # noqa: F841 - return True - except Exception: - return False - - -def getFilterInput( sourceName: str ) -> vtkDataObject: - """Access the vtk dataset that is used as input for a filter. - - Args: - sourceName (str): name of a source object in the pipeline. - - Returns: - Any: The vtk dataset that serves as input for the filter. - """ - filtre = FindSource( sourceName ) - assert filtre is not None, "Source is undefined." - clientSideObject = filtre.GetClientSideObject() - assert clientSideObject is not None, "Client Side Object is undefined." - inputAlgo = clientSideObject.GetInputAlgorithm() - assert inputAlgo is not None, "Input Algorithm is undefined." - inputValues = inputAlgo.GetInput() - if isinstance( inputValues, vtkDataObject ): - return inputValues - return vtkDataObject() - - -def getArrayChoices( array: vtkDataArraySelection ) -> list[ str ]: - """Extracts the column names of input array when they are enabled. - - Args: - array (vtkDataArraySelection): input data - - Returns: - set[str]: [columnName1, ..., columnNameN] - """ - checkedColumns: list[ str ] = [] - for i in range( array.GetNumberOfArrays() ): - columnName: str = array.GetArrayName( i ) - if array.ArrayIsEnabled( columnName ): - checkedColumns.append( columnName ) - return checkedColumns - - -def integrateSourceNames( sourceNames: set[ str ], arrayChoices: set[ str ] ) -> set[ str ]: - """Aggregate source and arrayChoices names. - - When creating the user choices in PythonViewConfigurator, you need - to take into account both the source names and the choices of curves - to have user choices corresponding to the column names of the dataframe - with the data to be plot. - - Args: - sourceNames (set[str]): Name of sources found in ParaView pipeline. - arrayChoices (set[str]): Column names of the vtkdataarrayselection. - - Returns: - set[str]: [sourceName1__choice1, sourceName1__choice2, - ..., sourceNameN__choiceN] - """ - completeNames: set[ str ] = set() - for sourceName in sourceNames: - for choice in arrayChoices: - completeName: str = choice + "__" + sourceName - completeNames.add( completeName ) - return completeNames - - -def getVtkOriginalCellIds( mesh: Union[ vtkMultiBlockDataSet, vtkCompositeDataSet, vtkDataObject ] ) -> list[ str ]: - """Get vtkOriginalCellIds from a vtkUnstructuredGrid object. - - Args: - mesh (vtkMultiBlockDataSet|vtkCompositeDataSet|vtkDataObject): input mesh. - - Returns: - list[str]: ids of the cells. - """ - # merge blocks for vtkCompositeDataSet - mesh2: vtkUnstructuredGrid = mergeFilterPV( mesh ) - name: str = GeosMeshOutputsEnum.VTK_ORIGINAL_CELL_ID.attributeName - assert isAttributeInObject( mesh2, name, False ), f"Attribute {name} is not in the mesh." - return [ str( int( ide ) ) for ide in getArrayInObject( mesh2, name, False ) ] - - -def strEnumToEnumerationDomainXml( enumObj: Enum ) -> str: - """Creates an enumeration domain from an Enum objec. - - Creates an enumeration domain from an Enum objec - for the dropdown widgets of paraview plugin. - - Args: - enumObj (Enum): Enumeration values to put in the dropdown widget. - - Returns: - str: the XML string. - """ - xml: str = """""" - for i, unitObj in enumerate( list( enumObj ) ): # type: ignore[call-overload] - xml += f"""""" - xml += """""" - return xml - - -def strListToEnumerationDomainXml( properties: Union[ list[ str ], set[ str ] ] ) -> str: - """Creates an enumeration domain from a list of strings. - - Creates an enumeration domain from a list of strings - for the dropdown widgets of paraview plugin. - - Args: - properties (set[str] | list[str]): Properties to put in the dropdown widget. - - Returns: - str: the XML string. - """ - xml: str = """""" - for i, prop in enumerate( list( properties ) ): - xml += f"""""" - xml += """""" - return xml - - -def dataframeForEachTimestep( sourceName: str ) -> dict[ str, pd.DataFrame ]: - """Get the data from source at each time step. - - In ParaView, a source object can contain data for multiple - timesteps. If so, knowing the source name, we can access its data - for each timestep and store it in a dict where the keys are the - timesteps and the values the data at each one of them. - - Args: - sourceName (str): Name of the source in ParaView pipeline. - - Returns: - dict[str, pd.DataFrame]: dictionary where time is the key and dataframe - is the value. - """ - animationScene = GetAnimationScene() - assert animationScene is not None, "animationScene is undefined." - # we set the animation to the initial timestep - animationScene.GoToFirst() - source = FindSource( sourceName ) - dataset: vtkDataObject = servermanager.Fetch( source ) - assert dataset is not None, "Dataset is undefined." - dataset2: vtkUnstructuredGrid = mergeFilterPV( dataset ) - time: str = str( animationScene.TimeKeeper.Time ) - dfPerTimestep: dict[ str, pd.DataFrame ] = { time: vtkToDataframe( dataset2 ) } - # then we iterate on the other timesteps of the source - for _ in range( animationScene.NumberOfFrames ): # type: ignore - animationScene.GoToNext() - source = FindSource( sourceName ) - dataset = servermanager.Fetch( source ) - dataset2 = mergeFilterPV( dataset ) - time = str( animationScene.TimeKeeper.Time ) - dfPerTimestep[ time ] = vtkToDataframe( dataset2 ) - return dfPerTimestep - - -def getTimeStepIndex( time: float, timeSteps: npt.NDArray[ np.float64 ] ) -> int: - """Get the time step index of input time from the list of time steps. - - Args: - time (float): time - timeSteps (npt.NDArray[np.float64]): Array of time steps - - Returns: - int: time step index - """ - indexes: npt.NDArray[ np.int64 ] = np.where( np.isclose( timeSteps, time ) )[ 0 ] - assert ( indexes.size > 0 ), f"Current time {time} does not exist in the selected object." - return int( indexes[ 0 ] ) - - -def mergeFilterPV( input: vtkDataObject, ) -> vtkUnstructuredGrid: - """Apply Paraview merge block filter. - - Args: - input (vtkMultiBlockDataSet | vtkCompositeDataSet | vtkDataObject): composite - object to merge blocks - - Returns: - vtkUnstructuredGrid: merged block object - - """ - mergeFilter: vtkMergeBlocks = vtkMergeBlocks() - mergeFilter.SetInputData( input ) - mergeFilter.Update() - return mergeFilter.GetOutputDataObject( 0 ) diff --git a/geos-posp/src/geos_posp/visu/__init__.py b/geos-posp/src/geos_posp/visu/__init__.py deleted file mode 100644 index 8b137891..00000000 --- a/geos-posp/src/geos_posp/visu/__init__.py +++ /dev/null @@ -1 +0,0 @@ - diff --git a/geos-pv/examples/PVproxyWidgetsDynamic.py b/geos-pv/examples/PVproxyWidgetsDynamic.py index 257d05dd..b0e6d81b 100644 --- a/geos-pv/examples/PVproxyWidgetsDynamic.py +++ b/geos-pv/examples/PVproxyWidgetsDynamic.py @@ -16,7 +16,7 @@ from geos.pv.utils.paraviewTreatments import ( strListToEnumerationDomainXml, strEnumToEnumerationDomainXml, getArrayChoices ) -from geos_posp.visu.PVUtils.checkboxFunction import ( # type: ignore[attr-defined] +from geos.pv.utils.checkboxFunction import ( # type: ignore[attr-defined] createModifiedCallback, ) from vtkmodules.util.vtkAlgorithm import VTKPythonAlgorithmBase diff --git a/geos-posp/src/PVplugins/PVMohrCirclePlot.py b/geos-pv/src/geos/pv/plugins/PVMohrCirclePlot.py similarity index 96% rename from geos-posp/src/PVplugins/PVMohrCirclePlot.py rename to geos-pv/src/geos/pv/plugins/PVMohrCirclePlot.py index 5a04106c..b8f23800 100644 --- a/geos-posp/src/PVplugins/PVMohrCirclePlot.py +++ b/geos-pv/src/geos/pv/plugins/PVMohrCirclePlot.py @@ -2,8 +2,8 @@ # SPDX-FileCopyrightText: Copyright 2023-2024 TotalEnergies. # SPDX-FileContributor: Alexandre Benedicto, Martin Lemay # ruff: noqa: E402 # disable Module level import not at top of file -import os import sys +from pathlib import Path from enum import Enum from typing import Any, Union, cast @@ -22,15 +22,14 @@ vtkUnstructuredGrid, ) -dir_path = os.path.dirname( os.path.realpath( __file__ ) ) -parent_dir_path = os.path.dirname( dir_path ) -if parent_dir_path not in sys.path: - sys.path.append( parent_dir_path ) +# update sys.path to load all GEOS Python Package dependencies +geos_pv_path: Path = Path( __file__ ).parent.parent.parent.parent.parent +sys.path.insert( 0, str( geos_pv_path / "src" ) ) +from geos.pv.utils.config import update_paths + +update_paths() -import PVplugins # noqa: F401 -import geos_posp.visu.mohrCircles.functionsMohrCircle as mcf -import geos_posp.visu.PVUtils.paraviewTreatments as pvt from geos.geomechanics.model.MohrCircle import MohrCircle from geos.utils.enumUnits import Pressure, enumerationDomainUnit from geos.utils.GeosOutputsConstants import ( @@ -45,11 +44,20 @@ ) from geos.mesh.utils.arrayHelpers import getArrayInObject from geos.mesh.utils.multiblockModifiers import mergeBlocks -from geos_posp.visu.PVUtils.checkboxFunction import ( # type: ignore[attr-defined] + + +# import geos_posp.visu.mohrCircles.functionsMohrCircle as mcf +import geos.pv.utils.mohrCircles.functionsMohrCircle as mcf +# import geos_posp.visu.PVUtils.paraviewTreatments as pvt +import geos.pv.utils.paraviewTreatments as pvt +from geos.pv.utils.checkboxFunction import ( # type: ignore[attr-defined] +# from geos_posp.visu.PVUtils.checkboxFunction import ( # type: ignore[attr-defined] createModifiedCallback, ) -from geos_posp.visu.PVUtils.DisplayOrganizationParaview import ( +# from geos_posp.visu.PVUtils.DisplayOrganizationParaview import ( +from geos.pv.utils.DisplayOrganizationParaview import ( buildNewLayoutWithPythonView, ) -from geos_posp.visu.PVUtils.matplotlibOptions import ( +# from geos_posp.visu.PVUtils.matplotlibOptions import ( +from geos.pv.pyplotUtils.matplotlibOptions import ( FontStyleEnum, FontWeightEnum, LegendLocationEnum, @@ -84,7 +92,8 @@ @smproxy.filter( name="PVMohrCirclePlot", label="Plot Mohr's Circles" ) @smhint.xml( """ - + # + """ ) @smproperty.input( name="Input", port_index=0 ) diff --git a/geos-posp/src/geos_posp/visu/mohrCircles/__init__.py b/geos-pv/src/geos/pv/utils/mohrCircles/__init__.py similarity index 100% rename from geos-posp/src/geos_posp/visu/mohrCircles/__init__.py rename to geos-pv/src/geos/pv/utils/mohrCircles/__init__.py diff --git a/geos-posp/src/geos_posp/visu/mohrCircles/functionsMohrCircle.py b/geos-pv/src/geos/pv/utils/mohrCircles/functionsMohrCircle.py similarity index 99% rename from geos-posp/src/geos_posp/visu/mohrCircles/functionsMohrCircle.py rename to geos-pv/src/geos/pv/utils/mohrCircles/functionsMohrCircle.py index 0d4042e3..a4f56481 100644 --- a/geos-posp/src/geos_posp/visu/mohrCircles/functionsMohrCircle.py +++ b/geos-pv/src/geos/pv/utils/mohrCircles/functionsMohrCircle.py @@ -9,7 +9,7 @@ from geos.geomechanics.model.MohrCircle import MohrCircle from geos.geomechanics.model.MohrCoulomb import MohrCoulomb -from geos_posp.visu.mohrCircles import ( +from geos.pv.utils.mohrCircles import ( MOHR_CIRCLE_ANALYSIS_MAIN, MOHR_CIRCLE_PATH, ) diff --git a/geos-posp/src/geos_posp/visu/mohrCircles/mainMohrCircles.py b/geos-pv/src/geos/pv/utils/mohrCircles/mainMohrCircles.py similarity index 86% rename from geos-posp/src/geos_posp/visu/mohrCircles/mainMohrCircles.py rename to geos-pv/src/geos/pv/utils/mohrCircles/mainMohrCircles.py index 7eb27a13..8b341d7f 100644 --- a/geos-posp/src/geos_posp/visu/mohrCircles/mainMohrCircles.py +++ b/geos-pv/src/geos/pv/utils/mohrCircles/mainMohrCircles.py @@ -7,8 +7,8 @@ import matplotlib.pyplot as plt from paraview import python_view - import geos_posp.visu.mohrCircles.functionsMohrCircle as mcf - import geos_posp.visu.mohrCircles.plotMohrCircles as pmc + import geos.pv.utils.mohrCircles.functionsMohrCircle as mcf + import geos.pv.utils.mohrCircles.plotMohrCircles as pmc plt.close() diff --git a/geos-posp/src/geos_posp/visu/mohrCircles/plotMohrCircles.py b/geos-pv/src/geos/pv/utils/mohrCircles/plotMohrCircles.py similarity index 98% rename from geos-posp/src/geos_posp/visu/mohrCircles/plotMohrCircles.py rename to geos-pv/src/geos/pv/utils/mohrCircles/plotMohrCircles.py index d7c21c6c..37ecf022 100644 --- a/geos-posp/src/geos_posp/visu/mohrCircles/plotMohrCircles.py +++ b/geos-pv/src/geos/pv/utils/mohrCircles/plotMohrCircles.py @@ -15,8 +15,8 @@ from matplotlib.figure import Figure # type: ignore[import-untyped] from matplotlib.lines import Line2D # type: ignore[import-untyped] -import geos_posp.visu.mohrCircles.functionsMohrCircle as mcf -from geos_posp.visu.PVUtils.matplotlibOptions import ( +import geos.pv.utils.mohrCircles.functionsMohrCircle as mcf +from geos.pv.pyplotUtils.matplotlibOptions import ( FontStyleEnum, FontWeightEnum, LegendLocationEnum, diff --git a/geos-pv/tests/testsFunctionsGeosLogReader.py b/geos-pv/tests/testsFunctionsGeosLogReader.py index 24f9f8d2..cd615d15 100644 --- a/geos-pv/tests/testsFunctionsGeosLogReader.py +++ b/geos-pv/tests/testsFunctionsGeosLogReader.py @@ -15,7 +15,7 @@ if parent_dir_path not in sys.path: sys.path.append( parent_dir_path ) -from geos_posp.processing import geosLogReaderFunctions as utils +from geos.pv import geosLogReaderFunctions as lrf from geos.utils.enumUnits import Unit, getSIUnits @@ -25,14 +25,14 @@ def test_replaceSpecialCharactersWithWhitespace( self: Self ) -> None: """Test replaceSpecialCharactersWithWhitespace function.""" example: str = "hi '(_there(''&*$^,:;'" expected: str = "hi there " - obtained: str = utils.replaceSpecialCharactersWithWhitespace( example ) + obtained: str = lrf.replaceSpecialCharactersWithWhitespace( example ) self.assertEqual( expected, obtained ) def test_formatPropertyName( self: Self ) -> None: """Test formatPropertyName function.""" example: str = " Delta pressure min" expected: str = "DeltaPressureMin" - obtained: str = utils.formatPropertyName( example ) + obtained: str = lrf.formatPropertyName( example ) self.assertEqual( expected, obtained ) def test_extractRegion( self: Self ) -> None: @@ -40,7 +40,7 @@ def test_extractRegion( self: Self ) -> None: example: str = ( "Adding Object CellElementRegion named Reservoir from" " ObjectManager::Catalog." ) expected: str = "Reservoir" - obtained: str = utils.extractRegion( example ) + obtained: str = lrf.extractRegion( example ) self.assertEqual( expected, obtained ) def test_extractStatsName( self: Self ) -> None: @@ -48,7 +48,7 @@ def test_extractStatsName( self: Self ) -> None: example: str = ( "compflowStatistics, Reservoir: Pressure (min, average, max): " "2.86419e+07, 2.93341e+07, 3.006e+07 Pa" ) expected: str = "compflowStatistics" - obtained: str = utils.extractStatsName( example ) + obtained: str = lrf.extractStatsName( example ) self.assertEqual( expected, obtained ) def test_extractPhaseModel( self: Self ) -> None: @@ -56,7 +56,7 @@ def test_extractPhaseModel( self: Self ) -> None: example: str = ( " TableFunction: " "fluid_phaseModel1_PhillipsBrineDensity_table" ) expected: str = "PhillipsBrineDensity" - obtained: str = utils.extractPhaseModel( example ) + obtained: str = lrf.extractPhaseModel( example ) self.assertEqual( expected, obtained ) def test_buildPropertiesNameForPhases( self: Self ) -> None: @@ -64,7 +64,7 @@ def test_buildPropertiesNameForPhases( self: Self ) -> None: example_block: str = " Mobile phase mass" example_phases: list[ str ] = [ "CO2", "Water" ] expected: list[ str ] = [ " Mobile CO2 mass", " Mobile Water mass" ] - obtained: list[ str ] = utils.buildPropertiesNameForPhases( example_block, example_phases ) + obtained: list[ str ] = lrf.buildPropertiesNameForPhases( example_block, example_phases ) self.assertEqual( expected, obtained ) def test_buildPropertiesNameForComponents( self: Self ) -> None: @@ -76,7 +76,7 @@ def test_buildPropertiesNameForComponents( self: Self ) -> None: "Dissolved mass CO2 in Water", "Dissolved mass Water in Water", ] - obtained: list[ str ] = utils.buildPropertiesNameForComponents( example ) + obtained: list[ str ] = lrf.buildPropertiesNameForComponents( example ) self.assertEqual( expected, obtained ) def test_buildPropertiesNameNoPhases( self: Self ) -> None: @@ -84,14 +84,14 @@ def test_buildPropertiesNameNoPhases( self: Self ) -> None: example_name_block: str = " Delta pressure " example_extensions: str = "min, max)" expected: list[ str ] = [ " Delta pressure min", " Delta pressure max" ] - obtained: list[ str ] = utils.buildPropertiesNameNoPhases( example_name_block, example_extensions ) + obtained: list[ str ] = lrf.buildPropertiesNameNoPhases( example_name_block, example_extensions ) self.assertEqual( expected, obtained ) def test_buildPropertiesNameNoPhases2( self: Self ) -> None: """Test buildPropertiesNameNoPhases function.""" example: str = " Delta pressure " expected: list[ str ] = [ " Delta pressure " ] - obtained: list[ str ] = utils.buildPropertiesNameNoPhases( example ) + obtained: list[ str ] = lrf.buildPropertiesNameNoPhases( example ) self.assertEqual( expected, obtained ) def test_buildPropertiesNameFromGeosProperties( self: Self ) -> None: @@ -99,17 +99,17 @@ def test_buildPropertiesNameFromGeosProperties( self: Self ) -> None: examples_phases: list[ str ] = [ "CO2", "Water" ] example: str = " Pressure (min, average, max)" expected: list[ str ] = [ " Pressure min", " Pressure average", " Pressure max" ] - obtained: list[ str ] = utils.buildPropertiesNameFromGeosProperties( example, examples_phases ) + obtained: list[ str ] = lrf.buildPropertiesNameFromGeosProperties( example, examples_phases ) self.assertEqual( expected, obtained ) example = " Total dynamic pore volume" expected = [ " Total dynamic pore volume" ] - obtained = utils.buildPropertiesNameFromGeosProperties( example, examples_phases ) + obtained = lrf.buildPropertiesNameFromGeosProperties( example, examples_phases ) self.assertEqual( expected, obtained ) example = " Non-trapped phase mass (metric 1)" expected = [ " Non-trapped CO2 mass ", " Non-trapped Water mass " ] - obtained = utils.buildPropertiesNameFromGeosProperties( example, examples_phases ) + obtained = lrf.buildPropertiesNameFromGeosProperties( example, examples_phases ) self.assertEqual( expected, obtained ) example = " Dissolved component mass" @@ -119,7 +119,7 @@ def test_buildPropertiesNameFromGeosProperties( self: Self ) -> None: "Dissolved mass CO2 in Water", "Dissolved mass Water in Water", ] - obtained = utils.buildPropertiesNameFromGeosProperties( example, examples_phases ) + obtained = lrf.buildPropertiesNameFromGeosProperties( example, examples_phases ) self.assertEqual( expected, obtained ) example = " Component mass" @@ -129,7 +129,7 @@ def test_buildPropertiesNameFromGeosProperties( self: Self ) -> None: "Dissolved mass CO2 in Water", "Dissolved mass Water in Water", ] - obtained = utils.buildPropertiesNameFromGeosProperties( example, examples_phases ) + obtained = lrf.buildPropertiesNameFromGeosProperties( example, examples_phases ) self.assertEqual( expected, obtained ) def test_extractPropertiesFlow( self: Self ) -> None: @@ -141,13 +141,13 @@ def test_extractPropertiesFlow( self: Self ) -> None: "Reservoir__TrappedCO2Mass", "Reservoir__TrappedWaterMass", ] - obtained: list[ str ] = utils.extractPropertiesFlow( example_block, examples_phases ) + obtained: list[ str ] = lrf.extractPropertiesFlow( example_block, examples_phases ) self.assertEqual( expected, obtained ) example_block = ( "compflowStatistics, Reservoir: Phase mass:" " { 0, 1.01274e+14 } kg" ) expected = [ "Reservoir__CO2Mass", "Reservoir__WaterMass" ] - obtained = utils.extractPropertiesFlow( example_block, examples_phases ) + obtained = lrf.extractPropertiesFlow( example_block, examples_phases ) self.assertEqual( expected, obtained ) example_block = ( "compflowStatistics, Region1 (time 4320000 s): Pressure" @@ -158,14 +158,14 @@ def test_extractPropertiesFlow( self: Self ) -> None: "Region1__PressureAverage", "Region1__PressureMax", ] - obtained = utils.extractPropertiesFlow( example_block, examples_phases ) + obtained = lrf.extractPropertiesFlow( example_block, examples_phases ) self.assertEqual( expected, obtained ) def test_countNumberLines( self: Self ) -> None: """Test countNumberLines function.""" log1: str = os.path.join( dir_path, "Data/job_GEOS_825200.out" ) expected1: int = 24307 - obtained1: int = utils.countNumberLines( log1 ) + obtained1: int = lrf.countNumberLines( log1 ) self.assertEqual( expected1, obtained1 ) def test_extractValuesFlow( self: Self ) -> None: @@ -173,38 +173,38 @@ def test_extractValuesFlow( self: Self ) -> None: example: str = ( "compflowStatistics, Reservoir: Pressure (min, average, max):" " 1.25e+07, 1.25e+07, 1.25e+07 Pa" ) expected: list[ float ] = [ 1.25e07, 1.25e07, 1.25e07 ] - obtained: list[ float ] = utils.extractValuesFlow( example ) + obtained: list[ float ] = lrf.extractValuesFlow( example ) self.assertEqual( expected, obtained ) example = ( "compflowStatistics, Reservoir: Phase dynamic pore volumes:" " { 0, 6.61331e+07 } rm^3" ) expected = [ 0.0, 6.61331e07 ] - obtained = utils.extractValuesFlow( example ) + obtained = lrf.extractValuesFlow( example ) self.assertEqual( expected, obtained ) example = ( "compflowStatistics, Reservoir: Dissolved component mass:" " { { 0, 0 }, { 0, 6.38235e+10 } } kg" ) expected = [ 0.0, 0.0, 0.0, 6.38235e10 ] - obtained = utils.extractValuesFlow( example ) + obtained = lrf.extractValuesFlow( example ) self.assertEqual( expected, obtained ) example = ( "compflowStatistics, Reservoir: Cell fluid mass" " (min, max): 10765.1, 2.2694e+10 kg" ) expected = [ 10765.1, 2.2694e10 ] - obtained = utils.extractValuesFlow( example ) + obtained = lrf.extractValuesFlow( example ) self.assertEqual( expected, obtained ) example = ( "compflowStatistics, Region1 (time 256800000 s): Pressure" " (min, average, max): 10023287.92961521, 10271543.591259222," " 10525096.98374942 Pa" ) expected = [ 10023287.92961521, 10271543.591259222, 10525096.98374942 ] - obtained = utils.extractValuesFlow( example ) + obtained = lrf.extractValuesFlow( example ) self.assertEqual( expected, obtained ) example = ( "compflowStatistics, Region1 (time 4320000 s): Phase dynamic" " pore volume: [0, 799999924.1499865] rm^3" ) expected = [ 0, 799999924.1499865 ] - obtained = utils.extractValuesFlow( example ) + obtained = lrf.extractValuesFlow( example ) self.assertEqual( expected, obtained ) def test_convertValues( self: Self ) -> None: @@ -213,20 +213,20 @@ def test_convertValues( self: Self ) -> None: propertyValues: list[ float ] = [ 1e6, 2e8 ] propertyUnits: dict[ str, Unit ] = getSIUnits() expected: list[ float ] = [ 1e6, 2e8 ] - obtained: list[ float ] = utils.convertValues( propertyNames, propertyValues, propertyUnits ) + obtained: list[ float ] = lrf.convertValues( propertyNames, propertyValues, propertyUnits ) self.assertEqual( expected, obtained ) propertyNames = [ "WellControls__TotalFluidDensity" ] propertyValues = [ 1e4 ] expected = [ 1e4 ] - obtained = utils.convertValues( propertyNames, propertyValues, propertyUnits ) + obtained = lrf.convertValues( propertyNames, propertyValues, propertyUnits ) self.assertEqual( expected, obtained ) def test_extractWell( self: Self ) -> None: """Test extractWell function.""" line = " TableFunction: well.CO2001_ConstantBHP_table" expected = "well.CO2001" - obtained = utils.extractWell( line ) + obtained = lrf.extractWell( line ) self.assertEqual( expected, obtained ) def test_identifyCurrentWell( self: Self ) -> None: @@ -234,52 +234,52 @@ def test_identifyCurrentWell( self: Self ) -> None: lastWellName: str = "well1" line: str = ( "The total rate is 0 kg/s, which corresponds to a" + "total surface volumetric rate of 0 sm3/s" ) expected: str = "well1" - obtained: str = utils.identifyCurrentWell( line, lastWellName ) + obtained: str = lrf.identifyCurrentWell( line, lastWellName ) self.assertEqual( expected, obtained ) line = ( "Rank 18: well.CO2001: BHP (at the specified reference" + " elevation): 19318538.400682557 Pa" ) expected = "well.CO2001" - obtained = utils.identifyCurrentWell( line, lastWellName ) + obtained = lrf.identifyCurrentWell( line, lastWellName ) self.assertEqual( expected, obtained ) line = ( "wellControls1: BHP (at the specified reference" + " elevation): 12337146.157562563 Pa" ) expected = "wellControls1" - obtained = utils.identifyCurrentWell( line, lastWellName ) + obtained = lrf.identifyCurrentWell( line, lastWellName ) self.assertEqual( expected, obtained ) def test_extractWellTags( self: Self ) -> None: """Test extractWellTags function.""" line: str = ( "Rank 18: well.CO2001: BHP " + "(at the specified reference elevation): 193000 Pa" ) expected: list[ str ] = [ "BHP" ] - obtained: list[ str ] = utils.extractWellTags( line ) + obtained: list[ str ] = lrf.extractWellTags( line ) self.assertEqual( expected, obtained ) line = ( "The total rate is 0 kg/s, which corresponds" + " to a total surface volumetric rate of 0 sm3/s" ) expected = [ "total massRate", "total surface volumetricRate" ] - obtained = utils.extractWellTags( line ) + obtained = lrf.extractWellTags( line ) self.assertEqual( expected, obtained ) def test_extractValuesWell( self: Self ) -> None: """Test extractValuesWell function.""" line: str = ( "Rank 18: well.CO2001: BHP " + "(at the specified reference elevation): 193000 Pa" ) expected: list[ float ] = [ 193000.0 ] - obtained: list[ float ] = utils.extractValuesWell( line, 1 ) + obtained: list[ float ] = lrf.extractValuesWell( line, 1 ) self.assertEqual( expected, obtained ) line = ( "The total rate is 0 kg/s, which corresponds" + " to a total surface volumetric rate of 0 sm3/s" ) expected = [ 0.0, 0.0 ] - obtained = utils.extractValuesWell( line, 2 ) + obtained = lrf.extractValuesWell( line, 2 ) self.assertEqual( expected, obtained ) line = "The phase surface volumetric rate is" + " 1.9466968733035026e-12 sm3/s" expected = [ 1.9466968733035026e-12 ] - obtained = utils.extractValuesWell( line, 1 ) + obtained = lrf.extractValuesWell( line, 1 ) self.assertEqual( expected, obtained ) def test_extractAquifer( self: Self ) -> None: """Test extractAquifer function.""" line: str = " TableFunction:aquifer1_pressureInfluence_table" expected: str = "aquifer1" - obtained: str = utils.extractAquifer( line ) + obtained: str = lrf.extractAquifer( line ) self.assertEqual( expected, obtained ) def test_extractValueAndNameAquifer( self: Self ) -> None: @@ -289,7 +289,7 @@ def test_extractValueAndNameAquifer( self: Self ) -> None: " boundary condition 'aquifer1' produces a flux of" + " -0.6181975187076816 kg (or moles if useMass=0)." ) expected: tuple[ str, float ] = ( "aquifer1", -0.6181975187076816 ) - obtained: tuple[ str, float ] = utils.extractValueAndNameAquifer( line ) + obtained: tuple[ str, float ] = lrf.extractValueAndNameAquifer( line ) self.assertEqual( expected, obtained ) line = ( "FlowSolverBase compositionalMultiphaseFVMSolver" + @@ -298,14 +298,14 @@ def test_extractValueAndNameAquifer( self: Self ) -> None: " boundary condition 'Aquifer3' produces a flux of" + " -0.8441759009606705 kg (or moles if useMass=0). " ) expected = ( "Aquifer3", -0.8441759009606705 ) - obtained = utils.extractValueAndNameAquifer( line ) + obtained = lrf.extractValueAndNameAquifer( line ) self.assertEqual( expected, obtained ) def test_extractNewtonIter( self: Self ) -> None: """Test extractNewtonIter function.""" line: str = " Attempt: 2, ConfigurationIter: 1, NewtonIter: 8" expected: int = 8 - obtained: int = utils.extractNewtonIter( line ) + obtained: int = lrf.extractNewtonIter( line ) self.assertEqual( expected, obtained ) def test_extractLinearIter( self: Self ) -> None: @@ -314,7 +314,7 @@ def test_extractLinearIter( self: Self ) -> None: " 5.96636e-05 | Make Restrictor Time: 0 | Compute Auu Time: 0 |" + " SC Filter Time: 0 | Setup Time: 1.5156 s | Solve Time:" + " 0.041093 s" ) expected: int = 23 - obtained: int = utils.extractLinearIter( line ) + obtained: int = lrf.extractLinearIter( line ) self.assertEqual( expected, obtained ) def test_timeInSecond( self: Self ) -> None: @@ -327,56 +327,56 @@ def test_timeInSecond( self: Self ) -> None: "s": 0, } expected: float = 0.0 - obtained: float = utils.timeInSecond( timeCounter ) + obtained: float = lrf.timeInSecond( timeCounter ) self.assertEqual( expected, obtained ) timeCounter = { "years": 1, "days": 1, "hrs": 1, "min": 1, "s": 1 } expected = 31647661.0 - obtained = utils.timeInSecond( timeCounter ) + obtained = lrf.timeInSecond( timeCounter ) self.assertEqual( expected, obtained ) def test_extractTimeAndDt( self: Self ) -> None: """Test extractTimeAndDt function.""" line: str = "Time: 1 s, dt: 1 s, Cycle: 0" expected: tuple[ float, float ] = ( 1.0, 1.0 ) - obtained: tuple[ float, float ] = utils.extractTimeAndDt( line ) + obtained: tuple[ float, float ] = lrf.extractTimeAndDt( line ) self.assertEqual( expected, obtained ) line = "Time: 1s, dt: 1s, Cycle: 0" expected = ( 1.0, 1.0 ) - obtained = utils.extractTimeAndDt( line ) + obtained = lrf.extractTimeAndDt( line ) self.assertEqual( expected, obtained ) line = "Time: 1e5s, dt: 1e6s, Cycle: 0" expected = ( 1.0e5, 1.0e6 ) - obtained = utils.extractTimeAndDt( line ) + obtained = lrf.extractTimeAndDt( line ) self.assertEqual( expected, obtained ) line = "Time: 1 min, dt: 1 s, Cycle: 0" expected = ( 60.0, 1.0 ) - obtained = utils.extractTimeAndDt( line ) + obtained = lrf.extractTimeAndDt( line ) self.assertEqual( expected, obtained ) line = "Time: 1 hrs, dt: 1 s, Cycle: 0" expected = ( 3600.0, 1.0 ) - obtained = utils.extractTimeAndDt( line ) + obtained = lrf.extractTimeAndDt( line ) self.assertEqual( expected, obtained ) line = "Time: 1 days, dt: 1 s, Cycle: 0" expected = ( 86400.0, 1.0 ) - obtained = utils.extractTimeAndDt( line ) + obtained = lrf.extractTimeAndDt( line ) self.assertEqual( expected, obtained ) line = "Time: 1 years, 1 days, 1 hrs, 1 min, 1 s, dt: 1 s, Cycle: 1" expected = ( 31647661.0, 1.0 ) - obtained = utils.extractTimeAndDt( line ) + obtained = lrf.extractTimeAndDt( line ) self.assertEqual( expected, obtained ) def test_identifyProperties( self: Self ) -> None: """Test identifyProperties function.""" properties: list[ str ] = [ "WellControls_TotalFluidDensity" ] expected: list[ str ] = [ "35:WellControls_TotalFluidDensity" ] - obtained: list[ str ] = utils.identifyProperties( properties ) + obtained: list[ str ] = lrf.identifyProperties( properties ) self.assertEqual( expected, obtained ) def test_findNumberPhasesSimulation( self: Self ) -> None: @@ -385,26 +385,26 @@ def test_findNumberPhasesSimulation( self: Self ) -> None: pathToFile: str = os.path.join( dir_path, "Data/" ) filepath: str = os.path.join( pathToFile, filename ) expected: int = 2 - obtained: int = utils.findNumberPhasesSimulation( filepath ) + obtained: int = lrf.findNumberPhasesSimulation( filepath ) self.assertEqual( expected, obtained ) def test_transformUserChoiceToListPhases( self: Self ) -> None: """Test phaseNameBuilder function with 3 phases.""" userChoice: str = "phase0 phase1 phase2" expected: list[ str ] = [ "phase0", "phase1", "phase2" ] - obtained: list[ str ] = utils.transformUserChoiceToListPhases( userChoice ) + obtained: list[ str ] = lrf.transformUserChoiceToListPhases( userChoice ) self.assertEqual( expected, obtained ) userChoice = "phase0, phase1, phase2" expected = [ "phase0", "phase1", "phase2" ] - obtained = utils.transformUserChoiceToListPhases( userChoice ) + obtained = lrf.transformUserChoiceToListPhases( userChoice ) self.assertEqual( expected, obtained ) userChoice = "phase0; phase1; phase2" expected = [] capturedOutput = io.StringIO() with contextlib.redirect_stdout( capturedOutput ): - obtained = utils.transformUserChoiceToListPhases( userChoice ) + obtained = lrf.transformUserChoiceToListPhases( userChoice ) self.assertEqual( expected, obtained ) self.assertGreater( len( capturedOutput.getvalue() ), 0 ) @@ -412,17 +412,17 @@ def test_phaseNamesBuilder( self: Self ) -> None: """Test phaseNameBuilder function with 4 phases.""" phasesFromUser: list[ str ] = [] expected: list[ str ] = [ "phase0", "phase1", "phase2", "phase3" ] - obtained: list[ str ] = utils.phaseNamesBuilder( 4, phasesFromUser ) + obtained: list[ str ] = lrf.phaseNamesBuilder( 4, phasesFromUser ) self.assertEqual( expected, obtained ) phasesFromUser = [ "water", "gas" ] expected = [ "water", "gas", "phase2", "phase3" ] - obtained = utils.phaseNamesBuilder( 4, phasesFromUser ) + obtained = lrf.phaseNamesBuilder( 4, phasesFromUser ) self.assertEqual( expected, obtained ) phasesFromUser = [ "water", "CO2", "N2", "H2", "CH4" ] expected = [ "water", "CO2", "N2", "H2" ] - obtained = utils.phaseNamesBuilder( 4, phasesFromUser ) + obtained = lrf.phaseNamesBuilder( 4, phasesFromUser ) self.assertEqual( expected, obtained ) # TODO def test_extractValuesFromBlockWhenMultipleComponents(self :Self) diff --git a/geos-pv/tests/testsGeosLogReaderConvergence.py b/geos-pv/tests/testsGeosLogReaderConvergence.py index 1c2e2897..c41d2ab9 100644 --- a/geos-pv/tests/testsGeosLogReaderConvergence.py +++ b/geos-pv/tests/testsGeosLogReaderConvergence.py @@ -14,7 +14,7 @@ if parent_dir_path not in sys.path: sys.path.append( parent_dir_path ) -from geos_posp.readers.GeosLogReaderConvergence import GeosLogReaderConvergence +from geos.pv.geosLogReaderUtils.GeosLogReaderConvergence import GeosLogReaderConvergence from geos.utils.UnitRepository import Unit, UnitRepository unitsObjSI: UnitRepository = UnitRepository() diff --git a/geos-pv/tests/testsGeosLogReaderFlow.py b/geos-pv/tests/testsGeosLogReaderFlow.py index 2c9b0ba8..977a1558 100644 --- a/geos-pv/tests/testsGeosLogReaderFlow.py +++ b/geos-pv/tests/testsGeosLogReaderFlow.py @@ -15,7 +15,7 @@ sys.path.append( parent_dir_path ) from geos.utils.UnitRepository import Unit, UnitRepository -from geos_posp.readers.GeosLogReaderFlow import GeosLogReaderFlow +from geos.pv.geosLogReaderUtils.GeosLogReaderFlow import GeosLogReaderFlow unitsObjSI: UnitRepository = UnitRepository() conversionFactors: dict[ str, Unit ] = unitsObjSI.getPropertiesUnit() diff --git a/geos-pv/tests/testsGeosLogReaderWells.py b/geos-pv/tests/testsGeosLogReaderWells.py index ee2b21d7..8d7fe719 100644 --- a/geos-pv/tests/testsGeosLogReaderWells.py +++ b/geos-pv/tests/testsGeosLogReaderWells.py @@ -17,7 +17,7 @@ import pandas as pd # type: ignore[import-untyped] -from geos_posp.readers.GeosLogReaderWells import GeosLogReaderWells +from geos.pv.geosLogReaderUtils.GeosLogReaderWells import GeosLogReaderWells from geos.utils.UnitRepository import Unit, UnitRepository unitsObjSI = UnitRepository() diff --git a/geos-pv/tests/testsInvalidLogs.py b/geos-pv/tests/testsInvalidLogs.py index fb9cce2c..c09e4169 100644 --- a/geos-pv/tests/testsInvalidLogs.py +++ b/geos-pv/tests/testsInvalidLogs.py @@ -15,10 +15,10 @@ if parent_dir_path not in sys.path: sys.path.append( parent_dir_path ) -from geos_posp.readers.GeosLogReaderAquifers import GeosLogReaderAquifers -from geos_posp.readers.GeosLogReaderConvergence import GeosLogReaderConvergence -from geos_posp.readers.GeosLogReaderFlow import GeosLogReaderFlow -from geos_posp.readers.GeosLogReaderWells import GeosLogReaderWells +from geos.pv.geosLogReaderUtils.GeosLogReaderAquifers import GeosLogReaderAquifers +from geos.pv.geosLogReaderUtils.GeosLogReaderConvergence import GeosLogReaderConvergence +from geos.pv.geosLogReaderUtils.GeosLogReaderFlow import GeosLogReaderFlow +from geos.pv.geosLogReaderUtils.GeosLogReaderWells import GeosLogReaderWells from geos.utils.UnitRepository import Unit, UnitRepository unitsObjSI: UnitRepository = UnitRepository()