From dda99f6eff8563ec5e515756ac109d266f5606c6 Mon Sep 17 00:00:00 2001
From: Kwabena N Amponsah <kwabenantim@yahoo.com>
Date: Thu, 16 May 2024 17:00:38 +0000
Subject: [PATCH 01/12] #24 update cmake for vtk9

---
 CMakeLists.txt   | 30 ++++++++++++++++++++++--------
 WrapPython.cmake |  2 +-
 2 files changed, 23 insertions(+), 9 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 5b58848c..776d4a3c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -33,7 +33,7 @@
 find_package(Chaste COMPONENTS cell_based)
 
 # PyChaste needs some additional VTK libraries
-if(VTK_MAJOR_VERSION LESS_EQUAL 6)
+if(VTK_MAJOR_VERSION LESS 7)
     find_package(VTK REQUIRED COMPONENTS
         vtkInteractionStyle
         vtkIOImage
@@ -44,24 +44,38 @@ if(VTK_MAJOR_VERSION LESS_EQUAL 6)
         vtkRenderingOpenGL
         vtkWrappingPythonCore
     )
-else()
+elseif(VTK_MAJOR_VERSION LESS 9)
     find_package(VTK REQUIRED COMPONENTS
-        vtkFiltersProgrammable
-        vtkFiltersVerdict
         vtkInteractionStyle
         vtkIOImage
         vtkIOMovie
         vtkRenderingAnnotation
         vtkRenderingCore
         vtkRenderingFreeType
-        vtkRenderingOpenGL2
+        vtkRenderingOpenGL
         vtkWrappingPythonCore
     )
+else()
+    find_package(VTK REQUIRED COMPONENTS
+        FiltersProgrammable
+        FiltersVerdict
+        InteractionStyle
+        IOImage
+        IOMovie
+        RenderingAnnotation
+        RenderingCore
+        RenderingFreeType
+        RenderingOpenGL2
+        WrappingPythonCore
+    )
 endif()
 
-list(APPEND Chaste_INCLUDES ${VTK_INCLUDE_DIRS})
-list(APPEND Chaste_project_PyChaste_INCLUDE_DIRS ${VTK_INCLUDE_DIRS})
-list(APPEND Chaste_THIRD_PARTY_LIBRARIES ${VTK_LIBRARIES})
+if (VTK_MAJOR_VERSION LESS 9)
+    list(APPEND Chaste_INCLUDES ${VTK_INCLUDE_DIRS})
+    list(APPEND Chaste_project_PyChaste_INCLUDE_DIRS ${VTK_INCLUDE_DIRS})
+    list(APPEND Chaste_THIRD_PARTY_LIBRARIES ${VTK_LIBRARIES})
+endif ()
+
 chaste_do_project(PyChaste)
 
 # Include the Python wrapping build logic
diff --git a/WrapPython.cmake b/WrapPython.cmake
index 376976e6..639ebd01 100644
--- a/WrapPython.cmake
+++ b/WrapPython.cmake
@@ -124,7 +124,7 @@ foreach(val RANGE ${len2})
         PREFIX "${PYTHON_MODULE_PREFIX}" SUFFIX ".so")
     target_compile_features(_chaste_project_PyChaste_${python_module} PRIVATE cxx_range_for)
     # order is important, pybind and python come first
-    target_link_libraries(_chaste_project_PyChaste_${python_module} pybind11::module ${PYTHON3_LIBRARIES} ${Chaste_THIRD_PARTY_LIBRARIES} ${Chaste_LIBRARIES} ${PYCHASTE_SHARED_LIB})
+    target_link_libraries(_chaste_project_PyChaste_${python_module} pybind11::module ${PYTHON3_LIBRARIES} ${Chaste_THIRD_PARTY_LIBRARIES} ${Chaste_LIBRARIES} ${PYCHASTE_SHARED_LIB} Chaste_COMMON_DEPS)
     add_dependencies(_chaste_project_PyChaste_${python_module} chaste_project_PyChaste)
 endforeach()
 

From 16277fa13675bfde0a328d7e508b647f190f5cd2 Mon Sep 17 00:00:00 2001
From: Kwabena N Amponsah <kwabenantim@yahoo.com>
Date: Thu, 16 May 2024 17:09:21 +0000
Subject: [PATCH 02/12] #24 limit max petsc version

---
 .github/workflows/test-vtk.yml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/.github/workflows/test-vtk.yml b/.github/workflows/test-vtk.yml
index 6b6e0b40..457be4a8 100644
--- a/.github/workflows/test-vtk.yml
+++ b/.github/workflows/test-vtk.yml
@@ -56,8 +56,8 @@ jobs:
             notebook
             numpy
             parmetis
-            petsc
-            petsc4py
+            petsc<3.19
+            petsc4py<3.19
             pip
             setuptools
             six

From 5168572d03ac010beef76b0fe9363115cce4b2a0 Mon Sep 17 00:00:00 2001
From: Kwabena N Amponsah <kwabenantim@yahoo.com>
Date: Thu, 16 May 2024 17:23:39 +0000
Subject: [PATCH 03/12] #24 restrict max sundials version

---
 .github/workflows/test-vtk.yml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/.github/workflows/test-vtk.yml b/.github/workflows/test-vtk.yml
index 457be4a8..ce590c2d 100644
--- a/.github/workflows/test-vtk.yml
+++ b/.github/workflows/test-vtk.yml
@@ -13,7 +13,7 @@ jobs:
     strategy:
       fail-fast: false
       matrix:
-        vtk-version: ["8.2", "9.2"]
+        vtk-version: ["7.1", "8.2", "9.2"]
 
     steps:
       - name: checkout chaste
@@ -61,7 +61,7 @@ jobs:
             pip
             setuptools
             six
-            sundials
+            sundials<7.0
             tbb-devel
             vtk=${{ matrix.vtk-version }}
             wheel

From 4f210b41806a47ec26cddf06fc39f49ba1600f7d Mon Sep 17 00:00:00 2001
From: Kwabena N Amponsah <kwabenantim@yahoo.com>
Date: Thu, 16 May 2024 17:32:36 +0000
Subject: [PATCH 04/12] #24 fix vtk components

---
 CMakeLists.txt | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 776d4a3c..2ab892e3 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -46,13 +46,15 @@ if(VTK_MAJOR_VERSION LESS 7)
     )
 elseif(VTK_MAJOR_VERSION LESS 9)
     find_package(VTK REQUIRED COMPONENTS
+        vtkFiltersProgrammable
+        vtkFiltersVerdict
         vtkInteractionStyle
         vtkIOImage
         vtkIOMovie
         vtkRenderingAnnotation
         vtkRenderingCore
         vtkRenderingFreeType
-        vtkRenderingOpenGL
+        vtkRenderingOpenGL2
         vtkWrappingPythonCore
     )
 else()

From 50a52aa9c562804ee18d4d00575891aa38e7ccdc Mon Sep 17 00:00:00 2001
From: Kwabena N Amponsah <kwabenantim@yahoo.com>
Date: Thu, 16 May 2024 18:12:03 +0000
Subject: [PATCH 05/12] #24 fix deprecated functions in vtk9

---
 .../CellPopulationPyChasteActorGenerator.cpp  | 40 ++++++++++---------
 1 file changed, 22 insertions(+), 18 deletions(-)

diff --git a/src/visualization/CellPopulationPyChasteActorGenerator.cpp b/src/visualization/CellPopulationPyChasteActorGenerator.cpp
index 94d8cd0b..4351ef15 100644
--- a/src/visualization/CellPopulationPyChasteActorGenerator.cpp
+++ b/src/visualization/CellPopulationPyChasteActorGenerator.cpp
@@ -324,17 +324,17 @@ void CellPopulationPyChasteActorGenerator<DIM>::AddPottsBasedCellPopulationActor
             }
         }
 
-        vtkSmartPointer<vtkGeometryFilter> p_geometry_filter_pre =
-          vtkSmartPointer<vtkGeometryFilter>::New();
-        #if VTK_MAJOR_VERSION <= 5
-            p_geometry_filter_pre->SetInput(p_potts_grid);
-        #else
-            p_geometry_filter_pre->SetInputData(p_potts_grid);
-        #endif
+        auto p_geometry_filter_pre = vtkSmartPointer<vtkGeometryFilter>::New();
+        p_geometry_filter_pre->SetInputData(p_potts_grid);
 
         vtkSmartPointer<vtkThreshold> p_threshold = vtkSmartPointer<vtkThreshold>::New();
         p_threshold->SetInputConnection(p_geometry_filter_pre->GetOutputPort());
+
+#if VTK_MAJOR_VERSION < 9
         p_threshold->ThresholdByUpper(0.0);
+#else
+        p_threshold->SetUpperThreshold(0.0);
+#endif
         p_threshold->SetInputArrayToProcess(0, 0, 0, vtkDataObject::FIELD_ASSOCIATION_CELLS, "Cell Id");
 
         vtkSmartPointer<vtkGeometryFilter> p_geom_filter = vtkSmartPointer<vtkGeometryFilter>::New();
@@ -366,12 +366,16 @@ void CellPopulationPyChasteActorGenerator<DIM>::AddPottsBasedCellPopulationActor
             for(unsigned idx=0; idx<p_potts_grid->GetNumberOfCells(); idx++)
             {
                 vtkSmartPointer<vtkThreshold> p_local_threshold = vtkSmartPointer<vtkThreshold>::New();
-                #if VTK_MAJOR_VERSION <= 5
-                    p_local_threshold->SetInput(p_geom_filter->GetOutput());
-                #else
-                    p_local_threshold->SetInputData(p_geom_filter->GetOutput());
-                #endif
-                p_local_threshold->ThresholdBetween(p_element_base_ids->GetTuple1(idx), p_element_base_ids->GetTuple1(idx));
+                p_local_threshold->SetInputData(p_geom_filter->GetOutput());
+
+#if VTK_MAJOR_VERSION < 9
+                p_local_threshold->ThresholdBetween(p_element_base_ids->GetTuple1(idx),
+                                                    p_element_base_ids->GetTuple1(idx));
+#else
+                p_threshold->SetLowerThreshold(p_element_base_ids->GetTuple1(idx));
+                p_threshold->SetUpperThreshold(p_element_base_ids->GetTuple1(idx));
+#endif
+
                 p_local_threshold->SetInputArrayToProcess(0, 0, 0, vtkDataObject::FIELD_ASSOCIATION_CELLS, "Cell Base Id");
 
                 vtkSmartPointer<vtkGeometryFilter> p_local_geom_filter = vtkSmartPointer<vtkGeometryFilter>::New();
@@ -1110,12 +1114,12 @@ void CellPopulationPyChasteActorGenerator<DIM>::AddMeshBasedCellPopulationActor(
         p_scaled_ctf->Build();
 
         vtkSmartPointer<vtkThreshold> p_threshold = vtkSmartPointer<vtkThreshold>::New();
-        #if VTK_MAJOR_VERSION <= 5
-            p_threshold->SetInput(p_voronoi_grid);
-        #else
-            p_threshold->SetInputData(p_voronoi_grid);
-        #endif
+        p_threshold->SetInputData(p_voronoi_grid);
+#if VTK_MAJOR_VERSION < 9
         p_threshold->ThresholdByUpper(0.0);
+#else
+        p_threshold->SetUpperThreshold(0.0);
+#endif
         p_threshold->SetInputArrayToProcess(0, 0, 0, vtkDataObject::FIELD_ASSOCIATION_CELLS, "CellColors");
 
         vtkSmartPointer<vtkGeometryFilter> p_geom_filter = vtkSmartPointer<vtkGeometryFilter>::New();

From 6433f32c8536b252f19cf25b055ebddab1f45169 Mon Sep 17 00:00:00 2001
From: Kwabena N Amponsah <kwabenantim@yahoo.com>
Date: Fri, 17 May 2024 08:26:47 +0000
Subject: [PATCH 06/12] #24 correct p_local_threshold

---
 src/visualization/CellPopulationPyChasteActorGenerator.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/visualization/CellPopulationPyChasteActorGenerator.cpp b/src/visualization/CellPopulationPyChasteActorGenerator.cpp
index 4351ef15..43b166e6 100644
--- a/src/visualization/CellPopulationPyChasteActorGenerator.cpp
+++ b/src/visualization/CellPopulationPyChasteActorGenerator.cpp
@@ -372,8 +372,8 @@ void CellPopulationPyChasteActorGenerator<DIM>::AddPottsBasedCellPopulationActor
                 p_local_threshold->ThresholdBetween(p_element_base_ids->GetTuple1(idx),
                                                     p_element_base_ids->GetTuple1(idx));
 #else
-                p_threshold->SetLowerThreshold(p_element_base_ids->GetTuple1(idx));
-                p_threshold->SetUpperThreshold(p_element_base_ids->GetTuple1(idx));
+                p_local_threshold->SetLowerThreshold(p_element_base_ids->GetTuple1(idx));
+                p_local_threshold->SetUpperThreshold(p_element_base_ids->GetTuple1(idx));
 #endif
 
                 p_local_threshold->SetInputArrayToProcess(0, 0, 0, vtkDataObject::FIELD_ASSOCIATION_CELLS, "Cell Base Id");

From e3ff2dc2438875d569319fc129ca767d4da59f4d Mon Sep 17 00:00:00 2001
From: Kwabena N Amponsah <kwabenantim@yahoo.com>
Date: Fri, 17 May 2024 08:31:15 +0000
Subject: [PATCH 07/12] #24 no vtk5 support

---
 .../CellPopulationPyChasteActorGenerator.cpp  | 52 ++++---------------
 1 file changed, 9 insertions(+), 43 deletions(-)

diff --git a/src/visualization/CellPopulationPyChasteActorGenerator.cpp b/src/visualization/CellPopulationPyChasteActorGenerator.cpp
index 43b166e6..72ee6815 100644
--- a/src/visualization/CellPopulationPyChasteActorGenerator.cpp
+++ b/src/visualization/CellPopulationPyChasteActorGenerator.cpp
@@ -160,11 +160,7 @@ void CellPopulationPyChasteActorGenerator<DIM>::AddCaBasedCellPopulationActor(vt
         p_ca_image->SetOrigin(bounds[0], bounds[2], bounds[4]);
         p_ca_image->SetSpacing(spacing, spacing, spacing);
 
-        #if VTK_MAJOR_VERSION <= 5
-            p_geom_filter->SetInput(p_ca_image);
-        #else
-            p_geom_filter->SetInputData(p_ca_image);
-        #endif
+        p_geom_filter->SetInputData(p_ca_image);
 
         vtkSmartPointer<vtkPolyDataMapper> p_mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
         p_mapper->SetInputConnection(p_geom_filter->GetOutputPort());
@@ -386,23 +382,14 @@ void CellPopulationPyChasteActorGenerator<DIM>::AddPottsBasedCellPopulationActor
                 p_features->Update();
 
                 vtkSmartPointer<vtkAppendPolyData> p_append = vtkSmartPointer<vtkAppendPolyData>::New();
-                #if VTK_MAJOR_VERSION <= 5
-                    p_append->AddInput(p_bounds);
-                    p_append->AddInput(p_features->GetOutput());
-                #else
-                    p_append->AddInputData(p_bounds);
-                    p_append->AddInputData(p_features->GetOutput());
-                #endif
+                p_append->AddInputData(p_bounds);
+                p_append->AddInputData(p_features->GetOutput());
                 p_append->Update();
                 p_bounds = p_append->GetOutput();
             }
 
             vtkSmartPointer<vtkPolyDataMapper> p_mapper2 = vtkSmartPointer<vtkPolyDataMapper>::New();
-            #if VTK_MAJOR_VERSION <= 5
-                p_mapper2->SetInput(p_bounds);
-            #else
-                p_mapper2->SetInputData(p_bounds);
-            #endif
+            p_mapper2->SetInputData(p_bounds);
 
             vtkSmartPointer<vtkActor> p_volume_actor2 = vtkSmartPointer<vtkActor>::New();
             p_volume_actor2->SetMapper(p_mapper2);
@@ -524,24 +511,15 @@ void CellPopulationPyChasteActorGenerator<DIM>::AddActor(vtkSmartPointer<vtkRend
         p_spheres->SetThetaResolution(16);
 
         vtkSmartPointer<vtkGlyph3D> p_glyph = vtkSmartPointer<vtkGlyph3D>::New();
-        #if VTK_MAJOR_VERSION <= 5
-            p_glyph->SetInput(p_polydata);
-            p_glyph->SetSource(p_spheres->GetOutput());
-        #else
-            p_glyph->SetInputData(p_polydata);
-            p_glyph->SetSourceConnection(p_spheres->GetOutputPort());
-        #endif
+        p_glyph->SetInputData(p_polydata);
+        p_glyph->SetSourceConnection(p_spheres->GetOutputPort());
         p_glyph->ClampingOff();
         p_glyph->SetScaleModeToScaleByScalar();
         p_glyph->SetScaleFactor(1.0);
         p_glyph->Update();
 
         vtkSmartPointer<vtkPolyDataMapper> p_mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
-        #if VTK_MAJOR_VERSION <= 5
-            p_mapper->SetInput(p_glyph->GetOutput());
-        #else
-            p_mapper->SetInputData(p_glyph->GetOutput());
-        #endif
+        p_mapper->SetInputData(p_glyph->GetOutput());
         p_mapper->SetLookupTable(p_scaled_ctf);
         p_mapper->ScalarVisibilityOn();
         p_mapper->SelectColorArray("CellColors");
@@ -720,11 +698,7 @@ void CellPopulationPyChasteActorGenerator<DIM>::AddVertexBasedCellPopulationActo
         p_scaled_ctf->Build();
 
         vtkSmartPointer<vtkGeometryFilter> p_geom_filter = vtkSmartPointer<vtkGeometryFilter>::New();
-        #if VTK_MAJOR_VERSION <= 5
-            p_geom_filter->SetInput(p_voronoi_grid);
-        #else
-            p_geom_filter->SetInputData(p_voronoi_grid);
-        #endif
+        p_geom_filter->SetInputData(p_voronoi_grid);
 
         vtkSmartPointer<vtkPolyDataMapper> p_mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
         p_mapper->SetInputConnection(p_geom_filter->GetOutputPort());
@@ -906,11 +880,7 @@ void CellPopulationPyChasteActorGenerator<DIM>::AddImmersedBoundaryCellPopulatio
         p_scaled_ctf->Build();
 
         vtkSmartPointer<vtkGeometryFilter> p_geom_filter = vtkSmartPointer<vtkGeometryFilter>::New();
-        #if VTK_MAJOR_VERSION <= 5
-            p_geom_filter->SetInput(p_voronoi_grid);
-        #else
-            p_geom_filter->SetInputData(p_voronoi_grid);
-        #endif
+        p_geom_filter->SetInputData(p_voronoi_grid);
 
         vtkSmartPointer<vtkPolyDataMapper> p_mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
         p_mapper->SetInputConnection(p_geom_filter->GetOutputPort());
@@ -1229,11 +1199,7 @@ void CellPopulationPyChasteActorGenerator<DIM>::AddMeshBasedCellPopulationActor(
         }
 
         vtkSmartPointer<vtkGeometryFilter> p_mutable_geom_filter = vtkSmartPointer<vtkGeometryFilter>::New();
-        #if VTK_MAJOR_VERSION <= 5
-        p_mutable_geom_filter->SetInput(p_mutable_grid);
-        #else
         p_mutable_geom_filter->SetInputData(p_mutable_grid);
-        #endif
 
         vtkSmartPointer<vtkFeatureEdges> p_extract_edges = vtkSmartPointer<vtkFeatureEdges>::New();
         p_extract_edges->SetInputConnection(p_mutable_geom_filter->GetOutputPort());

From 6b0201dedbde6fc3b995779e81441104508dc28e Mon Sep 17 00:00:00 2001
From: Kwabena N Amponsah <kwabenantim@yahoo.com>
Date: Fri, 17 May 2024 08:43:27 +0000
Subject: [PATCH 08/12] #24 less verbose vtk smart pointer

---
 .../CellPopulationPyChasteActorGenerator.cpp  | 146 +++++++++---------
 src/visualization/VtkScene.cpp                |   4 +-
 2 files changed, 75 insertions(+), 75 deletions(-)

diff --git a/src/visualization/CellPopulationPyChasteActorGenerator.cpp b/src/visualization/CellPopulationPyChasteActorGenerator.cpp
index 72ee6815..828148b5 100644
--- a/src/visualization/CellPopulationPyChasteActorGenerator.cpp
+++ b/src/visualization/CellPopulationPyChasteActorGenerator.cpp
@@ -106,15 +106,15 @@ CellPopulationPyChasteActorGenerator<DIM>::~CellPopulationPyChasteActorGenerator
 template<unsigned DIM>
 void CellPopulationPyChasteActorGenerator<DIM>::AddCaBasedCellPopulationActor(vtkSmartPointer<vtkRenderer> pRenderer)
 {
-    vtkSmartPointer<vtkImageData> p_potts_grid = vtkSmartPointer<vtkImageData>::New();
-    vtkSmartPointer<vtkGeometryFilter> p_geom_filter = vtkSmartPointer<vtkGeometryFilter>::New();
+    auto p_potts_grid = vtkSmartPointer<vtkImageData>::New();
+    auto p_geom_filter = vtkSmartPointer<vtkGeometryFilter>::New();
 
     boost::shared_ptr<CaBasedCellPopulation<DIM> > p_ca_population =
         boost::dynamic_pointer_cast<CaBasedCellPopulation<DIM> >(mpCellPopulation);
 
     if(p_ca_population && mShowPottsMeshEdges)
     {
-        vtkSmartPointer<vtkPoints> p_points = vtkSmartPointer<vtkPoints>::New();
+        auto p_points = vtkSmartPointer<vtkPoints>::New();
         p_points->GetData()->SetName("Vertex positions");
 
         unsigned counter = 0;
@@ -148,12 +148,12 @@ void CellPopulationPyChasteActorGenerator<DIM>::AddCaBasedCellPopulationActor(vt
             counter ++;
         }
 
-        vtkSmartPointer<vtkPolyData> p_temp_polydata = vtkSmartPointer<vtkPolyData>::New();
+        auto p_temp_polydata = vtkSmartPointer<vtkPolyData>::New();
         p_temp_polydata->SetPoints(p_points);
 
         double bounds[6];
         p_temp_polydata->GetBounds(bounds);
-        vtkSmartPointer<vtkImageData> p_ca_image = vtkSmartPointer<vtkImageData>::New();
+        auto p_ca_image = vtkSmartPointer<vtkImageData>::New();
         p_ca_image->SetDimensions(std::floor((bounds[1]-bounds[0])/spacing) + 1,
                 std::floor((bounds[3]-bounds[2])/spacing) + 1,
                 std::floor((bounds[5]-bounds[4])/spacing) + 1);
@@ -162,10 +162,10 @@ void CellPopulationPyChasteActorGenerator<DIM>::AddCaBasedCellPopulationActor(vt
 
         p_geom_filter->SetInputData(p_ca_image);
 
-        vtkSmartPointer<vtkPolyDataMapper> p_mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
+        auto p_mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
         p_mapper->SetInputConnection(p_geom_filter->GetOutputPort());
 
-        vtkSmartPointer<vtkActor> p_volume_actor = vtkSmartPointer<vtkActor>::New();
+        auto p_volume_actor = vtkSmartPointer<vtkActor>::New();
         p_volume_actor->SetMapper(p_mapper);
         p_volume_actor->GetProperty()->SetEdgeVisibility(this->mShowEdges);
         p_volume_actor->GetProperty()->SetLineWidth(this->mEdgeSize);
@@ -177,14 +177,14 @@ void CellPopulationPyChasteActorGenerator<DIM>::AddCaBasedCellPopulationActor(vt
 template<unsigned DIM>
 void CellPopulationPyChasteActorGenerator<DIM>::AddPottsBasedCellPopulationActor(vtkSmartPointer<vtkRenderer> pRenderer)
 {
-    vtkSmartPointer<vtkImageData> p_potts_grid = vtkSmartPointer<vtkImageData>::New();
+    auto p_potts_grid = vtkSmartPointer<vtkImageData>::New();
 
     boost::shared_ptr<PottsBasedCellPopulation<DIM> > p_potts_population =
             boost::dynamic_pointer_cast<PottsBasedCellPopulation<DIM> >(mpCellPopulation);
 
     if(p_potts_population && mShowPottsMeshEdges)
     {
-        vtkSmartPointer<vtkPoints> p_points = vtkSmartPointer<vtkPoints>::New();
+        auto p_points = vtkSmartPointer<vtkPoints>::New();
         p_points->GetData()->SetName("Vertex positions");
 
         unsigned counter = 0;
@@ -219,7 +219,7 @@ void CellPopulationPyChasteActorGenerator<DIM>::AddPottsBasedCellPopulationActor
             counter ++;
         }
 
-        vtkSmartPointer<vtkPolyData> p_temp_polydata = vtkSmartPointer<vtkPolyData>::New();
+        auto p_temp_polydata = vtkSmartPointer<vtkPolyData>::New();
         p_temp_polydata->SetPoints(p_points);
 
         double bounds[6];
@@ -233,11 +233,11 @@ void CellPopulationPyChasteActorGenerator<DIM>::AddPottsBasedCellPopulationActor
         p_potts_grid->SetOrigin(bounds[0]-spacing/2.0, bounds[2]-spacing/2.0, bounds[4]-spacing/2.0);
         p_potts_grid->SetSpacing(spacing, spacing, spacing);
 
-        vtkSmartPointer<vtkDoubleArray> p_element_ids = vtkSmartPointer<vtkDoubleArray>::New();
+        auto p_element_ids = vtkSmartPointer<vtkDoubleArray>::New();
         p_element_ids->SetNumberOfTuples(p_potts_grid->GetNumberOfPoints());
         p_element_ids->SetName("Cell Id");
 
-        vtkSmartPointer<vtkDoubleArray> p_element_base_ids = vtkSmartPointer<vtkDoubleArray>::New();
+        auto p_element_base_ids = vtkSmartPointer<vtkDoubleArray>::New();
         p_element_base_ids->SetNumberOfTuples(p_potts_grid->GetNumberOfPoints());
         p_element_base_ids->SetName("Cell Base Id");
         for(unsigned idx=0; idx<p_potts_grid->GetNumberOfPoints(); idx++)
@@ -307,7 +307,7 @@ void CellPopulationPyChasteActorGenerator<DIM>::AddPottsBasedCellPopulationActor
         p_potts_grid->GetCellData()->AddArray(p_element_ids);
         p_potts_grid->GetCellData()->AddArray(p_element_base_ids);
 
-        vtkSmartPointer<vtkColorTransferFunction> p_scaled_ctf = vtkSmartPointer<vtkColorTransferFunction>::New();
+        auto p_scaled_ctf = vtkSmartPointer<vtkColorTransferFunction>::New();
         if(!mColorByCellData)
         {
             double range[2];
@@ -323,7 +323,7 @@ void CellPopulationPyChasteActorGenerator<DIM>::AddPottsBasedCellPopulationActor
         auto p_geometry_filter_pre = vtkSmartPointer<vtkGeometryFilter>::New();
         p_geometry_filter_pre->SetInputData(p_potts_grid);
 
-        vtkSmartPointer<vtkThreshold> p_threshold = vtkSmartPointer<vtkThreshold>::New();
+        auto p_threshold = vtkSmartPointer<vtkThreshold>::New();
         p_threshold->SetInputConnection(p_geometry_filter_pre->GetOutputPort());
 
 #if VTK_MAJOR_VERSION < 9
@@ -333,10 +333,10 @@ void CellPopulationPyChasteActorGenerator<DIM>::AddPottsBasedCellPopulationActor
 #endif
         p_threshold->SetInputArrayToProcess(0, 0, 0, vtkDataObject::FIELD_ASSOCIATION_CELLS, "Cell Id");
 
-        vtkSmartPointer<vtkGeometryFilter> p_geom_filter = vtkSmartPointer<vtkGeometryFilter>::New();
+        auto p_geom_filter = vtkSmartPointer<vtkGeometryFilter>::New();
         p_geom_filter->SetInputConnection(p_threshold->GetOutputPort());
 
-        vtkSmartPointer<vtkPolyDataMapper> p_mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
+        auto p_mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
         p_mapper->SetInputConnection(p_geom_filter->GetOutputPort());
         p_mapper->SetLookupTable(p_scaled_ctf);
         p_mapper->ScalarVisibilityOn();
@@ -344,7 +344,7 @@ void CellPopulationPyChasteActorGenerator<DIM>::AddPottsBasedCellPopulationActor
         p_mapper->SetScalarModeToUseCellData();
         p_mapper->SetColorModeToMapScalars();
 
-        vtkSmartPointer<vtkActor> p_volume_actor = vtkSmartPointer<vtkActor>::New();
+        auto p_volume_actor = vtkSmartPointer<vtkActor>::New();
         p_volume_actor->SetMapper(p_mapper);
         //p_volume_actor->GetProperty()->SetEdgeVisibility(this->mShowEdges);
         p_volume_actor->GetProperty()->SetLineWidth(this->mEdgeSize);
@@ -357,11 +357,11 @@ void CellPopulationPyChasteActorGenerator<DIM>::AddPottsBasedCellPopulationActor
 
         if(mShowPottsMeshOutlines)
         {
-            vtkSmartPointer<vtkPolyData> p_bounds = vtkSmartPointer<vtkPolyData>::New();
+            auto p_bounds = vtkSmartPointer<vtkPolyData>::New();
 
             for(unsigned idx=0; idx<p_potts_grid->GetNumberOfCells(); idx++)
             {
-                vtkSmartPointer<vtkThreshold> p_local_threshold = vtkSmartPointer<vtkThreshold>::New();
+                auto p_local_threshold = vtkSmartPointer<vtkThreshold>::New();
                 p_local_threshold->SetInputData(p_geom_filter->GetOutput());
 
 #if VTK_MAJOR_VERSION < 9
@@ -374,24 +374,24 @@ void CellPopulationPyChasteActorGenerator<DIM>::AddPottsBasedCellPopulationActor
 
                 p_local_threshold->SetInputArrayToProcess(0, 0, 0, vtkDataObject::FIELD_ASSOCIATION_CELLS, "Cell Base Id");
 
-                vtkSmartPointer<vtkGeometryFilter> p_local_geom_filter = vtkSmartPointer<vtkGeometryFilter>::New();
+                auto p_local_geom_filter = vtkSmartPointer<vtkGeometryFilter>::New();
                 p_local_geom_filter->SetInputConnection(p_local_threshold->GetOutputPort());
 
-                vtkSmartPointer<vtkFeatureEdges> p_features = vtkSmartPointer<vtkFeatureEdges>::New();
+                auto p_features = vtkSmartPointer<vtkFeatureEdges>::New();
                 p_features->SetInputConnection(p_local_geom_filter->GetOutputPort());
                 p_features->Update();
 
-                vtkSmartPointer<vtkAppendPolyData> p_append = vtkSmartPointer<vtkAppendPolyData>::New();
+                auto p_append = vtkSmartPointer<vtkAppendPolyData>::New();
                 p_append->AddInputData(p_bounds);
                 p_append->AddInputData(p_features->GetOutput());
                 p_append->Update();
                 p_bounds = p_append->GetOutput();
             }
 
-            vtkSmartPointer<vtkPolyDataMapper> p_mapper2 = vtkSmartPointer<vtkPolyDataMapper>::New();
+            auto p_mapper2 = vtkSmartPointer<vtkPolyDataMapper>::New();
             p_mapper2->SetInputData(p_bounds);
 
-            vtkSmartPointer<vtkActor> p_volume_actor2 = vtkSmartPointer<vtkActor>::New();
+            auto p_volume_actor2 = vtkSmartPointer<vtkActor>::New();
             p_volume_actor2->SetMapper(p_mapper2);
             p_volume_actor2->GetProperty()->SetEdgeVisibility(this->mShowEdges);
             p_volume_actor2->GetProperty()->SetLineWidth(this->mEdgeSize);
@@ -414,10 +414,10 @@ void CellPopulationPyChasteActorGenerator<DIM>::AddActor(vtkSmartPointer<vtkRend
     if(mShowCellCentres || boost::dynamic_pointer_cast<CaBasedCellPopulation<DIM> >(mpCellPopulation) ||
             boost::dynamic_pointer_cast<NodeBasedCellPopulation<DIM> >(mpCellPopulation))
     {
-        vtkSmartPointer<vtkPoints> p_points = vtkSmartPointer<vtkPoints>::New();
-        vtkSmartPointer<vtkDoubleArray> p_cell_color_reference_data = vtkSmartPointer<vtkDoubleArray>::New();
+        auto p_points = vtkSmartPointer<vtkPoints>::New();
+        auto p_cell_color_reference_data = vtkSmartPointer<vtkDoubleArray>::New();
         p_cell_color_reference_data->SetName("CellColors");
-        vtkSmartPointer<vtkPolyData> p_polydata = vtkSmartPointer<vtkPolyData>::New();
+        auto p_polydata = vtkSmartPointer<vtkPolyData>::New();
 
         for (typename AbstractCellPopulation<DIM>::Iterator cell_iter = mpCellPopulation->Begin();
              cell_iter != mpCellPopulation->End(); ++cell_iter)
@@ -481,7 +481,7 @@ void CellPopulationPyChasteActorGenerator<DIM>::AddActor(vtkSmartPointer<vtkRend
         p_polydata->SetPoints(p_points);
         p_polydata->GetPointData()->AddArray(p_cell_color_reference_data);
 
-        vtkSmartPointer<vtkColorTransferFunction> p_scaled_ctf = vtkSmartPointer<vtkColorTransferFunction>::New();
+        auto p_scaled_ctf = vtkSmartPointer<vtkColorTransferFunction>::New();
         if(!mColorByCellData)
         {
             double range[2];
@@ -505,12 +505,12 @@ void CellPopulationPyChasteActorGenerator<DIM>::AddActor(vtkSmartPointer<vtkRend
             }
         }
 
-        vtkSmartPointer<vtkSphereSource> p_spheres = vtkSmartPointer<vtkSphereSource>::New();
+        auto p_spheres = vtkSmartPointer<vtkSphereSource>::New();
         p_spheres->SetRadius(this->mPointSize);
         p_spheres->SetPhiResolution(16);
         p_spheres->SetThetaResolution(16);
 
-        vtkSmartPointer<vtkGlyph3D> p_glyph = vtkSmartPointer<vtkGlyph3D>::New();
+        auto p_glyph = vtkSmartPointer<vtkGlyph3D>::New();
         p_glyph->SetInputData(p_polydata);
         p_glyph->SetSourceConnection(p_spheres->GetOutputPort());
         p_glyph->ClampingOff();
@@ -518,7 +518,7 @@ void CellPopulationPyChasteActorGenerator<DIM>::AddActor(vtkSmartPointer<vtkRend
         p_glyph->SetScaleFactor(1.0);
         p_glyph->Update();
 
-        vtkSmartPointer<vtkPolyDataMapper> p_mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
+        auto p_mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
         p_mapper->SetInputData(p_glyph->GetOutput());
         p_mapper->SetLookupTable(p_scaled_ctf);
         p_mapper->ScalarVisibilityOn();
@@ -526,7 +526,7 @@ void CellPopulationPyChasteActorGenerator<DIM>::AddActor(vtkSmartPointer<vtkRend
         p_mapper->SetScalarModeToUsePointFieldData();
         p_mapper->SetColorModeToMapScalars();
 
-        vtkSmartPointer<vtkActor> p_actor = vtkSmartPointer<vtkActor>::New();
+        auto p_actor = vtkSmartPointer<vtkActor>::New();
         p_actor->SetMapper(p_mapper);
         p_actor->GetProperty()->SetOpacity(this->mVolumeOpacity);
         if(mColorCellByUserDefined)
@@ -577,11 +577,11 @@ void CellPopulationPyChasteActorGenerator<DIM>::AddVertexBasedCellPopulationActo
 
     if(mShowVoronoiMeshEdges)
     {
-        vtkSmartPointer<vtkUnstructuredGrid> p_voronoi_grid = vtkSmartPointer<vtkUnstructuredGrid>::New();
-        vtkSmartPointer<vtkDoubleArray> p_cell_color_reference_data = vtkSmartPointer<vtkDoubleArray>::New();
+        auto p_voronoi_grid = vtkSmartPointer<vtkUnstructuredGrid>::New();
+        auto p_cell_color_reference_data = vtkSmartPointer<vtkDoubleArray>::New();
         p_cell_color_reference_data->SetName("CellColors");
 
-        vtkSmartPointer<vtkPoints> p_points = vtkSmartPointer<vtkPoints>::New();
+        auto p_points = vtkSmartPointer<vtkPoints>::New();
         p_points->GetData()->SetName("Vertex positions");
         for (unsigned node_num=0; node_num<p_cell_population->rGetMesh().GetNumNodes(); node_num++)
         {
@@ -672,7 +672,7 @@ void CellPopulationPyChasteActorGenerator<DIM>::AddVertexBasedCellPopulationActo
         p_voronoi_grid->GetCellData()->AddArray(p_cell_color_reference_data);
         p_voronoi_grid->GetCellData()->SetScalars(p_cell_color_reference_data);
 
-        vtkSmartPointer<vtkColorTransferFunction> p_scaled_ctf = vtkSmartPointer<vtkColorTransferFunction>::New();
+        auto p_scaled_ctf = vtkSmartPointer<vtkColorTransferFunction>::New();
         if(!mColorByCellData)
         {
             double range[2];
@@ -697,10 +697,10 @@ void CellPopulationPyChasteActorGenerator<DIM>::AddVertexBasedCellPopulationActo
         }
         p_scaled_ctf->Build();
 
-        vtkSmartPointer<vtkGeometryFilter> p_geom_filter = vtkSmartPointer<vtkGeometryFilter>::New();
+        auto p_geom_filter = vtkSmartPointer<vtkGeometryFilter>::New();
         p_geom_filter->SetInputData(p_voronoi_grid);
 
-        vtkSmartPointer<vtkPolyDataMapper> p_mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
+        auto p_mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
         p_mapper->SetInputConnection(p_geom_filter->GetOutputPort());
         p_mapper->SetLookupTable(p_scaled_ctf);
         p_mapper->ScalarVisibilityOn();
@@ -708,7 +708,7 @@ void CellPopulationPyChasteActorGenerator<DIM>::AddVertexBasedCellPopulationActo
         p_mapper->SetScalarModeToUseCellData();
         p_mapper->SetColorModeToMapScalars();
 
-        vtkSmartPointer<vtkActor> p_actor = vtkSmartPointer<vtkActor>::New();
+        auto p_actor = vtkSmartPointer<vtkActor>::New();
         p_actor->SetMapper(p_mapper);
         p_actor->GetProperty()->SetOpacity(this->mVolumeOpacity);
         if(mColorCellByUserDefined)
@@ -717,23 +717,23 @@ void CellPopulationPyChasteActorGenerator<DIM>::AddVertexBasedCellPopulationActo
         }
         pRenderer->AddActor(p_actor);
 
-        vtkSmartPointer<vtkFeatureEdges> p_voronoi_extract_edges = vtkSmartPointer<vtkFeatureEdges>::New();
+        auto p_voronoi_extract_edges = vtkSmartPointer<vtkFeatureEdges>::New();
         p_voronoi_extract_edges->SetInputConnection(p_geom_filter->GetOutputPort());
         p_voronoi_extract_edges->SetFeatureEdges(false);
         p_voronoi_extract_edges->SetBoundaryEdges(true);
         p_voronoi_extract_edges->SetManifoldEdges(true);
         p_voronoi_extract_edges->SetNonManifoldEdges(false);
 
-        vtkSmartPointer<vtkTubeFilter> p_voronoi_tubes = vtkSmartPointer<vtkTubeFilter>::New();
+        auto p_voronoi_tubes = vtkSmartPointer<vtkTubeFilter>::New();
         p_voronoi_tubes->SetInputConnection(p_voronoi_extract_edges->GetOutputPort());
         p_voronoi_tubes->SetRadius(this->mEdgeSize);
         p_voronoi_tubes->SetNumberOfSides(12);
 
-        vtkSmartPointer<vtkPolyDataMapper> p_voronoi_tube_mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
+        auto p_voronoi_tube_mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
         p_voronoi_tube_mapper->SetInputConnection(p_voronoi_tubes->GetOutputPort());
         p_voronoi_tube_mapper->ScalarVisibilityOff();
 
-        vtkSmartPointer<vtkActor> p_voronoi_tube_actor = vtkSmartPointer<vtkActor>::New();
+        auto p_voronoi_tube_actor = vtkSmartPointer<vtkActor>::New();
         p_voronoi_tube_actor->SetMapper(p_voronoi_tube_mapper);
         p_voronoi_tube_actor->GetProperty()->SetColor(this->mEdgeColor[0], this->mEdgeColor[1], this->mEdgeColor[2]);
         pRenderer->AddActor(p_voronoi_tube_actor);
@@ -759,11 +759,11 @@ void CellPopulationPyChasteActorGenerator<DIM>::AddImmersedBoundaryCellPopulatio
 
     if(mShowVoronoiMeshEdges)
     {
-        vtkSmartPointer<vtkUnstructuredGrid> p_voronoi_grid = vtkSmartPointer<vtkUnstructuredGrid>::New();
-        vtkSmartPointer<vtkDoubleArray> p_cell_color_reference_data = vtkSmartPointer<vtkDoubleArray>::New();
+        auto p_voronoi_grid = vtkSmartPointer<vtkUnstructuredGrid>::New();
+        auto p_cell_color_reference_data = vtkSmartPointer<vtkDoubleArray>::New();
         p_cell_color_reference_data->SetName("CellColors");
 
-        vtkSmartPointer<vtkPoints> p_points = vtkSmartPointer<vtkPoints>::New();
+        auto p_points = vtkSmartPointer<vtkPoints>::New();
         p_points->GetData()->SetName("Vertex positions");
         for (unsigned node_num=0; node_num<p_cell_population->rGetMesh().GetNumNodes(); node_num++)
         {
@@ -854,7 +854,7 @@ void CellPopulationPyChasteActorGenerator<DIM>::AddImmersedBoundaryCellPopulatio
         p_voronoi_grid->GetCellData()->AddArray(p_cell_color_reference_data);
         p_voronoi_grid->GetCellData()->SetScalars(p_cell_color_reference_data);
 
-        vtkSmartPointer<vtkColorTransferFunction> p_scaled_ctf = vtkSmartPointer<vtkColorTransferFunction>::New();
+        auto p_scaled_ctf = vtkSmartPointer<vtkColorTransferFunction>::New();
         if(!mColorByCellData)
         {
             double range[2];
@@ -879,10 +879,10 @@ void CellPopulationPyChasteActorGenerator<DIM>::AddImmersedBoundaryCellPopulatio
         }
         p_scaled_ctf->Build();
 
-        vtkSmartPointer<vtkGeometryFilter> p_geom_filter = vtkSmartPointer<vtkGeometryFilter>::New();
+        auto p_geom_filter = vtkSmartPointer<vtkGeometryFilter>::New();
         p_geom_filter->SetInputData(p_voronoi_grid);
 
-        vtkSmartPointer<vtkPolyDataMapper> p_mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
+        auto p_mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
         p_mapper->SetInputConnection(p_geom_filter->GetOutputPort());
         p_mapper->SetLookupTable(p_scaled_ctf);
         p_mapper->ScalarVisibilityOn();
@@ -890,7 +890,7 @@ void CellPopulationPyChasteActorGenerator<DIM>::AddImmersedBoundaryCellPopulatio
         p_mapper->SetScalarModeToUseCellData();
         p_mapper->SetColorModeToMapScalars();
 
-        vtkSmartPointer<vtkActor> p_actor = vtkSmartPointer<vtkActor>::New();
+        auto p_actor = vtkSmartPointer<vtkActor>::New();
         p_actor->SetMapper(p_mapper);
         p_actor->GetProperty()->SetOpacity(this->mVolumeOpacity);
         if(mColorCellByUserDefined)
@@ -899,23 +899,23 @@ void CellPopulationPyChasteActorGenerator<DIM>::AddImmersedBoundaryCellPopulatio
         }
         pRenderer->AddActor(p_actor);
 
-        vtkSmartPointer<vtkFeatureEdges> p_voronoi_extract_edges = vtkSmartPointer<vtkFeatureEdges>::New();
+        auto p_voronoi_extract_edges = vtkSmartPointer<vtkFeatureEdges>::New();
         p_voronoi_extract_edges->SetInputConnection(p_geom_filter->GetOutputPort());
         p_voronoi_extract_edges->SetFeatureEdges(false);
         p_voronoi_extract_edges->SetBoundaryEdges(true);
         p_voronoi_extract_edges->SetManifoldEdges(true);
         p_voronoi_extract_edges->SetNonManifoldEdges(false);
 
-        vtkSmartPointer<vtkTubeFilter> p_voronoi_tubes = vtkSmartPointer<vtkTubeFilter>::New();
+        auto p_voronoi_tubes = vtkSmartPointer<vtkTubeFilter>::New();
         p_voronoi_tubes->SetInputConnection(p_voronoi_extract_edges->GetOutputPort());
         p_voronoi_tubes->SetRadius(this->mEdgeSize);
         p_voronoi_tubes->SetNumberOfSides(12);
 
-        vtkSmartPointer<vtkPolyDataMapper> p_voronoi_tube_mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
+        auto p_voronoi_tube_mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
         p_voronoi_tube_mapper->SetInputConnection(p_voronoi_tubes->GetOutputPort());
         p_voronoi_tube_mapper->ScalarVisibilityOff();
 
-        vtkSmartPointer<vtkActor> p_voronoi_tube_actor = vtkSmartPointer<vtkActor>::New();
+        auto p_voronoi_tube_actor = vtkSmartPointer<vtkActor>::New();
         p_voronoi_tube_actor->SetMapper(p_voronoi_tube_mapper);
         p_voronoi_tube_actor->GetProperty()->SetColor(this->mEdgeColor[0], this->mEdgeColor[1], this->mEdgeColor[2]);
         pRenderer->AddActor(p_voronoi_tube_actor);
@@ -946,13 +946,13 @@ void CellPopulationPyChasteActorGenerator<DIM>::AddMeshBasedCellPopulationActor(
     if(mShowVoronoiMeshEdges)
     {
         p_cell_population->CreateVoronoiTessellation();
-        vtkSmartPointer<vtkUnstructuredGrid> p_voronoi_grid = vtkSmartPointer<vtkUnstructuredGrid>::New();
-        vtkSmartPointer<vtkDoubleArray> p_cell_color_reference_data = vtkSmartPointer<vtkDoubleArray>::New();
+        auto p_voronoi_grid = vtkSmartPointer<vtkUnstructuredGrid>::New();
+        auto p_cell_color_reference_data = vtkSmartPointer<vtkDoubleArray>::New();
         p_cell_color_reference_data->SetName("CellColors");
 
         if(p_cell_population->GetVoronoiTessellation() != NULL)
         {
-            vtkSmartPointer<vtkPoints> p_points = vtkSmartPointer<vtkPoints>::New();
+            auto p_points = vtkSmartPointer<vtkPoints>::New();
             p_points->GetData()->SetName("Vertex positions");
             for (unsigned node_num=0; node_num<p_cell_population->GetVoronoiTessellation()->GetNumNodes(); node_num++)
             {
@@ -1058,7 +1058,7 @@ void CellPopulationPyChasteActorGenerator<DIM>::AddMeshBasedCellPopulationActor(
         p_voronoi_grid->GetCellData()->AddArray(p_cell_color_reference_data);
         p_voronoi_grid->GetCellData()->SetScalars(p_cell_color_reference_data);
 
-        vtkSmartPointer<vtkColorTransferFunction> p_scaled_ctf = vtkSmartPointer<vtkColorTransferFunction>::New();
+        auto p_scaled_ctf = vtkSmartPointer<vtkColorTransferFunction>::New();
         if(!mColorByCellData)
         {
             double range[2];
@@ -1083,7 +1083,7 @@ void CellPopulationPyChasteActorGenerator<DIM>::AddMeshBasedCellPopulationActor(
         }
         p_scaled_ctf->Build();
 
-        vtkSmartPointer<vtkThreshold> p_threshold = vtkSmartPointer<vtkThreshold>::New();
+        auto p_threshold = vtkSmartPointer<vtkThreshold>::New();
         p_threshold->SetInputData(p_voronoi_grid);
 #if VTK_MAJOR_VERSION < 9
         p_threshold->ThresholdByUpper(0.0);
@@ -1092,10 +1092,10 @@ void CellPopulationPyChasteActorGenerator<DIM>::AddMeshBasedCellPopulationActor(
 #endif
         p_threshold->SetInputArrayToProcess(0, 0, 0, vtkDataObject::FIELD_ASSOCIATION_CELLS, "CellColors");
 
-        vtkSmartPointer<vtkGeometryFilter> p_geom_filter = vtkSmartPointer<vtkGeometryFilter>::New();
+        auto p_geom_filter = vtkSmartPointer<vtkGeometryFilter>::New();
         p_geom_filter->SetInputConnection(p_threshold->GetOutputPort());
 
-        vtkSmartPointer<vtkPolyDataMapper> p_mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
+        auto p_mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
         p_mapper->SetInputConnection(p_geom_filter->GetOutputPort());
         p_mapper->SetLookupTable(p_scaled_ctf);
         p_mapper->ScalarVisibilityOn();
@@ -1104,7 +1104,7 @@ void CellPopulationPyChasteActorGenerator<DIM>::AddMeshBasedCellPopulationActor(
         p_mapper->SetScalarModeToUseCellData();
         p_mapper->SetColorModeToMapScalars();
 
-        vtkSmartPointer<vtkActor> p_actor = vtkSmartPointer<vtkActor>::New();
+        auto p_actor = vtkSmartPointer<vtkActor>::New();
         p_actor->SetMapper(p_mapper);
         p_actor->GetProperty()->SetOpacity(this->mVolumeOpacity);
         if(mColorCellByUserDefined)
@@ -1113,23 +1113,23 @@ void CellPopulationPyChasteActorGenerator<DIM>::AddMeshBasedCellPopulationActor(
         }
         pRenderer->AddActor(p_actor);
 
-        vtkSmartPointer<vtkFeatureEdges> p_voronoi_extract_edges = vtkSmartPointer<vtkFeatureEdges>::New();
+        auto p_voronoi_extract_edges = vtkSmartPointer<vtkFeatureEdges>::New();
         p_voronoi_extract_edges->SetInputConnection(p_geom_filter->GetOutputPort());
         p_voronoi_extract_edges->SetFeatureEdges(false);
         p_voronoi_extract_edges->SetBoundaryEdges(true);
         p_voronoi_extract_edges->SetManifoldEdges(true);
         p_voronoi_extract_edges->SetNonManifoldEdges(false);
 
-        vtkSmartPointer<vtkTubeFilter> p_voronoi_tubes = vtkSmartPointer<vtkTubeFilter>::New();
+        auto p_voronoi_tubes = vtkSmartPointer<vtkTubeFilter>::New();
         p_voronoi_tubes->SetInputConnection(p_voronoi_extract_edges->GetOutputPort());
         p_voronoi_tubes->SetRadius(this->mEdgeSize);
         p_voronoi_tubes->SetNumberOfSides(12);
 
-        vtkSmartPointer<vtkPolyDataMapper> p_voronoi_tube_mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
+        auto p_voronoi_tube_mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
         p_voronoi_tube_mapper->SetInputConnection(p_voronoi_tubes->GetOutputPort());
         p_voronoi_tube_mapper->ScalarVisibilityOff();
 
-        vtkSmartPointer<vtkActor> p_voronoi_tube_actor = vtkSmartPointer<vtkActor>::New();
+        auto p_voronoi_tube_actor = vtkSmartPointer<vtkActor>::New();
         p_voronoi_tube_actor->SetMapper(p_voronoi_tube_mapper);
         p_voronoi_tube_actor->GetProperty()->SetColor(this->mEdgeColor[0], this->mEdgeColor[1], this->mEdgeColor[2]);
         pRenderer->AddActor(p_voronoi_tube_actor);
@@ -1146,8 +1146,8 @@ void CellPopulationPyChasteActorGenerator<DIM>::AddMeshBasedCellPopulationActor(
     {
         // Do the mutable mesh
         //Make the local mesh into a VtkMesh
-        vtkSmartPointer<vtkUnstructuredGrid> p_mutable_grid = vtkSmartPointer<vtkUnstructuredGrid>::New();
-        vtkSmartPointer<vtkPoints> p_points = vtkSmartPointer<vtkPoints>::New();
+        auto p_mutable_grid = vtkSmartPointer<vtkUnstructuredGrid>::New();
+        auto p_points = vtkSmartPointer<vtkPoints>::New();
         p_points->GetData()->SetName("Vertex positions");
 
         for (typename AbstractMesh<DIM,DIM>::NodeIterator node_iter = p_cell_population->rGetMesh().GetNodeIteratorBegin();
@@ -1198,25 +1198,25 @@ void CellPopulationPyChasteActorGenerator<DIM>::AddMeshBasedCellPopulationActor(
             p_mutable_grid->InsertNextCell(p_cell->GetCellType(), p_cell_id_list);
         }
 
-        vtkSmartPointer<vtkGeometryFilter> p_mutable_geom_filter = vtkSmartPointer<vtkGeometryFilter>::New();
+        auto p_mutable_geom_filter = vtkSmartPointer<vtkGeometryFilter>::New();
         p_mutable_geom_filter->SetInputData(p_mutable_grid);
 
-        vtkSmartPointer<vtkFeatureEdges> p_extract_edges = vtkSmartPointer<vtkFeatureEdges>::New();
+        auto p_extract_edges = vtkSmartPointer<vtkFeatureEdges>::New();
         p_extract_edges->SetInputConnection(p_mutable_geom_filter->GetOutputPort());
         p_extract_edges->SetFeatureEdges(false);
         p_extract_edges->SetBoundaryEdges(true);
         p_extract_edges->SetManifoldEdges(true);
         p_extract_edges->SetNonManifoldEdges(false);
 
-        vtkSmartPointer<vtkTubeFilter> p_mutable_tubes = vtkSmartPointer<vtkTubeFilter>::New();
+        auto p_mutable_tubes = vtkSmartPointer<vtkTubeFilter>::New();
         p_mutable_tubes->SetInputConnection(p_extract_edges->GetOutputPort());
         p_mutable_tubes->SetRadius(0.02);
         p_mutable_tubes->SetNumberOfSides(12);
 
-        vtkSmartPointer<vtkPolyDataMapper> p_mutable_mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
+        auto p_mutable_mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
         p_mutable_mapper->SetInputConnection(p_mutable_tubes->GetOutputPort());
 
-        vtkSmartPointer<vtkActor> p_mutable_actor = vtkSmartPointer<vtkActor>::New();
+        auto p_mutable_actor = vtkSmartPointer<vtkActor>::New();
         p_mutable_actor->SetMapper(p_mutable_mapper);
         p_mutable_actor->GetProperty()->SetColor(1,1,1);
         pRenderer->AddActor(p_mutable_actor);
diff --git a/src/visualization/VtkScene.cpp b/src/visualization/VtkScene.cpp
index 2ea30cb7..d7b815c3 100644
--- a/src/visualization/VtkScene.cpp
+++ b/src/visualization/VtkScene.cpp
@@ -165,7 +165,7 @@ vtkSmartPointer<vtkUnsignedCharArray> VtkScene<DIM>::GetSceneAsCharBuffer()
     mpRenderWindow->SetOffScreenRendering(1);
     mpRenderWindow->Render();
     mWindowToImageFilter->Modified();
-    vtkSmartPointer<vtkPNGWriter> p_writer = vtkSmartPointer<vtkPNGWriter>::New();
+    auto p_writer = vtkSmartPointer<vtkPNGWriter>::New();
     p_writer->SetWriteToMemory(1);
     p_writer->SetInputConnection(mWindowToImageFilter->GetOutputPort());
     p_writer->Write();
@@ -199,7 +199,7 @@ void VtkScene<DIM>::ResetRenderer(unsigned time_step)
         mpRenderWindow->SetOffScreenRendering(1);
         mpRenderWindow->Render();
         mWindowToImageFilter->Modified();
-        vtkSmartPointer<vtkPNGWriter> p_writer = vtkSmartPointer<vtkPNGWriter>::New();
+        auto p_writer = vtkSmartPointer<vtkPNGWriter>::New();
         p_writer->SetWriteToMemory(1);
         p_writer->SetInputConnection(mWindowToImageFilter->GetOutputPort());
         if(!mOutputFilePath.empty())

From f74cb6622ced789632e316163b8b6c95c05f9208 Mon Sep 17 00:00:00 2001
From: Kwabena N Amponsah <kwabenantim@yahoo.com>
Date: Fri, 17 May 2024 08:55:19 +0000
Subject: [PATCH 09/12] #24 less verbose boost shared pointer

---
 test/visualization/TestVtkSceneWithCaBased.hpp    |  7 +++----
 test/visualization/TestVtkSceneWithMeshBased.hpp  | 14 ++++++--------
 test/visualization/TestVtkSceneWithPottsBased.hpp | 14 ++++++--------
 3 files changed, 15 insertions(+), 20 deletions(-)

diff --git a/test/visualization/TestVtkSceneWithCaBased.hpp b/test/visualization/TestVtkSceneWithCaBased.hpp
index 31ee878c..650ca18d 100644
--- a/test/visualization/TestVtkSceneWithCaBased.hpp
+++ b/test/visualization/TestVtkSceneWithCaBased.hpp
@@ -130,16 +130,15 @@ class TestVtkSceneWithCaBasedPopulation : public AbstractCellBasedTestSuite
         cells_generator.GenerateBasic(cells, location_indices.size());
 
         // Create cell population
-        boost::shared_ptr<CaBasedCellPopulation<3> > p_cell_population =
-                boost::make_shared<CaBasedCellPopulation<3> >(*p_mesh, cells, location_indices);
+        auto p_cell_population = boost::make_shared<CaBasedCellPopulation<3> >(*p_mesh, cells, location_indices);
 
-        boost::shared_ptr<VtkScene<3> > p_scene = boost::make_shared<VtkScene<3> >();
+        auto p_scene = boost::make_shared<VtkScene<3> >();
         p_scene->SetCellPopulation(p_cell_population);
         p_scene->SetSaveAsImages(true);
         p_scene->GetCellPopulationActorGenerator()->SetShowPottsMeshEdges(true);
         p_scene->SetOutputFilePath(file_handler1.GetOutputDirectoryFullPath()+"/cell_population");
 
-        boost::shared_ptr<VtkSceneModifier<3> > p_scene_modifier = boost::make_shared<VtkSceneModifier<3> >();
+        auto p_scene_modifier = boost::make_shared<VtkSceneModifier<3> >();
         p_scene_modifier->SetVtkScene(p_scene);
 
         p_scene->Start();
diff --git a/test/visualization/TestVtkSceneWithMeshBased.hpp b/test/visualization/TestVtkSceneWithMeshBased.hpp
index 314a4499..47bb715c 100644
--- a/test/visualization/TestVtkSceneWithMeshBased.hpp
+++ b/test/visualization/TestVtkSceneWithMeshBased.hpp
@@ -87,16 +87,15 @@ class TestVtkSceneWithMeshBasedPopulation : public AbstractCellBasedTestSuite
         MAKE_PTR(TransitCellProliferativeType, p_transit_type);
         CellsGenerator<UniformCellCycleModel, 2> cells_generator;
         cells_generator.GenerateBasicRandom(cells, location_indices.size(), p_transit_type);
-        boost::shared_ptr<MeshBasedCellPopulationWithGhostNodes<2> > p_cell_population =
-                boost::shared_ptr<MeshBasedCellPopulationWithGhostNodes<2> >(new MeshBasedCellPopulationWithGhostNodes<2> (*p_mesh, cells, location_indices));
+        auto p_cell_population = boost::make_shared<MeshBasedCellPopulationWithGhostNodes<2> >(*p_mesh, cells, location_indices);
         p_cell_population->AddPopulationWriter<VoronoiDataWriter>();
 
-        boost::shared_ptr<VtkScene<2> > p_scene = boost::shared_ptr<VtkScene<2> >(new VtkScene<2>);
+        auto p_scene = boost::make_shared<VtkScene<2> >();
         p_scene->SetCellPopulation(p_cell_population);
         p_scene->SetSaveAsImages(true);
         p_scene->SetOutputFilePath(file_handler1.GetOutputDirectoryFullPath()+"/cell_population");
 
-        boost::shared_ptr<VtkSceneModifier<2> > p_scene_modifier = boost::shared_ptr<VtkSceneModifier<2> >(new VtkSceneModifier<2>);
+        auto p_scene_modifier = boost::make_shared<VtkSceneModifier<2> >();
         p_scene_modifier->SetVtkScene(p_scene);
         p_scene->Start();
 
@@ -128,17 +127,16 @@ class TestVtkSceneWithMeshBasedPopulation : public AbstractCellBasedTestSuite
         CellsGenerator<UniformCellCycleModel, 3> cells_generator;
         cells_generator.GenerateBasicRandom(cells, mesh.GetNumNodes(), p_transit_type);
 
-        boost::shared_ptr<MeshBasedCellPopulation<3> > p_cell_population =
-                boost::shared_ptr<MeshBasedCellPopulation<3> >(new MeshBasedCellPopulation<3> (mesh, cells));
+        auto p_cell_population = boost::make_shared<MeshBasedCellPopulation<3> >(mesh, cells);
         p_cell_population->SetAbsoluteMovementThreshold(DBL_MAX);
         p_cell_population->AddPopulationWriter<VoronoiDataWriter>();
 
-        boost::shared_ptr<VtkScene<3> > p_scene = boost::shared_ptr<VtkScene<3> >(new VtkScene<3>);
+        auto p_scene = boost::make_shared<VtkScene<3> >();
         p_scene->SetCellPopulation(p_cell_population);
         p_scene->SetSaveAsImages(true);
         p_scene->SetOutputFilePath(file_handler1.GetOutputDirectoryFullPath()+"/cell_population");
 
-        boost::shared_ptr<VtkSceneModifier<3> > p_scene_modifier = boost::shared_ptr<VtkSceneModifier<3> >(new VtkSceneModifier<3>);
+        auto p_scene_modifier = boost::make_shared<VtkSceneModifier<3> >();
         p_scene_modifier->SetVtkScene(p_scene);
         p_scene->Start();
 
diff --git a/test/visualization/TestVtkSceneWithPottsBased.hpp b/test/visualization/TestVtkSceneWithPottsBased.hpp
index 3be3fea6..82e235a0 100644
--- a/test/visualization/TestVtkSceneWithPottsBased.hpp
+++ b/test/visualization/TestVtkSceneWithPottsBased.hpp
@@ -87,8 +87,7 @@ class TestVtkScene : public AbstractCellBasedTestSuite
         CellsGenerator<UniformCellCycleModel, 2> cells_generator;
         cells_generator.GenerateBasicRandom(cells, p_mesh->GetNumElements(), p_transit_type);
 
-        boost::shared_ptr<PottsBasedCellPopulation<2> >  p_cell_population =
-                boost::shared_ptr<PottsBasedCellPopulation<2> >(new PottsBasedCellPopulation<2> (*p_mesh, cells));
+        auto  p_cell_population = boost::make_shared<PottsBasedCellPopulation<2> >(*p_mesh, cells);
         p_cell_population->SetTemperature(0.1);
         p_cell_population->SetNumSweepsPerTimestep(1);
 
@@ -98,14 +97,14 @@ class TestVtkScene : public AbstractCellBasedTestSuite
         simulator.SetDt(0.1);
         simulator.SetSamplingTimestepMultiple(10);
 
-        boost::shared_ptr<VtkScene<2> > p_scene = boost::shared_ptr<VtkScene<2> >(new VtkScene<2>);
+        auto p_scene = boost::make_shared<VtkScene<2> >();
         p_scene->SetCellPopulation(p_cell_population);
         p_scene->SetIsInteractive(true);
         p_scene->SetSaveAsImages(false);
         p_scene->GetCellPopulationActorGenerator()->SetShowPottsMeshEdges(true);
         p_scene->SetOutputFilePath(file_handler1.GetOutputDirectoryFullPath()+"/cell_population");
 
-        boost::shared_ptr<VtkSceneModifier<2> > p_scene_modifier = boost::shared_ptr<VtkSceneModifier<2> >(new VtkSceneModifier<2>);
+        auto p_scene_modifier = boost::make_shared<VtkSceneModifier<2> >();
         p_scene_modifier->SetVtkScene(p_scene);
         p_scene_modifier->SetUpdateFrequency(10);
         p_scene->Start();
@@ -132,8 +131,7 @@ class TestVtkScene : public AbstractCellBasedTestSuite
         CellsGenerator<UniformCellCycleModel, 3> cells_generator;
         cells_generator.GenerateBasicRandom(cells, p_mesh->GetNumElements(), p_transit_type);
 
-        boost::shared_ptr<PottsBasedCellPopulation<3> >  p_cell_population =
-                boost::shared_ptr<PottsBasedCellPopulation<3> >(new PottsBasedCellPopulation<3> (*p_mesh, cells));
+        auto p_cell_population = boost::make_shared<PottsBasedCellPopulation<3> >(*p_mesh, cells);
         p_cell_population->SetTemperature(0.1);
         p_cell_population->SetNumSweepsPerTimestep(1);
 
@@ -143,7 +141,7 @@ class TestVtkScene : public AbstractCellBasedTestSuite
         simulator.SetDt(0.1);
         simulator.SetSamplingTimestepMultiple(100);
 
-        boost::shared_ptr<VtkScene<3> > p_scene = boost::shared_ptr<VtkScene<3> >(new VtkScene<3>);
+        auto p_scene = boost::make_shared<VtkScene<3> >();
         p_scene->SetCellPopulation(p_cell_population);
         p_scene->SetIsInteractive(true);
         p_scene->SetSaveAsImages(false);
@@ -151,7 +149,7 @@ class TestVtkScene : public AbstractCellBasedTestSuite
         p_scene->GetCellPopulationActorGenerator()->SetShowPottsMeshOutlines(true);
         p_scene->SetOutputFilePath(file_handler1.GetOutputDirectoryFullPath()+"/cell_population");
 
-        boost::shared_ptr<VtkSceneModifier<3> > p_scene_modifier = boost::shared_ptr<VtkSceneModifier<3> >(new VtkSceneModifier<3>);
+        auto p_scene_modifier = boost::make_shared<VtkSceneModifier<3> >();
         p_scene_modifier->SetVtkScene(p_scene);
         p_scene->Start();
 

From a611e13ff1883832e6d347e68ea1cc504ece9871 Mon Sep 17 00:00:00 2001
From: Kwabena N Amponsah <kwabenantim@yahoo.com>
Date: Fri, 17 May 2024 19:49:21 +0000
Subject: [PATCH 10/12] #24 restructure cmake

---
 CMakeLists.txt        | 152 ++++++++++++++++++++++++++++++++++++++++--
 ProjectIncludes.cmake |  39 -----------
 WrapPython.cmake      | 136 -------------------------------------
 3 files changed, 147 insertions(+), 180 deletions(-)
 delete mode 100644 ProjectIncludes.cmake
 delete mode 100644 WrapPython.cmake

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 2ab892e3..e5d6a455 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -30,6 +30,11 @@
 # OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 # 
 
+#========================================
+# Setup PyChaste project
+#========================================
+
+# PyChaste needs the cell_based component (and its dependencies)
 find_package(Chaste COMPONENTS cell_based)
 
 # PyChaste needs some additional VTK libraries
@@ -73,12 +78,149 @@ else()
 endif()
 
 if (VTK_MAJOR_VERSION LESS 9)
-    list(APPEND Chaste_INCLUDES ${VTK_INCLUDE_DIRS})
-    list(APPEND Chaste_project_PyChaste_INCLUDE_DIRS ${VTK_INCLUDE_DIRS})
-    list(APPEND Chaste_THIRD_PARTY_LIBRARIES ${VTK_LIBRARIES})
+    list(APPEND Chaste_INCLUDES "${VTK_INCLUDE_DIRS}")
+    list(APPEND Chaste_project_PyChaste_INCLUDE_DIRS "${VTK_INCLUDE_DIRS}")
+    list(APPEND Chaste_THIRD_PARTY_LIBRARIES "${VTK_LIBRARIES}")
+else()
+    target_link_libraries(Chaste_COMMON_DEPS INTERFACE ${VTK_LIBRARIES})
 endif ()
 
+# Do Chaste project preprocessing, which results in something like:
+#   add_custom_target(project_PyChaste)
+#   set(Chaste_project_PyChaste_SOURCE_DIR ...)
+#   set(Chaste_project_PyChaste_INCLUDE_DIRS ...)
+#   include_directories("${Chaste_THIRD_PARTY_INCLUDE_DIRS}")
+#   include_directories("${Chaste_project_PyChaste_INCLUDE_DIRS}")
+#   include_directories("${Chaste_INCLUDE_DIRS}")
+#   add_library(chaste_project_PyChaste ...)
+#   target_link_libraries(chaste_project_PyChaste ...)
 chaste_do_project(PyChaste)
 
-# Include the Python wrapping build logic
-include(${CMAKE_CURRENT_SOURCE_DIR}/WrapPython.cmake)
+#========================================
+# Compiler options
+#========================================
+add_compile_options(-Wno-unused-local-typedefs)
+
+if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
+    # https://stackoverflow.com/questions/25365160/boostmultiprecisionfloat128-and-c11
+    add_compile_options(-fext-numeric-literals)
+endif()
+
+#========================================
+# PyChaste non-wrapper C++ code
+#========================================
+
+# Non-wrapper code locations
+set(PYCHASTE_INCLUDE_DIRS
+    ${CMAKE_CURRENT_SOURCE_DIR}/src/
+    ${CMAKE_CURRENT_SOURCE_DIR}/src/cell_based/
+    ${CMAKE_CURRENT_SOURCE_DIR}/src/ode/
+    ${CMAKE_CURRENT_SOURCE_DIR}/src/tutorial/
+    ${CMAKE_CURRENT_SOURCE_DIR}/src/visualization/
+    ${CMAKE_CURRENT_SOURCE_DIR}/dynamic/)
+
+# Non-wrapper code needs to be put in a separate shared library
+set(PYCHASTE_SHARED_LIB
+    "${CMAKE_CURRENT_BINARY_DIR}/libchaste_project_PyChaste${CMAKE_SHARED_LIBRARY_SUFFIX}")
+
+#========================================
+# Target for wrapper auto-generation
+#========================================
+add_custom_target(project_PyChaste_Python_Bindings)
+add_custom_command(TARGET project_PyChaste_Python_Bindings
+    COMMAND cppwg ${CMAKE_SOURCE_DIR}
+        -w ${CMAKE_CURRENT_SOURCE_DIR}/dynamic/wrappers
+        -p ${CMAKE_CURRENT_SOURCE_DIR}/dynamic/wrapper_generators/package_info.yaml
+        -i ${PYCHASTE_INCLUDE_DIRS} ${Chaste_INCLUDE_DIRS} ${Chaste_THIRD_PARTY_INCLUDE_DIRS}
+        --std c++17
+)
+
+#========================================
+# Build python modules from wrappers
+#========================================
+include_directories(${PYCHASTE_INCLUDE_DIRS})
+include_directories(${CMAKE_CURRENT_SOURCE_DIR}/dynamic/wrappers)
+include_directories(${PYTHON3_INCLUDE_DIRS})
+
+add_subdirectory(dynamic/pybind11)
+
+# Copy python package structure to build directory, ignoring existing shared libraries
+file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/src/python/
+     DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/python/
+     PATTERN "*${CMAKE_SHARED_LIBRARY_SUFFIX}" EXCLUDE)
+
+file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/test/python/
+     DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/python/test/)
+
+file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/doc/
+     DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/python/doc/)
+
+# List of modules to build into shared libraries
+set (PYCHASTE_PYTHON_MODULES
+        # Modules with auto-generated wrappers
+        core
+        ode
+        pde
+        mesh
+        cell_based
+        visualization
+        tutorial
+        # Modules with manual wrappers
+        preload
+        tutorial_manual)
+
+# Locations to put each module library
+set (PYCHASTE_PYTHON_MODULE_LOCATIONS
+        # Modules with auto-generated wrappers
+        ${CMAKE_CURRENT_BINARY_DIR}/python/chaste/core/
+        ${CMAKE_CURRENT_BINARY_DIR}/python/chaste/ode/
+        ${CMAKE_CURRENT_BINARY_DIR}/python/chaste/pde/
+        ${CMAKE_CURRENT_BINARY_DIR}/python/chaste/mesh/
+        ${CMAKE_CURRENT_BINARY_DIR}/python/chaste/cell_based/
+        ${CMAKE_CURRENT_BINARY_DIR}/python/chaste/visualization/
+        ${CMAKE_CURRENT_BINARY_DIR}/python/chaste/tutorial/
+        # Modules with manual wrappers
+        ${CMAKE_CURRENT_BINARY_DIR}/python/chaste/
+        ${CMAKE_CURRENT_BINARY_DIR}/python/chaste/tutorial/)
+
+# Create a shared library target for each module
+list(LENGTH PYCHASTE_PYTHON_MODULES max_module_idx)
+math(EXPR max_module_idx "${max_module_idx} - 1")
+set(module_prefix "_chaste_project_PyChaste_")
+
+foreach(idx RANGE ${max_module_idx})
+    list(GET PYCHASTE_PYTHON_MODULES ${idx} module_name)
+    list(GET PYCHASTE_PYTHON_MODULE_LOCATIONS ${idx} module_dir)
+
+    # Glob the module's wrapper code from the `dynamic` directory
+    file(GLOB module_sources ${CMAKE_CURRENT_SOURCE_DIR}/dynamic/wrappers/${module_name}/*.cpp)
+
+    # The module library name here must be the same as the pybind11 module name
+    # defined in the main wrapper e.g. `dynamic/wrappers/ode/ode.main.cpp`
+    # defines a pybind11 module `_chaste_project_PyChaste_ode`. By convention,
+    # the name starts with an underscore. The usual 'lib' prefix is disabled.
+    add_library(${module_prefix}${module_name} SHARED ${module_sources})
+
+    set_target_properties(${module_prefix}${module_name}
+        PROPERTIES
+            LIBRARY_OUTPUT_DIRECTORY ${module_dir}
+            PREFIX "${PYTHON_MODULE_PREFIX}"
+            SUFFIX "${CMAKE_SHARED_LIBRARY_SUFFIX}")
+
+    # The order here is important - pybind11 and python come first
+    target_link_libraries(${module_prefix}${module_name}
+        pybind11::module
+        ${PYTHON3_LIBRARIES}
+        ${Chaste_THIRD_PARTY_LIBRARIES}
+        ${Chaste_LIBRARIES}
+        ${PYCHASTE_SHARED_LIB})
+
+    add_dependencies(${module_prefix}${module_name} chaste_project_PyChaste)
+endforeach()
+
+# Target for building all module shared libraries
+add_custom_target(project_PyChaste_Python)
+foreach(idx RANGE ${max_module_idx})
+    list(GET PYCHASTE_PYTHON_MODULES ${idx} module_name)
+    add_dependencies(project_PyChaste_Python ${module_prefix}${module_name})
+endforeach()
diff --git a/ProjectIncludes.cmake b/ProjectIncludes.cmake
deleted file mode 100644
index a919baef..00000000
--- a/ProjectIncludes.cmake
+++ /dev/null
@@ -1,39 +0,0 @@
-# Copyright (c) 2005-2024, University of Oxford.
-# All rights reserved.
-# 
-# University of Oxford means the Chancellor, Masters and Scholars of the
-# University of Oxford, having an administrative office at Wellington
-# Square, Oxford OX1 2JD, UK.
-# 
-# This file is part of Chaste.
-# 
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are met:
-#  * Redistributions of source code must retain the above copyright notice,
-#    this list of conditions and the following disclaimer.
-#  * Redistributions in binary form must reproduce the above copyright notice,
-#    this list of conditions and the following disclaimer in the documentation
-#    and/or other materials provided with the distribution.
-#  * Neither the name of the University of Oxford nor the names of its
-#    contributors may be used to endorse or promote products derived from this
-#    software without specific prior written permission.
-# 
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
-# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
-# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
-# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-# 
-
-######### Collect the include directories for the project. ###################### 
-set(PYCHASTE_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/src/)
-list (APPEND PYCHASTE_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/src/cell_based)
-list (APPEND PYCHASTE_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/src/ode)
-list (APPEND PYCHASTE_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/src/tutorial)
-list (APPEND PYCHASTE_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/src/visualization)
-list (APPEND PYCHASTE_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/dynamic)
\ No newline at end of file
diff --git a/WrapPython.cmake b/WrapPython.cmake
deleted file mode 100644
index 639ebd01..00000000
--- a/WrapPython.cmake
+++ /dev/null
@@ -1,136 +0,0 @@
-# Copyright (c) 2005-2024, University of Oxford.
-# All rights reserved.
-# 
-# University of Oxford means the Chancellor, Masters and Scholars of the
-# University of Oxford, having an administrative office at Wellington
-# Square, Oxford OX1 2JD, UK.
-# 
-# This file is part of Chaste.
-# 
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are met:
-#  * Redistributions of source code must retain the above copyright notice,
-#    this list of conditions and the following disclaimer.
-#  * Redistributions in binary form must reproduce the above copyright notice,
-#    this list of conditions and the following disclaimer in the documentation
-#    and/or other materials provided with the distribution.
-#  * Neither the name of the University of Oxford nor the names of its
-#    contributors may be used to endorse or promote products derived from this
-#    software without specific prior written permission.
-# 
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
-# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
-# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
-# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-# 
-add_compile_options(-Wno-unused-local-typedefs)
-
-######### Find the dependencies for wrapper building ###################### 
-# Add any cmake modules defined in this project
-list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR} PARENT_SCOPE)
-
-# Find the Chaste and third party dependency header files.
-include_directories(${Chaste_INCLUDE_DIRS} ${Chaste_THIRD_PARTY_INCLUDE_DIRS})
-
-# Any non-wrapper code (code in the src folder) in this project needs to be put in its own shared library. 
-if(APPLE)
-    set(PYCHASTE_SHARED_LIB ${CMAKE_CURRENT_BINARY_DIR}/libchaste_project_PyChaste.dylib)
-elseif(WIN32)
-    set(PYCHASTE_SHARED_LIB ${CMAKE_CURRENT_BINARY_DIR}/libchaste_project_PyChaste.dll)  
-else()
-    set(PYCHASTE_SHARED_LIB ${CMAKE_CURRENT_BINARY_DIR}/libchaste_project_PyChaste.so)  
-endif()
-
-# Collect the header directories for this project
-include(${CMAKE_CURRENT_SOURCE_DIR}/ProjectIncludes.cmake)
-include_directories(${PYCHASTE_INCLUDE_DIRS})
-include_directories(${CMAKE_CURRENT_SOURCE_DIR}/dynamic/)
-include_directories(${CMAKE_CURRENT_SOURCE_DIR}/dynamic/wrappers)
-
-if(CMAKE_COMPILER_IS_GNUCXX)
-        # https://svn.boost.org/trac/boost/ticket/9240
-        set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fext-numeric-literals")
-endif()
-include_directories(${CMAKE_CURRENT_SOURCE_DIR}/dynamic/pybind11/include)
-
-add_subdirectory(dynamic/pybind11)
-include_directories(${PYTHON3_INCLUDE_DIRS})
-
-######### Build the Python modules ###################### 
-set (PYCHASTE_PYTHON_AUTO_MODULES "")
-set (PYCHASTE_PYTHON_MODULES "")
-# The shared library corresponding to this module needs to be put in the correct place in the package tree after it is built, put the location here.
-set (PYCHASTE_PYTHON_MODULE_LOCATIONS "")
-
-# Add each module to be built to this list. 
-# Modules with auto wrapping
-list (APPEND PYCHASTE_PYTHON_AUTO_MODULES core)
-list (APPEND PYCHASTE_PYTHON_MODULE_LOCATIONS ${CMAKE_CURRENT_BINARY_DIR}/python/chaste/core)
-list (APPEND PYCHASTE_PYTHON_AUTO_MODULES ode)
-list (APPEND PYCHASTE_PYTHON_MODULE_LOCATIONS ${CMAKE_CURRENT_BINARY_DIR}/python/chaste/ode)
-list (APPEND PYCHASTE_PYTHON_AUTO_MODULES pde)
-list (APPEND PYCHASTE_PYTHON_MODULE_LOCATIONS ${CMAKE_CURRENT_BINARY_DIR}/python/chaste/pde)
-list (APPEND PYCHASTE_PYTHON_AUTO_MODULES mesh)
-list (APPEND PYCHASTE_PYTHON_MODULE_LOCATIONS ${CMAKE_CURRENT_BINARY_DIR}/python/chaste/mesh)
-list (APPEND PYCHASTE_PYTHON_AUTO_MODULES cell_based)
-list (APPEND PYCHASTE_PYTHON_MODULE_LOCATIONS ${CMAKE_CURRENT_BINARY_DIR}/python/chaste/cell_based)
-list (APPEND PYCHASTE_PYTHON_AUTO_MODULES visualization)
-list (APPEND PYCHASTE_PYTHON_MODULE_LOCATIONS ${CMAKE_CURRENT_BINARY_DIR}/python/chaste/visualization)
-list (APPEND PYCHASTE_PYTHON_AUTO_MODULES tutorial)
-list (APPEND PYCHASTE_PYTHON_MODULE_LOCATIONS ${CMAKE_CURRENT_BINARY_DIR}/python/chaste/tutorial)
-list (APPEND PYCHASTE_PYTHON_MODULES ${PYCHASTE_PYTHON_AUTO_MODULES})
-
-# Modules with manual wrapping
-list (APPEND PYCHASTE_PYTHON_MODULES preload)
-list (APPEND PYCHASTE_PYTHON_MODULE_LOCATIONS ${CMAKE_CURRENT_BINARY_DIR}/python/chaste/)
-list (APPEND PYCHASTE_PYTHON_MODULES tutorial_manual)
-list (APPEND PYCHASTE_PYTHON_MODULE_LOCATIONS ${CMAKE_CURRENT_BINARY_DIR}/python/chaste/tutorial/)
-
-# Copy the Python package (i.e. all source files etc) to the build folder, ignore any shared libraries that might be in there.
-file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/src/python/ DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/python/ PATTERN "*.so" EXCLUDE)
-file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/test/python/ DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/python/test/)
-file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/doc/ DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/python/doc/)
-
-# Target to generate bindings
-add_custom_target(project_PyChaste_Python_Bindings)
-add_custom_command(
-    TARGET project_PyChaste_Python_Bindings
-    COMMAND cppwg ${CMAKE_SOURCE_DIR}
-        -w ${CMAKE_CURRENT_SOURCE_DIR}/dynamic/wrappers
-        -p ${CMAKE_CURRENT_SOURCE_DIR}/dynamic/wrapper_generators/package_info.yaml
-        -i ${PYCHASTE_INCLUDE_DIRS} ${Chaste_INCLUDE_DIRS} ${Chaste_THIRD_PARTY_INCLUDE_DIRS}
-        --std c++17
-)
-
-# Loop through each module and create the shared library targets
-list(LENGTH PYCHASTE_PYTHON_MODULES len1)
-math(EXPR len2 "${len1} - 1")
-foreach(val RANGE ${len2})
-    list(GET PYCHASTE_PYTHON_MODULES ${val} python_module)
-    list(GET PYCHASTE_PYTHON_MODULE_LOCATIONS ${val} python_module_location)
-    
-    file(GLOB MODULE_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/dynamic/wrappers/${python_module}/*.cpp)
-    
-    # each module is in the 'dynamic' directory. The library name must be the same as that defined in the cpp file. It is customary
-    # to start the name with an underscore. The usual 'lib' prefix is disabled.
-    add_library(_chaste_project_PyChaste_${python_module} SHARED ${MODULE_SOURCES})
-    set_target_properties(_chaste_project_PyChaste_${python_module} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${python_module_location} 
-        PREFIX "${PYTHON_MODULE_PREFIX}" SUFFIX ".so")
-    target_compile_features(_chaste_project_PyChaste_${python_module} PRIVATE cxx_range_for)
-    # order is important, pybind and python come first
-    target_link_libraries(_chaste_project_PyChaste_${python_module} pybind11::module ${PYTHON3_LIBRARIES} ${Chaste_THIRD_PARTY_LIBRARIES} ${Chaste_LIBRARIES} ${PYCHASTE_SHARED_LIB} Chaste_COMMON_DEPS)
-    add_dependencies(_chaste_project_PyChaste_${python_module} chaste_project_PyChaste)
-endforeach()
-
-# Add a target so all the libraries are built with a single command
-add_custom_target(project_PyChaste_Python)
-foreach(val RANGE ${len2})
-    list(GET PYCHASTE_PYTHON_MODULES ${val} python_module)
-    add_dependencies(project_PyChaste_Python _chaste_project_PyChaste_${python_module})
-endforeach()

From 52dbc0674485a4d150f11ffa1d693d1876e5db58 Mon Sep 17 00:00:00 2001
From: Kwabena N Amponsah <kwabenantim@yahoo.com>
Date: Tue, 21 May 2024 16:01:08 +0000
Subject: [PATCH 11/12] #24 fix vtkWrappingPythonCore

---
 CMakeLists.txt | 79 ++++++++++++++++++++++++++++----------------------
 1 file changed, 44 insertions(+), 35 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index e5d6a455..62cffdd6 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -37,6 +37,23 @@
 # PyChaste needs the cell_based component (and its dependencies)
 find_package(Chaste COMPONENTS cell_based)
 
+# Do Chaste project preprocessing, which results in something like:
+#   add_custom_target(project_PyChaste)
+#   set(Chaste_project_PyChaste_SOURCE_DIR ...)
+#   set(Chaste_project_PyChaste_INCLUDE_DIRS ...)
+#   include_directories("${Chaste_THIRD_PARTY_INCLUDE_DIRS}")
+#   include_directories("${Chaste_project_PyChaste_INCLUDE_DIRS}")
+#   include_directories("${Chaste_INCLUDE_DIRS}")
+#   add_library(chaste_project_PyChaste ...)
+#   target_link_libraries(chaste_project_PyChaste ...)
+chaste_do_project(PyChaste)
+
+add_library(PyChaste_COMMON_DEPS INTERFACE)
+
+# PyChaste needs the Python3 development libraries
+find_package(Python3 REQUIRED COMPONENTS Interpreter Development)
+target_link_libraries(PyChaste_COMMON_DEPS INTERFACE Python3::Module)
+
 # PyChaste needs some additional VTK libraries
 if(VTK_MAJOR_VERSION LESS 7)
     find_package(VTK REQUIRED COMPONENTS
@@ -71,9 +88,9 @@ else()
         IOMovie
         RenderingAnnotation
         RenderingCore
-        RenderingFreeType
-        RenderingOpenGL2
-        WrappingPythonCore
+        # RenderingFreeType # needs Freetype::Freetype
+        # RenderingOpenGL2 # needs X11::X11 and GLEW::GLEW
+        WrappingPythonCore # needs Python3::Module
     )
 endif()
 
@@ -82,20 +99,10 @@ if (VTK_MAJOR_VERSION LESS 9)
     list(APPEND Chaste_project_PyChaste_INCLUDE_DIRS "${VTK_INCLUDE_DIRS}")
     list(APPEND Chaste_THIRD_PARTY_LIBRARIES "${VTK_LIBRARIES}")
 else()
-    target_link_libraries(Chaste_COMMON_DEPS INTERFACE ${VTK_LIBRARIES})
+    target_link_libraries(PyChaste_COMMON_DEPS INTERFACE VTK::WrappingPythonCore)
+    # target_link_libraries(PyChaste_COMMON_DEPS INTERFACE ${VTK_LIBRARIES})
 endif ()
 
-# Do Chaste project preprocessing, which results in something like:
-#   add_custom_target(project_PyChaste)
-#   set(Chaste_project_PyChaste_SOURCE_DIR ...)
-#   set(Chaste_project_PyChaste_INCLUDE_DIRS ...)
-#   include_directories("${Chaste_THIRD_PARTY_INCLUDE_DIRS}")
-#   include_directories("${Chaste_project_PyChaste_INCLUDE_DIRS}")
-#   include_directories("${Chaste_INCLUDE_DIRS}")
-#   add_library(chaste_project_PyChaste ...)
-#   target_link_libraries(chaste_project_PyChaste ...)
-chaste_do_project(PyChaste)
-
 #========================================
 # Compiler options
 #========================================
@@ -116,8 +123,7 @@ set(PYCHASTE_INCLUDE_DIRS
     ${CMAKE_CURRENT_SOURCE_DIR}/src/cell_based/
     ${CMAKE_CURRENT_SOURCE_DIR}/src/ode/
     ${CMAKE_CURRENT_SOURCE_DIR}/src/tutorial/
-    ${CMAKE_CURRENT_SOURCE_DIR}/src/visualization/
-    ${CMAKE_CURRENT_SOURCE_DIR}/dynamic/)
+    ${CMAKE_CURRENT_SOURCE_DIR}/src/visualization/)
 
 # Non-wrapper code needs to be put in a separate shared library
 set(PYCHASTE_SHARED_LIB
@@ -183,44 +189,47 @@ set (PYCHASTE_PYTHON_MODULE_LOCATIONS
         ${CMAKE_CURRENT_BINARY_DIR}/python/chaste/
         ${CMAKE_CURRENT_BINARY_DIR}/python/chaste/tutorial/)
 
+# The module library name must be the same as the pybind11 module name
+# defined in the main wrapper e.g. `dynamic/wrappers/ode/ode.main.cpp`
+# defines a pybind11 module `_chaste_project_PyChaste_ode`. By convention,
+# the name starts with an underscore. The usual 'lib' prefix is disabled.
+set(PYCHASTE_PYTHON_MODULE_PREFIX "_chaste_project_PyChaste_")
+
 # Create a shared library target for each module
-list(LENGTH PYCHASTE_PYTHON_MODULES max_module_idx)
-math(EXPR max_module_idx "${max_module_idx} - 1")
-set(module_prefix "_chaste_project_PyChaste_")
+list(LENGTH PYCHASTE_PYTHON_MODULES max_idx)
+math(EXPR max_idx "${max_idx} - 1")
 
-foreach(idx RANGE ${max_module_idx})
-    list(GET PYCHASTE_PYTHON_MODULES ${idx} module_name)
+foreach(idx RANGE ${max_idx})
+    list(GET PYCHASTE_PYTHON_MODULES ${idx} module)
     list(GET PYCHASTE_PYTHON_MODULE_LOCATIONS ${idx} module_dir)
 
     # Glob the module's wrapper code from the `dynamic` directory
-    file(GLOB module_sources ${CMAKE_CURRENT_SOURCE_DIR}/dynamic/wrappers/${module_name}/*.cpp)
+    file(GLOB module_sources ${CMAKE_CURRENT_SOURCE_DIR}/dynamic/wrappers/${module}/*.cpp)
 
-    # The module library name here must be the same as the pybind11 module name
-    # defined in the main wrapper e.g. `dynamic/wrappers/ode/ode.main.cpp`
-    # defines a pybind11 module `_chaste_project_PyChaste_ode`. By convention,
-    # the name starts with an underscore. The usual 'lib' prefix is disabled.
-    add_library(${module_prefix}${module_name} SHARED ${module_sources})
+    set(module_library_name ${PYCHASTE_PYTHON_MODULE_PREFIX}${module})
+    add_library(${module_library_name} SHARED ${module_sources})
 
-    set_target_properties(${module_prefix}${module_name}
+    set_target_properties(${module_library_name}
         PROPERTIES
             LIBRARY_OUTPUT_DIRECTORY ${module_dir}
             PREFIX "${PYTHON_MODULE_PREFIX}"
             SUFFIX "${CMAKE_SHARED_LIBRARY_SUFFIX}")
 
     # The order here is important - pybind11 and python come first
-    target_link_libraries(${module_prefix}${module_name}
+    target_link_libraries(${module_library_name} 
         pybind11::module
-        ${PYTHON3_LIBRARIES}
+        Python3::Module
         ${Chaste_THIRD_PARTY_LIBRARIES}
+        Chaste_COMMON_DEPS
+        PyChaste_COMMON_DEPS
         ${Chaste_LIBRARIES}
         ${PYCHASTE_SHARED_LIB})
 
-    add_dependencies(${module_prefix}${module_name} chaste_project_PyChaste)
+    add_dependencies(${module_library_name} chaste_project_PyChaste)
 endforeach()
 
 # Target for building all module shared libraries
 add_custom_target(project_PyChaste_Python)
-foreach(idx RANGE ${max_module_idx})
-    list(GET PYCHASTE_PYTHON_MODULES ${idx} module_name)
-    add_dependencies(project_PyChaste_Python ${module_prefix}${module_name})
+foreach(module IN LISTS PYCHASTE_PYTHON_MODULES)
+    add_dependencies(project_PyChaste_Python ${PYCHASTE_PYTHON_MODULE_PREFIX}${module})
 endforeach()

From 9f85a5d66e2d17813e9c0c5ccf1e1aa6a831ef07 Mon Sep 17 00:00:00 2001
From: Kwabena N Amponsah <kwabenantim@yahoo.com>
Date: Wed, 22 May 2024 13:52:00 +0000
Subject: [PATCH 12/12] #24 update cmake

---
 CMakeLists.txt | 17 +++++++----------
 1 file changed, 7 insertions(+), 10 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 62cffdd6..829ed34e 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -37,7 +37,7 @@
 # PyChaste needs the cell_based component (and its dependencies)
 find_package(Chaste COMPONENTS cell_based)
 
-# Do Chaste project preprocessing, which results in something like:
+# Do Chaste project preprocessing, which does something like:
 #   add_custom_target(project_PyChaste)
 #   set(Chaste_project_PyChaste_SOURCE_DIR ...)
 #   set(Chaste_project_PyChaste_INCLUDE_DIRS ...)
@@ -48,11 +48,9 @@ find_package(Chaste COMPONENTS cell_based)
 #   target_link_libraries(chaste_project_PyChaste ...)
 chaste_do_project(PyChaste)
 
-add_library(PyChaste_COMMON_DEPS INTERFACE)
-
 # PyChaste needs the Python3 development libraries
 find_package(Python3 REQUIRED COMPONENTS Interpreter Development)
-target_link_libraries(PyChaste_COMMON_DEPS INTERFACE Python3::Module)
+target_link_libraries(Chaste_COMMON_DEPS INTERFACE Python3::Module Python3::Python)
 
 # PyChaste needs some additional VTK libraries
 if(VTK_MAJOR_VERSION LESS 7)
@@ -86,10 +84,11 @@ else()
         InteractionStyle
         IOImage
         IOMovie
+        IOOggTheora
         RenderingAnnotation
         RenderingCore
-        # RenderingFreeType # needs Freetype::Freetype
-        # RenderingOpenGL2 # needs X11::X11 and GLEW::GLEW
+        RenderingFreeType # needs Freetype::Freetype
+        RenderingOpenGL2 # needs X11::X11 and GLEW::GLEW
         WrappingPythonCore # needs Python3::Module
     )
 endif()
@@ -99,8 +98,7 @@ if (VTK_MAJOR_VERSION LESS 9)
     list(APPEND Chaste_project_PyChaste_INCLUDE_DIRS "${VTK_INCLUDE_DIRS}")
     list(APPEND Chaste_THIRD_PARTY_LIBRARIES "${VTK_LIBRARIES}")
 else()
-    target_link_libraries(PyChaste_COMMON_DEPS INTERFACE VTK::WrappingPythonCore)
-    # target_link_libraries(PyChaste_COMMON_DEPS INTERFACE ${VTK_LIBRARIES})
+    target_link_libraries(Chaste_COMMON_DEPS INTERFACE ${VTK_LIBRARIES})
 endif ()
 
 #========================================
@@ -218,10 +216,9 @@ foreach(idx RANGE ${max_idx})
     # The order here is important - pybind11 and python come first
     target_link_libraries(${module_library_name} 
         pybind11::module
-        Python3::Module
+        ${Python3_LIBRARIES}
         ${Chaste_THIRD_PARTY_LIBRARIES}
         Chaste_COMMON_DEPS
-        PyChaste_COMMON_DEPS
         ${Chaste_LIBRARIES}
         ${PYCHASTE_SHARED_LIB})