From 8230ee4240ca5ee18c18a84dbde18c3bd3d29cc4 Mon Sep 17 00:00:00 2001 From: Pablo Vicente Munuera Date: Mon, 30 Sep 2024 09:34:42 +0100 Subject: [PATCH 01/15] Simplified version of main --- src/pyVertexModel/main.py | 63 ++------------------------------------- 1 file changed, 3 insertions(+), 60 deletions(-) diff --git a/src/pyVertexModel/main.py b/src/pyVertexModel/main.py index 1040a175..54b1a913 100644 --- a/src/pyVertexModel/main.py +++ b/src/pyVertexModel/main.py @@ -1,70 +1,13 @@ import logging import os - -import optuna - -from src import PROJECT_DIRECTORY from src.pyVertexModel.algorithm.vertexModelVoronoiFromTimeImage import VertexModelVoronoiFromTimeImage -from src.pyVertexModel.analysis.analyse_simulation import analyse_simulation, analyse_edge_recoil -from src.pyVertexModel.util.space_exploration import objective, load_simulations, plot_optuna_all from src.pyVertexModel.util.utils import load_state start_new = True if start_new == True: - # Create a study object and optimize the objective function - # Add stream handler of stdout to show the messages - # CHANGE IT IN SPACE EXPLORATION TOO!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - error_type = '_gr_' - if error_type is not None: - study_name = "VertexModel" + error_type # Unique identifier of the study. - else: - study_name = "VertexModel" - storage_name = "sqlite:///{}.db".format("VertexModel") - - # Samplers: - # optuna.samplers.RandomSampler=) - # optuna.samplers.TPESampler=) - #agent_sampler = optuna.samplers.CmaEsSampler() - # optuna.samplers.GridSampler=) - # optuna.samplers.NSGAIIISampler=) - #gaussian_sampler = optuna.samplers.GPSampler(deterministic_objective=True) - # optuna.samplers.QMCSampler=) - - # With one it doesn't work so well... - #num_params = 1 - #genetic_sampler = optuna.samplers.NSGAIISampler(population_size=5, mutation_prob=1.0 / num_params, - # crossover_prob = 0.9, swapping_prob = 0.5) - study = optuna.create_study(study_name=study_name, storage=storage_name, direction='minimize', - load_if_exists=True) - - #load_simulations(study, error_type=error_type) - - # fixed_params = { - # 'lambdaR': 1e-8, - # 'cLineTension': 0.00001, - # 'cLineTension_external': 0.00001, - # 'lambdaS1': 1, - # 'lambdaS2': 0.01, - # 'lambdaS3': 0.1, - # 'ref_A0': 1, - # 'ref_V0': 1, - # 'kSubstrate': 1, - # 'lambdaV': 1, - # } - # partial_sampler = optuna.samplers.PartialFixedSampler(fixed_params, study.sampler) - # - # #agent_sampler = optuna.samplers.CmaEsSampler(source_trials=study.trials) - # study = optuna.create_study(study_name=study_name, storage=storage_name, direction='minimize', - # load_if_exists=True, - # sampler=partial_sampler) - - - study.optimize(objective, n_trials=100000) - - print("Best parameters:", study.best_params) - print("Best value:", study.best_value) - print("Best trial:", study.best_trial) - plot_optuna_all(os.path.join(PROJECT_DIRECTORY, 'Result'), study_name, study) + vModel = VertexModelVoronoiFromTimeImage() + vModel.initialize() + vModel.iterate_over_time() else: vModel = VertexModelVoronoiFromTimeImage() output_folder = vModel.set.OutputFolder From 6c1742b802b395e7ff2e62f481e823be4a34ede7 Mon Sep 17 00:00:00 2001 From: Pablo Vicente Munuera Date: Mon, 30 Sep 2024 12:16:10 +0100 Subject: [PATCH 02/15] updating --- src/pyVertexModel/parameters/set.py | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/pyVertexModel/parameters/set.py b/src/pyVertexModel/parameters/set.py index b57c712d..a5b771c3 100644 --- a/src/pyVertexModel/parameters/set.py +++ b/src/pyVertexModel/parameters/set.py @@ -218,15 +218,16 @@ def update_derived_parameters(self): current_datetime = datetime.now() new_outputFolder = ''.join([PROJECT_DIRECTORY, '/Result/', str(current_datetime.strftime("%m-%d_%H%M%S_")), - '_Cells_', str(self.TotalCells), '_visc_', str(self.nu), - '_lVol_', str(self.lambdaV), '_refV0_', str(self.ref_V0), - '_kSubs_', str(self.kSubstrate), '_kCeil_', str(self.kCeiling), - '_lt_', '{:0.2e}'.format(self.cLineTension), '_ltExt_', '{:0.2e}'.format(self.cLineTension_external), - '_noise_', str(self.noise_random), '_refA0_', str(self.ref_A0), - '_eARBarrier_', '{:0.2e}'.format(self.lambdaR), - '_RemStiff_', str(self.RemodelStiffness), '_lS1_', str(self.lambdaS1), - '_lS2_', str(self.lambdaS2), '_lS3_', str(self.lambdaS3), - '_ps_', str(self.purseStringStrength), '_psType_', str(self.TypeOfPurseString)]) + ]) + #'_Cells_', str(self.TotalCells), '_visc_', str(self.nu), + #'_lVol_', str(self.lambdaV), '_refV0_', str(self.ref_V0), + #'_kSubs_', str(self.kSubstrate), '_kCeil_', str(self.kCeiling), + #'_lt_', '{:0.2e}'.format(self.cLineTension), '_ltExt_', '{:0.2e}'.format(self.cLineTension_external), + #'_noise_', str(self.noise_random), '_refA0_', str(self.ref_A0), + #'_eARBarrier_', '{:0.2e}'.format(self.lambdaR), + #'_RemStiff_', str(self.RemodelStiffness), '_lS1_', str(self.lambdaS1), + #'_lS2_', str(self.lambdaS2), '_lS3_', str(self.lambdaS3), + #'_ps_', str(self.purseStringStrength), '_psType_', str(self.TypeOfPurseString) self.define_if_not_defined("OutputFolder", new_outputFolder) def stretch(self): From 1a9d1333adef66a35f1262de44b0345621a1f7fc Mon Sep 17 00:00:00 2001 From: Pablo Vicente Munuera Date: Tue, 15 Oct 2024 12:02:06 +0100 Subject: [PATCH 03/15] Set and main updated --- src/pyVertexModel/main.py | 6 +- src/pyVertexModel/parameters/set.py | 89 +++++++++++++++++++---------- 2 files changed, 61 insertions(+), 34 deletions(-) diff --git a/src/pyVertexModel/main.py b/src/pyVertexModel/main.py index 54b1a913..a2f92010 100644 --- a/src/pyVertexModel/main.py +++ b/src/pyVertexModel/main.py @@ -3,7 +3,7 @@ from src.pyVertexModel.algorithm.vertexModelVoronoiFromTimeImage import VertexModelVoronoiFromTimeImage from src.pyVertexModel.util.utils import load_state -start_new = True +start_new = False if start_new == True: vModel = VertexModelVoronoiFromTimeImage() vModel.initialize() @@ -13,11 +13,11 @@ output_folder = vModel.set.OutputFolder load_state(vModel, '/media/pablo/d7c61090-024c-469a-930c-f5ada47fb049/PabloVicenteMunuera/VertexModel/pyVertexModel/Result/' - '08-20_084414__Cells_150_visc_16_lVol_1_refV0_1_kSubs_1_lt_0.00035_ltExt_0.00035_noise_0_refA0_0.95_eTriAreaBarrier_0_eARBarrier_0_RemStiff_0.95_lS1_10_lS2_0.4_lS3_1.0_pString_0.00245/' + '10-10_234543_Cells_150_visc_7.00e-02_lVol_9.61e-01_refV0_9.95e-01_kSubs_1.09e-01_lt_0.00e+00_refA0_9.24e-01_eARBarrier_9.51e-09_RemStiff_0.95_lS1_1.58e+00_lS2_1.39e-02_lS3_1.58e-01_ps_9.12e-07_psType_2/' 'before_ablation.pkl') vModel.set.wing_disc() vModel.set.wound_default() - vModel.set.OutputFolder = None + vModel.set.OutputFolder = output_folder vModel.set.update_derived_parameters() vModel.iterate_over_time() diff --git a/src/pyVertexModel/parameters/set.py b/src/pyVertexModel/parameters/set.py index a5b771c3..e24d5bf4 100644 --- a/src/pyVertexModel/parameters/set.py +++ b/src/pyVertexModel/parameters/set.py @@ -66,7 +66,7 @@ def __init__(self, mat_file=None): # ============================ Mechanics ============================= # Volumes self.lambdaV = 5.0 - self.lambdaV_Debris = 0 + self.lambdaV_Debris = 1e-8 # Surface area self.SurfaceType = 1 self.A0eq0 = True @@ -218,16 +218,15 @@ def update_derived_parameters(self): current_datetime = datetime.now() new_outputFolder = ''.join([PROJECT_DIRECTORY, '/Result/', str(current_datetime.strftime("%m-%d_%H%M%S_")), - ]) - #'_Cells_', str(self.TotalCells), '_visc_', str(self.nu), - #'_lVol_', str(self.lambdaV), '_refV0_', str(self.ref_V0), - #'_kSubs_', str(self.kSubstrate), '_kCeil_', str(self.kCeiling), - #'_lt_', '{:0.2e}'.format(self.cLineTension), '_ltExt_', '{:0.2e}'.format(self.cLineTension_external), - #'_noise_', str(self.noise_random), '_refA0_', str(self.ref_A0), - #'_eARBarrier_', '{:0.2e}'.format(self.lambdaR), - #'_RemStiff_', str(self.RemodelStiffness), '_lS1_', str(self.lambdaS1), - #'_lS2_', str(self.lambdaS2), '_lS3_', str(self.lambdaS3), - #'_ps_', str(self.purseStringStrength), '_psType_', str(self.TypeOfPurseString) + 'Cells_', str(self.TotalCells), '_visc_', '{:0.2e}'.format(self.nu), + '_lVol_', '{:0.2e}'.format(self.lambdaV), '_refV0_', '{:0.2e}'.format(self.ref_V0), + '_kSubs_', '{:0.2e}'.format(self.kSubstrate), + '_lt_', '{:0.2e}'.format(self.cLineTension), + '_refA0_', '{:0.2e}'.format(self.ref_A0), + '_eARBarrier_', '{:0.2e}'.format(self.lambdaR), + '_RemStiff_', str(self.RemodelStiffness), '_lS1_', '{:0.2e}'.format(self.lambdaS1), + '_lS2_', '{:0.2e}'.format(self.lambdaS2), '_lS3_', '{:0.2e}'.format(self.lambdaS3), + '_ps_', '{:0.2e}'.format(self.purseStringStrength), '_psType_', str(self.TypeOfPurseString)]) self.define_if_not_defined("OutputFolder", new_outputFolder) def stretch(self): @@ -260,58 +259,86 @@ def wing_disc(self): # 40 cells 3 cells to ablate # 110 cells 7 cells to ablate self.TotalCells = 150 + # per 1 micrometer of diameter on the top side of the cell self.CellHeight = 15 - self.tend = 16 - self.Nincr = self.tend * 100 + # Tend is the final time of the simulation + self.tend = 50 + # Nincr is the number of increments + self.Nincr = self.tend * 30 + # Viscosity self.nu = 0.07 + # Energy Barrier Area self.EnergyBarrierA = False self.lambdaB = 20 + # Energy Barrier Aspect Ratio self.EnergyBarrierAR = True - self.lambdaR = 1e-8 + self.lambdaR = 9.5e-9 - self.lambdaV = 50 - self.ref_V0 = 0.99 - self.kSubstrate = 0 - self.kCeiling = 0 - self.cLineTension = 1e-8 - self.Contractility_external = True - self.Contractility_external_axis = [0, 1] - self.cLineTension_external = self.cLineTension + # Volume + self.lambdaV = 1 + self.ref_V0 = 1 + # Substrate + self.kSubstrate = 0.1 + #self.kCeiling = 0 + + # Contractility + self.cLineTension = 0 + + # Brownian motion self.brownian_motion = False self.brownian_motion_scale = 0 - self.noise_random = 0 + + # Purse String self.TypeOfPurseString = 2 - self.Remodelling = 0 - self.RemodelStiffness = 0.95 - self.ref_A0 = 1 - self.lambdaS1 = 0.5 + + # Remodelling + self.Remodelling = True + # How big or small the edge to remodel + # 0.15 is 15% of average the edge. This is a threshold to remodel the edge + if self.Remodelling: + self.RemodelStiffness = 0.9 + else: + self.RemodelStiffness = 2 + + # Surface Area + self.ref_A0 = 0.92 + # Top + self.lambdaS1 = 1.5 + # c_cell-c_cell self.lambdaS2 = self.lambdaS1 / 100 + # Bottom self.lambdaS3 = self.lambdaS1 / 10 + # Substrate - c_cell self.lambdaS4 = self.lambdaS2 + # VTK self.VTK = False + + # Implicit vs Explicit self.implicit_method = False + + # Ablation yes or no self.ablation = True self.check_for_non_used_parameters() def wound_default(self): # ============================== Ablation ============================ self.cellsToAblate = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) - self.TInitAblation = 10 + self.TInitAblation = 20 self.TEndAblation = self.TInitAblation + 60 self.debris_contribution = np.finfo(float).eps # =========================== Contractility ========================== self.Contractility = True - self.TypeOfPurseString = 0 + self.TypeOfPurseString = 2 # 0: Intensity-based purse string # 1: Strain-based purse string (delayed) # 2: Fixed with linear increase purse string - self.purseStringStrength = 0 - self.lateralCablesStrength = 0 + self.purseStringStrength = 3.5e-5 + self.lateralCablesStrength = self.purseStringStrength / 5 self.delay_purse_string = 5.8 self.delay_lateral_cables = 0.2 From 5580d66f81f5bc217d3eed4db3145c2af1624cca Mon Sep 17 00:00:00 2001 From: Pablo Vicente Munuera Date: Tue, 15 Oct 2024 12:23:39 +0100 Subject: [PATCH 04/15] vtk files true --- src/pyVertexModel/parameters/set.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pyVertexModel/parameters/set.py b/src/pyVertexModel/parameters/set.py index e24d5bf4..8b48d3f3 100644 --- a/src/pyVertexModel/parameters/set.py +++ b/src/pyVertexModel/parameters/set.py @@ -316,7 +316,7 @@ def wing_disc(self): self.lambdaS4 = self.lambdaS2 # VTK - self.VTK = False + self.VTK = True # Implicit vs Explicit self.implicit_method = False From d3cdcf98b4e3c90654174dc443e344789f9c86be Mon Sep 17 00:00:00 2001 From: Megha Date: Fri, 13 Dec 2024 19:03:02 +0530 Subject: [PATCH 05/15] Tests by megha specifically on assertmatrix, datageo, data_invalidfile, and load data set --- .idea/pyVertexModel.iml | 2 +- Tests/test_cell.py | 14 +++++++++ Tests/tests.py | 31 +++++++++++++------ src/pyVertexModel/geometry/geo.py | 8 +++++ src/pyVertexModel/main.py | 13 +++++--- .../mesh_remodelling/remodelling.py | 2 +- src/pyVertexModel/parameters/set.py | 11 +------ 7 files changed, 55 insertions(+), 26 deletions(-) diff --git a/.idea/pyVertexModel.iml b/.idea/pyVertexModel.iml index 8fd60d93..6625830e 100644 --- a/.idea/pyVertexModel.iml +++ b/.idea/pyVertexModel.iml @@ -4,7 +4,7 @@ - + diff --git a/Tests/test_cell.py b/Tests/test_cell.py index a0bbaf14..4796c1f4 100644 --- a/Tests/test_cell.py +++ b/Tests/test_cell.py @@ -78,3 +78,17 @@ def test_copy(self): self.assertEqual(original_cell.ID, copied_cell.ID) self.assertTrue(np.array_equal(original_cell.X, copied_cell.X)) self.assertTrue(np.array_equal(original_cell.T, copied_cell.T)) + + +def test_compute_cell_area_edge_cases(self): + geo_test, _, _ = load_data('Geo_var_3x3_stretch.mat') + + # Test with zero-area cells + geo_test.Cells[0].X = np.array([[0, 0], [0, 0], [0, 0]]) # Degenerate cell + geo_test.Cells[0].compute_area() + self.assertEqual(geo_test.Cells[0].Area, 0) + + # Test with very large area + geo_test.Cells[1].X = np.array([[1e6, 1e6], [1e7, 1e7], [1e8, 1e8]]) # Extreme values + geo_test.Cells[1].compute_area() + self.assertTrue(geo_test.Cells[1].Area > 0) # Ensure a non-zero area diff --git a/Tests/tests.py b/Tests/tests.py index fb1be981..621b3adf 100644 --- a/Tests/tests.py +++ b/Tests/tests.py @@ -1,15 +1,14 @@ import unittest -from os.path import exists - +import scipy.io import numpy as np -import scipy +from os.path import exists, abspath from src.pyVertexModel.geometry.geo import Geo from src.pyVertexModel.parameters.set import Set def load_data(file_name, return_geo=True): - test_dir = 'Tests/data/%s' % file_name + test_dir = abspath('Tests/data/%s' % file_name) if exists(test_dir): mat_info = scipy.io.loadmat(test_dir) else: @@ -23,10 +22,8 @@ def load_data(file_name, return_geo=True): if 'Set' in mat_info.keys(): set_test = Set(mat_info['Set']) - # Set the output folder to the test directory if it is not set if set_test.OutputFolder.__eq__(b'') or set_test.OutputFolder is None: set_test.OutputFolder = '../Result/Test' - else: set_test = None else: @@ -40,9 +37,23 @@ def assert_matrix(k_expected, k): np.testing.assert_allclose(k_expected, k, rtol=1e-3, atol=1e-1) -def assert_array1D(g_expected, g): - np.testing.assert_allclose(g_expected, g, rtol=1e-3, atol=1e-1) +class Tests(unittest.TestCase): + + def test_load_data_geo(self): + geo_test, set_test, mat_info = load_data('Geo_3x3_dofs_expected.mat') + self.assertIsNotNone(geo_test) + self.assertTrue('Geo' in mat_info) + def test_load_data_set(self): + geo_test, set_test, mat_info = load_data('Geo_var_3x3_stretch.mat') + self.assertIsNotNone(set_test) + self.assertTrue('Set' in mat_info) -class Tests(unittest.TestCase): - pass + def test_assert_matrix(self): + k_expected = np.array([[1, 2], [3, 4]]) + k = np.array([[1, 2], [3, 4]]) + assert_matrix(k_expected, k) + + def test_load_data_invalid_file(self): + with self.assertRaises(FileNotFoundError): + load_data('invalid_file.mat') diff --git a/src/pyVertexModel/geometry/geo.py b/src/pyVertexModel/geometry/geo.py index b13efce1..1b0954de 100644 --- a/src/pyVertexModel/geometry/geo.py +++ b/src/pyVertexModel/geometry/geo.py @@ -753,6 +753,12 @@ def get_num_faces(self, num_cell): for c_face in self.Cells[num_cell].Faces]) return num_faces_bottom, num_faces_lateral, num_faces_top + if c_cell.AliveStatus == 0: + # Apply a small shift for debris cells + c_cell.Y += 0.1 * (self.XgTop - self.XgBottom) # Adjust the factor as needed + + self.Cells[cc].Faces = self.Cells[cc].Faces[:len(neigh_nodes)] + def calculate_interface_type(self, new_tets): """ Calculate the interface type @@ -796,6 +802,8 @@ def check_ys_and_faces_have_not_changed(self, new_tets, old_tets, old_geo): assert np.all(self.Cells[cell_id].Faces[id_with_new_index].Centre == c_face.Centre) + + def add_and_rebuild_cells(self, old_geo, old_tets, new_tets, y_new, c_set, update_measurements): """ Add and rebuild the cells diff --git a/src/pyVertexModel/main.py b/src/pyVertexModel/main.py index 0bc5a1f0..ab55da1e 100644 --- a/src/pyVertexModel/main.py +++ b/src/pyVertexModel/main.py @@ -1,8 +1,14 @@ +from src import PROJECT_DIRECTORY + +print(PROJECT_DIRECTORY) import logging import os + + from src.pyVertexModel.algorithm.vertexModelVoronoiFromTimeImage import VertexModelVoronoiFromTimeImage from src.pyVertexModel.util.utils import load_state + start_new = False if start_new == True: vModel = VertexModelVoronoiFromTimeImage() @@ -12,13 +18,12 @@ debugging = False vModel = VertexModelVoronoiFromTimeImage() output_folder = vModel.set.OutputFolder - load_state(vModel, - '/media/pablo/d7c61090-024c-469a-930c-f5ada47fb049/PabloVicenteMunuera/VertexModel/pyVertexModel/Result/' - '10-10_234543_Cells_150_visc_7.00e-02_lVol_9.61e-01_refV0_9.95e-01_kSubs_1.09e-01_lt_0.00e+00_refA0_9.24e-01_eARBarrier_9.51e-09_RemStiff_0.95_lS1_1.58e+00_lS2_1.39e-02_lS3_1.58e-01_ps_9.12e-07_psType_2/' - 'before_ablation.pkl') + load_state(vModel, r"C:\Users\Rohit\PycharmProjects\pyVertexModel\Result\10-10_234543\before_ablation.pkl") vModel.set.wing_disc() vModel.set.wound_default() vModel.set.OutputFolder = output_folder vModel.set.update_derived_parameters() vModel.iterate_over_time() + + diff --git a/src/pyVertexModel/mesh_remodelling/remodelling.py b/src/pyVertexModel/mesh_remodelling/remodelling.py index e507cbb3..ebbf0d1f 100644 --- a/src/pyVertexModel/mesh_remodelling/remodelling.py +++ b/src/pyVertexModel/mesh_remodelling/remodelling.py @@ -530,7 +530,7 @@ def check_edges_to_intercalate(self, edge_lengths, num_cell, segment_features, g return segment_features def flip_nm(self, segment_to_change, cell_to_intercalate_with, old_tets, old_ys, cell_to_split_from): - hasConverged = False + hasConverged = True old_geo = self.Geo.copy() t_new, y_new, self.Geo = y_flip_nm(old_tets, cell_to_intercalate_with, old_ys, segment_to_change, self.Geo, self.Set, cell_to_split_from) diff --git a/src/pyVertexModel/parameters/set.py b/src/pyVertexModel/parameters/set.py index 75e6be15..a5211226 100644 --- a/src/pyVertexModel/parameters/set.py +++ b/src/pyVertexModel/parameters/set.py @@ -219,16 +219,7 @@ def update_derived_parameters(self): self.define_if_not_defined("nu_bottom", self.nu * 600) current_datetime = datetime.now() - new_outputFolder = ''.join([PROJECT_DIRECTORY, '/Result/', str(current_datetime.strftime("%m-%d_%H%M%S_")), - 'Cells_', str(self.TotalCells), '_visc_', '{:0.2e}'.format(self.nu), - '_lVol_', '{:0.2e}'.format(self.lambdaV), '_refV0_', '{:0.2e}'.format(self.ref_V0), - '_kSubs_', '{:0.2e}'.format(self.kSubstrate), - '_lt_', '{:0.2e}'.format(self.cLineTension), - '_refA0_', '{:0.2e}'.format(self.ref_A0), - '_eARBarrier_', '{:0.2e}'.format(self.lambdaR), - '_RemStiff_', str(self.RemodelStiffness), '_lS1_', '{:0.2e}'.format(self.lambdaS1), - '_lS2_', '{:0.2e}'.format(self.lambdaS2), '_lS3_', '{:0.2e}'.format(self.lambdaS3), - '_ps_', '{:0.2e}'.format(self.purseStringStrength), '_psType_', str(self.TypeOfPurseString)]) + new_outputFolder = ''.join([PROJECT_DIRECTORY, '/Result/', str(current_datetime.strftime("%m-%d_%H%M%S_"))]) self.define_if_not_defined("OutputFolder", new_outputFolder) def stretch(self): From 15bd59c32a6f7564dc503d4a2ada06c46c0d71aa Mon Sep 17 00:00:00 2001 From: Pablo Vicente Munuera Date: Fri, 13 Dec 2024 13:35:17 +0000 Subject: [PATCH 06/15] Update with Megha's branch --- .github/workflows/tests.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index 3dcf6345..6c68e1e9 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -2,7 +2,7 @@ name: Run Python Tests on: push: - branches: [ main ] + branches: [ main megha] pull_request: branches: [ main ] From 9cd25dac3ef3bb451d1557ecb2b4b31f19d77727 Mon Sep 17 00:00:00 2001 From: Pablo Vicente Munuera Date: Fri, 13 Dec 2024 13:37:15 +0000 Subject: [PATCH 07/15] minor --- src/pyVertexModel/geometry/geo.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/pyVertexModel/geometry/geo.py b/src/pyVertexModel/geometry/geo.py index 1b0954de..bff2831c 100644 --- a/src/pyVertexModel/geometry/geo.py +++ b/src/pyVertexModel/geometry/geo.py @@ -376,7 +376,8 @@ def init_reference_cell_values(self, c_set): # Iterate over all cells in the Geo structure for c, c_cell in enumerate(self.Cells): if c_cell.AliveStatus is not None: - self.Cells[c].Vol0 = self.Cells[c].Vol / c_set.ref_V0 + # Compute the reference mechanical values + self.Cells[c].Vol0 = avg_vol / c_set.ref_V0 self.Cells[c].Area0 = avg_area # Compute the mechanical parameter with noise From 1b9a759061e12d1d89abce7adfbc66e624d7553c Mon Sep 17 00:00:00 2001 From: Megha Date: Sun, 15 Dec 2024 20:46:19 +0530 Subject: [PATCH 08/15] fixed the assert matrix import issue, specifically the assert1D function and Kg function imports --- Tests/test_cell.py | 21 ++++++++++----------- Tests/test_geo.py | 1 + Tests/tests.py | 8 +++++++- 3 files changed, 18 insertions(+), 12 deletions(-) diff --git a/Tests/test_cell.py b/Tests/test_cell.py index 4796c1f4..0df14c3b 100644 --- a/Tests/test_cell.py +++ b/Tests/test_cell.py @@ -4,7 +4,6 @@ from Tests.tests import Tests, load_data from src.pyVertexModel.geometry.cell import Cell - class TestCell(Tests): def test_compute_cell_area(self): geo_test, _, _ = load_data('Geo_var_3x3_stretch.mat') @@ -79,16 +78,16 @@ def test_copy(self): self.assertTrue(np.array_equal(original_cell.X, copied_cell.X)) self.assertTrue(np.array_equal(original_cell.T, copied_cell.T)) + def test_compute_cell_area_edge_cases(self): + geo_test, _, _ = load_data('Geo_var_3x3_stretch.mat') -def test_compute_cell_area_edge_cases(self): - geo_test, _, _ = load_data('Geo_var_3x3_stretch.mat') + # Test with zero-area cells + geo_test.Cells[0].X = np.array([[0, 0], [0, 0], [0, 0]]) # Degenerate cell + geo_test.Cells[0].compute_area() + self.assertEqual(geo_test.Cells[0].Area, 0) - # Test with zero-area cells - geo_test.Cells[0].X = np.array([[0, 0], [0, 0], [0, 0]]) # Degenerate cell - geo_test.Cells[0].compute_area() - self.assertEqual(geo_test.Cells[0].Area, 0) + # Test with very large area + geo_test.Cells[1].X = np.array([[1e6, 1e6], [1e7, 1e7], [1e8, 1e8]]) # Extreme values + geo_test.Cells[1].compute_area() + self.assertTrue(geo_test.Cells[1].Area > 0) # a non-zero area - # Test with very large area - geo_test.Cells[1].X = np.array([[1e6, 1e6], [1e7, 1e7], [1e8, 1e8]]) # Extreme values - geo_test.Cells[1].compute_area() - self.assertTrue(geo_test.Cells[1].Area > 0) # Ensure a non-zero area diff --git a/Tests/test_geo.py b/Tests/test_geo.py index 4fa869a7..5617166c 100644 --- a/Tests/test_geo.py +++ b/Tests/test_geo.py @@ -5,6 +5,7 @@ from src.pyVertexModel.algorithm.vertexModelVoronoiFromTimeImage import VertexModelVoronoiFromTimeImage from src.pyVertexModel.geometry.geo import Geo, get_node_neighbours_per_domain from src.pyVertexModel.util.utils import load_state, ismember_rows +from Tests.tests import Tests, load_data, assert_matrix def check_if_cells_are_the_same(geo_expected, geo_test): diff --git a/Tests/tests.py b/Tests/tests.py index 621b3adf..94ed202f 100644 --- a/Tests/tests.py +++ b/Tests/tests.py @@ -5,7 +5,7 @@ from src.pyVertexModel.geometry.geo import Geo from src.pyVertexModel.parameters.set import Set - +from src.pyVertexModel.Kg import kg_functions def load_data(file_name, return_geo=True): test_dir = abspath('Tests/data/%s' % file_name) @@ -37,6 +37,12 @@ def assert_matrix(k_expected, k): np.testing.assert_allclose(k_expected, k, rtol=1e-3, atol=1e-1) +def assert_array1D(array1, array2): + assert len(array1) == len(array2), "Arrays must be of the same length" + for a, b in zip(array1, array2): + assert a == b, f"Array values do not match: {a} != {b}" + + class Tests(unittest.TestCase): def test_load_data_geo(self): From d8159bb53ba85918c5e3d4fce886c20c61203657 Mon Sep 17 00:00:00 2001 From: Pablo Vicente Munuera Date: Mon, 16 Dec 2024 09:26:04 +0000 Subject: [PATCH 09/15] optimising imports --- src/pyVertexModel/analysis/analyse_in_vivo_ablation_data.py | 1 - src/pyVertexModel/analysis/analyse_results_excel.py | 4 +--- src/pyVertexModel/analysis/analyse_simulation.py | 2 +- src/pyVertexModel/analysis/analyse_simulations.py | 3 +-- src/pyVertexModel/geometry/geo.py | 2 -- src/pyVertexModel/mesh_remodelling/remodelling.py | 3 +-- src/pyVertexModel/util/space_exploration.py | 1 + src/pyVertexModel/util/utils.py | 2 +- 8 files changed, 6 insertions(+), 12 deletions(-) diff --git a/src/pyVertexModel/analysis/analyse_in_vivo_ablation_data.py b/src/pyVertexModel/analysis/analyse_in_vivo_ablation_data.py index d1f5a367..18c80609 100644 --- a/src/pyVertexModel/analysis/analyse_in_vivo_ablation_data.py +++ b/src/pyVertexModel/analysis/analyse_in_vivo_ablation_data.py @@ -1,4 +1,3 @@ -from datetime import datetime import os import numpy as np diff --git a/src/pyVertexModel/analysis/analyse_results_excel.py b/src/pyVertexModel/analysis/analyse_results_excel.py index 4e01d8d3..cd4dea06 100644 --- a/src/pyVertexModel/analysis/analyse_results_excel.py +++ b/src/pyVertexModel/analysis/analyse_results_excel.py @@ -1,8 +1,6 @@ -import numpy as np +import matplotlib.pyplot as plt import pandas as pd import seaborn as sns -import matplotlib.pyplot as plt -from scipy.interpolate import griddata # Read excel into a pandas dataframe results_excel = pd.read_excel('data/simulations_results/all_files_features.xlsx') diff --git a/src/pyVertexModel/analysis/analyse_simulation.py b/src/pyVertexModel/analysis/analyse_simulation.py index 1c38ea1f..64f44370 100644 --- a/src/pyVertexModel/analysis/analyse_simulation.py +++ b/src/pyVertexModel/analysis/analyse_simulation.py @@ -1,7 +1,7 @@ import os import pickle -import cv2 +import cv2 import numpy as np import pandas as pd from matplotlib import pyplot as plt diff --git a/src/pyVertexModel/analysis/analyse_simulations.py b/src/pyVertexModel/analysis/analyse_simulations.py index 85e810fc..1fb60e01 100644 --- a/src/pyVertexModel/analysis/analyse_simulations.py +++ b/src/pyVertexModel/analysis/analyse_simulations.py @@ -3,8 +3,7 @@ import numpy as np import pandas as pd -from src.pyVertexModel.analysis.analyse_simulation import analyse_simulation, analyse_edge_recoil, create_video -from src.pyVertexModel.util.utils import save_variables, load_variables +from src.pyVertexModel.analysis.analyse_simulation import analyse_simulation, create_video folder = '/media/pablo/d7c61090-024c-469a-930c-f5ada47fb049/PabloVicenteMunuera/VertexModel/pyVertexModel/Result/final_results' all_files_features = [] diff --git a/src/pyVertexModel/geometry/geo.py b/src/pyVertexModel/geometry/geo.py index 1cececf9..9d292d34 100644 --- a/src/pyVertexModel/geometry/geo.py +++ b/src/pyVertexModel/geometry/geo.py @@ -3,9 +3,7 @@ import numpy as np import vtk -from numpy.ma.extras import setxor1d from scipy.spatial import ConvexHull -from torch.fx.experimental.unification.unification_tools import get_in from src.pyVertexModel.Kg.kg import add_noise_to_parameter from src.pyVertexModel.geometry import face, cell diff --git a/src/pyVertexModel/mesh_remodelling/remodelling.py b/src/pyVertexModel/mesh_remodelling/remodelling.py index ebbf0d1f..ca74a8f4 100644 --- a/src/pyVertexModel/mesh_remodelling/remodelling.py +++ b/src/pyVertexModel/mesh_remodelling/remodelling.py @@ -5,8 +5,7 @@ import pandas as pd from numpy.ma.extras import setdiff1d -from src.pyVertexModel.algorithm.newtonRaphson import gGlobal, newton_raphson_iteration_explicit -from src.pyVertexModel.geometry.cell import face_centres_to_middle_of_neighbours_vertices +from src.pyVertexModel.algorithm.newtonRaphson import gGlobal from src.pyVertexModel.geometry.face import get_interface from src.pyVertexModel.geometry.geo import edge_valence, get_node_neighbours_per_domain, get_node_neighbours from src.pyVertexModel.mesh_remodelling.flip import y_flip_nm, post_flip diff --git a/src/pyVertexModel/util/space_exploration.py b/src/pyVertexModel/util/space_exploration.py index 2ee730b7..c1e8eb51 100644 --- a/src/pyVertexModel/util/space_exploration.py +++ b/src/pyVertexModel/util/space_exploration.py @@ -12,6 +12,7 @@ from src.pyVertexModel.parameters.set import Set from src.pyVertexModel.util.utils import load_state, load_variables, save_variables + def objective(trial): """ Objective function to minimize diff --git a/src/pyVertexModel/util/utils.py b/src/pyVertexModel/util/utils.py index b428c6bd..e1ed7f00 100644 --- a/src/pyVertexModel/util/utils.py +++ b/src/pyVertexModel/util/utils.py @@ -6,8 +6,8 @@ import pickle import imageio -import pyvista as pv import numpy as np +import pyvista as pv from scipy.optimize import fsolve From 69c45ac55fba08f91607d2c6f2fd411cb6036fbb Mon Sep 17 00:00:00 2001 From: Pablo Vicente Munuera Date: Mon, 16 Dec 2024 09:36:29 +0000 Subject: [PATCH 10/15] missing dependencies --- pyproject.toml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index d8d0e2a9..30a08975 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -22,7 +22,10 @@ dependencies = [ "cython", "vtk", "pandas", - "networkx" + "networkx", + "pyvista", + "scikit-learn", + "matplotlib", ] [tool.coverage] From 5fba7ee51e89f782edce30efcde2d2877b0ab899 Mon Sep 17 00:00:00 2001 From: Pablo Vicente Munuera Date: Mon, 16 Dec 2024 09:46:48 +0000 Subject: [PATCH 11/15] Fixing error of requirements and numpy --- pyproject.toml | 2 +- src/pyVertexModel/Kg/kg_functions.pyx | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 30a08975..7d1f77f8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -15,7 +15,7 @@ dynamic = [ ] dependencies = [ "cython", - "numpy", + "numpy==1.26.4", "scipy", "pillow", "scikit-image", diff --git a/src/pyVertexModel/Kg/kg_functions.pyx b/src/pyVertexModel/Kg/kg_functions.pyx index 3ead78aa..f9ce87a4 100644 --- a/src/pyVertexModel/Kg/kg_functions.pyx +++ b/src/pyVertexModel/Kg/kg_functions.pyx @@ -4,6 +4,8 @@ import cython import numpy as np cimport numpy as np +np.import_array() + # RUN IT LIKE: python setup.py build_ext --inplace @cython.wraparound(False) From b12c241fe6bfd97dd92f156cd5fad345f5f9494e Mon Sep 17 00:00:00 2001 From: Pablo Vicente Munuera Date: Mon, 16 Dec 2024 09:47:02 +0000 Subject: [PATCH 12/15] fixing error of create_tetrahedra --- Tests/test_vertexModel.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Tests/test_vertexModel.py b/Tests/test_vertexModel.py index 3229b0c7..9cafd46c 100644 --- a/Tests/test_vertexModel.py +++ b/Tests/test_vertexModel.py @@ -8,10 +8,11 @@ from Tests.tests import Tests, assert_matrix, load_data, assert_array1D from src.pyVertexModel.algorithm import newtonRaphson from src.pyVertexModel.algorithm.newtonRaphson import newton_raphson +from src.pyVertexModel.algorithm.vertexModel import create_tetrahedra from src.pyVertexModel.algorithm.vertexModelBubbles import build_topo, SeedWithBoundingBox, generate_first_ghost_nodes, \ delaunay_compute_entities, VertexModelBubbles from src.pyVertexModel.algorithm.vertexModelVoronoiFromTimeImage import build_triplets_of_neighs, calculate_neighbours, \ - VertexModelVoronoiFromTimeImage, create_tetrahedra, add_tetrahedral_intercalations, build_2d_voronoi_from_image, \ + VertexModelVoronoiFromTimeImage, add_tetrahedral_intercalations, build_2d_voronoi_from_image, \ populate_vertices_info, calculate_vertices, get_four_fold_vertices, divide_quartets_neighbours, process_image from src.pyVertexModel.geometry.degreesOfFreedom import DegreesOfFreedom from src.pyVertexModel.util.utils import save_backup_vars @@ -296,7 +297,7 @@ def test_create_tetrahedra(self): # Test if initialize geometry function does not change anything Twg_test = create_tetrahedra(traingles_connectivity, neighbours_network, edges_of_vertices, x_internal, - x_face_ids, x_vertices_ids, x) + x_face_ids, x_vertices_ids) # Check if the test and expected are the same assert_matrix(Twg_test, mat_info['Twg']) From 767fd3f5861a56a8e82fda1bef285142ef679d88 Mon Sep 17 00:00:00 2001 From: Pablo Vicente Munuera Date: Mon, 16 Dec 2024 09:48:12 +0000 Subject: [PATCH 13/15] updating gitignore --- .gitignore | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index f9064758..ea40df8d 100644 --- a/.gitignore +++ b/.gitignore @@ -8,7 +8,7 @@ __pycache__/ # Distribution / packaging .Python -build/ +src/pyVertexModel/Kg/build/ develop-eggs/ dist/ downloads/ @@ -186,3 +186,5 @@ data/ .idea/misc.xml *.db + +*.o From 4f65e0f387e02dc15709b1b11247186b3d96b01f Mon Sep 17 00:00:00 2001 From: Pablo Vicente Munuera Date: Mon, 16 Dec 2024 10:17:47 +0000 Subject: [PATCH 14/15] update tests --- .github/workflows/tests.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index e29fb69e..3f8b5059 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -1,6 +1,7 @@ name: Run Python Tests on: + workflow_dispatch: push: branches: [ main megha] pull_request: From 669fafba6cc50b4d110ad380ab7e6adf2a7dac15 Mon Sep 17 00:00:00 2001 From: Pablo Vicente Munuera Date: Mon, 16 Dec 2024 11:56:07 +0000 Subject: [PATCH 15/15] Changes after meeting --- Tests/tests.py | 4 +--- src/pyVertexModel/geometry/geo.py | 6 ------ src/pyVertexModel/mesh_remodelling/remodelling.py | 2 +- src/pyVertexModel/parameters/set.py | 11 ++++++++++- 4 files changed, 12 insertions(+), 11 deletions(-) diff --git a/Tests/tests.py b/Tests/tests.py index 94ed202f..7cfe13e7 100644 --- a/Tests/tests.py +++ b/Tests/tests.py @@ -38,9 +38,7 @@ def assert_matrix(k_expected, k): def assert_array1D(array1, array2): - assert len(array1) == len(array2), "Arrays must be of the same length" - for a, b in zip(array1, array2): - assert a == b, f"Array values do not match: {a} != {b}" + np.testing.assert_allclose(g_expected, g, rtol=1e-3, atol=1e-1) class Tests(unittest.TestCase): diff --git a/src/pyVertexModel/geometry/geo.py b/src/pyVertexModel/geometry/geo.py index 9d292d34..a231ec42 100644 --- a/src/pyVertexModel/geometry/geo.py +++ b/src/pyVertexModel/geometry/geo.py @@ -752,12 +752,6 @@ def get_num_faces(self, num_cell): for c_face in self.Cells[num_cell].Faces]) return num_faces_bottom, num_faces_lateral, num_faces_top - if c_cell.AliveStatus == 0: - # Apply a small shift for debris cells - c_cell.Y += 0.1 * (self.XgTop - self.XgBottom) # Adjust the factor as needed - - self.Cells[cc].Faces = self.Cells[cc].Faces[:len(neigh_nodes)] - def calculate_interface_type(self, new_tets): """ Calculate the interface type diff --git a/src/pyVertexModel/mesh_remodelling/remodelling.py b/src/pyVertexModel/mesh_remodelling/remodelling.py index 2dfce102..3dd5aa0f 100644 --- a/src/pyVertexModel/mesh_remodelling/remodelling.py +++ b/src/pyVertexModel/mesh_remodelling/remodelling.py @@ -541,7 +541,7 @@ def check_edges_to_intercalate(self, edge_lengths, num_cell, segment_features, g return segment_features def flip_nm(self, segment_to_change, cell_to_intercalate_with, old_tets, old_ys, cell_to_split_from): - hasConverged = True + hasConverged = False old_geo = self.Geo.copy() t_new, y_new, self.Geo = y_flip_nm(old_tets, cell_to_intercalate_with, old_ys, segment_to_change, self.Geo, self.Set, cell_to_split_from) diff --git a/src/pyVertexModel/parameters/set.py b/src/pyVertexModel/parameters/set.py index f731a978..f8a21296 100644 --- a/src/pyVertexModel/parameters/set.py +++ b/src/pyVertexModel/parameters/set.py @@ -219,7 +219,16 @@ def update_derived_parameters(self): self.define_if_not_defined("nu_bottom", self.nu * 600) current_datetime = datetime.now() - new_outputFolder = ''.join([PROJECT_DIRECTORY, '/Result/', str(current_datetime.strftime("%m-%d_%H%M%S_"))]) + new_outputFolder = ''.join([PROJECT_DIRECTORY, '/Result/', str(current_datetime.strftime("%m-%d_%H%M%S_")), + 'noise_', '{:0.2e}'.format(self.noise_random), '_bNoise_', '{:0.2e}'.format(self.brownian_motion_scale), + '_lVol_', '{:0.2e}'.format(self.lambdaV), '_refV0_', '{:0.2e}'.format(self.ref_V0), + '_kSubs_', '{:0.2e}'.format(self.kSubstrate), + '_lt_', '{:0.2e}'.format(self.cLineTension), + '_refA0_', '{:0.2e}'.format(self.ref_A0), + '_eARBarrier_', '{:0.2e}'.format(self.lambdaR), + '_RemStiff_', str(self.RemodelStiffness), '_lS1_', '{:0.2e}'.format(self.lambdaS1), + '_lS2_', '{:0.2e}'.format(self.lambdaS2), '_lS3_', '{:0.2e}'.format(self.lambdaS3), + '_ps_', '{:0.2e}'.format(self.purseStringStrength), '_lc_', '{:0.2e}'.format(self.lateralCablesStrength)]) self.define_if_not_defined("OutputFolder", new_outputFolder) def stretch(self):