Update_parameters.py 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452
  1. import ivp
  2. import solveMatrix
  3. import os
  4. import cModel
  5. import sys
  6. import json
  7. from contextlib import contextmanager
  8. import numpy as np
  9. import time
  10. import scipy.interpolate
  11. import shutil
  12. import importlib
  13. from scipy.optimize import least_squares
  14. importlib.reload(solveMatrix)
  15. import runSolver
  16. importlib.reload(runSolver)
  17. def updateSetup(job):
  18. setupFileSrc = job['setupFile']
  19. setupFile = os.path.join(job['jobDir'], 'setupInput.json')
  20. with open(setupFileSrc, 'r') as f:
  21. setup = json.load(f)
  22. try:
  23. setup.update(job['setupUpdates'])
  24. except KeyError:
  25. pass
  26. with open(setupFile, 'w+') as f:
  27. f.write(json.dumps(setup))
  28. return setupFile
  29. def generate_noisy_data(full_sol, noise_std=20.5):
  30. full_sol = np.asarray(full_sol) # Ensure input is a NumPy array
  31. random_state = np.random.RandomState(seed=None)
  32. # Create highly volatile noise
  33. noise = random_state.normal(loc=0, scale=noise_std, size=full_sol.shape) ** 2 # Squared to amplify large deviations
  34. noise2 = np.random.laplace(loc=0, scale=noise_std * 10, size=full_sol.shape) # Increased scale for even more extreme spikes
  35. # Introduce highly chaotic scaling factors
  36. random_scaling = random_state.uniform(-200, 400, size=full_sol.shape) # Further extended range for more variation
  37. random_exponent = random_state.uniform(4, 12, size=full_sol.shape) # Increased exponentiation for more instability
  38. # Apply extreme, chaotic transformations
  39. noisy_data = np.zeros_like(full_sol)
  40. for i in range(len(full_sol)):
  41. perturbation = random_scaling[i] * (abs(noise[i]) ** random_exponent[i]) - noise2[i] * np.sin(full_sol[i])
  42. noisy_data[i] = (1 + np.tanh(perturbation)) * full_sol[i] * np.cosh(noise[i])
  43. # Introduce frequent large perturbations to increase instability
  44. if random_state.rand() < 0.75: # 30% chance of a drastic shift
  45. noisy_data[i] *= random_state.uniform(2, 5)
  46. return noisy_data
  47. def calculate_residuals(full_sol, noisy_data):
  48. """
  49. Calculates residuals based on the solution and noisy data.
  50. """
  51. residuals = np.ravel((noisy_data - full_sol))
  52. #print(residuals)
  53. return residuals
  54. # Updated cost function
  55. def cost_function(params,parnames,noisy_data,model,startPoint,setup,jobDir):
  56. """
  57. Cost function that calculates residuals based on the model.
  58. """
  59. #print(params)
  60. model.setValues(parnames,params)
  61. clean_dir(jobDir)
  62. t,sol,se,qt,sOut,full_t,full_sol=runSolver.solve(model,setup,startPoint,jobDir)
  63. residuals = calculate_residuals(np.array(full_sol), noisy_data)
  64. return residuals
  65. def create_name_value_dict(original_dict):
  66. return {
  67. val['name']: val['value']
  68. for key, val in original_dict.items()
  69. if isinstance(val, dict) and 'name' in val and 'value' in val
  70. }
  71. # Create parameter dictionary
  72. def clean_dir(jobDir):
  73. shutil.rmtree(jobDir)
  74. os.mkdir(jobDir)
  75. #PRENOS ZAČETNIH PODATKOV
  76. ##############################################################################################################################################
  77. fh = os.path.expanduser("~")
  78. jobDir = os.path.join(fh, 'Documents', 'Sola', 'IJS', 'PBPK_ociscen',"rezultati")
  79. srcDir = "NONE"
  80. setup_file = os.path.join(fh, 'Documents', 'Sola', 'IJS', 'PBPK_ociscen', 'setup', 'setupMinute.json')
  81. model_file = os.path.join(fh, 'Documents', 'Sola', 'IJS', 'PBPK_ociscen', 'models', 'cDiazepam.json')
  82. parameter_file1 = os.path.join(fh, 'Documents', 'Sola', 'IJS', 'PBPK_ociscen', 'models', 'cDiazepam_parameters.json')
  83. # Prvi model s prvim parameter file
  84. model1 = cModel.model()
  85. model1.parse(model_file, parameter_file1)
  86. setup1 = runSolver.parseSetup(setup_file)
  87. name_value_dict1 = create_name_value_dict(model1.parSetup['parameters'])
  88. # Lahko zdaj uporabiš name_value_dict1 in name_value_dict2 ločeno
  89. # Excluded parameters
  90. excluded_params1 = {'venousInput',"heartPC","kidneyPC","remainderPC","skinPC","splanchnicPC","stomachPC","testesPC","one","venousVolume","heartVolume","brainVolume","adiposeVolume","remainderFlow"}
  91. # Create initial guesses without excluded parameters
  92. initial_guesses = np.array(
  93. [val for par, val in name_value_dict1.items() if par not in excluded_params1],
  94. dtype=np.float64
  95. )
  96. # Create list of parameter names without excluded
  97. param_names = [par for par in name_value_dict1.keys() if par not in excluded_params1]
  98. initial_pars = np.array([x for x in initial_guesses])
  99. #initial_pars[3]*=1.1
  100. #print("kolicnik")
  101. #print(initial_guesses/initial_pars)
  102. #print(param_names)
  103. # TO NAREDI REŠITVE Z ZAČETNIMI PARAMETRI
  104. start_point= runSolver.findStartPoint("NONE",setup1)
  105. #model1.setValues(param_names,initial_pars)
  106. clean_dir(jobDir)
  107. t,sol,se,qt,sOut,full_t,full_sol = runSolver.solve(model1,setup1,start_point,jobDir)
  108. clean_dir(jobDir)
  109. # Step 4: Create a new dictionary for the optimized parameters
  110. # Map the optimized parameters back to the correct order in the original parameter dictionary
  111. optimized_params_dict1 = {par: initial_guesses[i] for i, par in enumerate(param_names)}
  112. # Step 5: Include the excluded parameters with their original values
  113. for par in excluded_params1:
  114. optimized_params_dict1[par] = name_value_dict1[par]
  115. # Step 6: Ensure that everything stays in order in the final dictionary
  116. # This will maintain the order of parameters as they appear in the original `name_value_dict2`
  117. final_dict1 = {par: optimized_params_dict1.get(par, name_value_dict1[par]) for par in name_value_dict1}
  118. #################################################################################################################333
  119. # Z DRUGIMI PARAMETRI
  120. ##########################################################################################################################
  121. fh = os.path.expanduser("~")
  122. # Drugi model z drugim parameter file
  123. parameter_file2 = os.path.join(fh, 'Documents', 'Sola', 'IJS', 'PBPK_ociscen', 'models', 'cDiazepam_parameters1.json')
  124. model2 = cModel.model()
  125. model2.parse(model_file, parameter_file2)
  126. setup2 = runSolver.parseSetup(setup_file)
  127. name_value_dict2 = create_name_value_dict(model2.parSetup['parameters'])
  128. # Excluded parameters
  129. excluded_params2 = {'venousInput',"heartPC","kidneyPC","remainderPC","skinPC","splanchnicPC","stomachPC","testesPC","one","venousVolume","heartVolume","brainVolume","adiposeVolume","remainderFlow"}
  130. # Step 1: Filter out excluded parameters for initial guesses
  131. initial_guesses2 = np.array(
  132. [val for par, val in name_value_dict2.items() if par not in excluded_params2],
  133. dtype=np.float64
  134. )
  135. param_names2 = [par for par in name_value_dict2.keys() if par not in excluded_params2]
  136. initial_pars2 = np.array([x for x in initial_guesses2])
  137. # Step 4: Create a new dictionary for the optimized parameters
  138. # Map the optimized parameters back to the correct order in the original parameter dictionary
  139. optimized_params_dict2 = {par: initial_guesses2[i] for i, par in enumerate(param_names2)}
  140. # Step 5: Include the excluded parameters with their original values
  141. for par in excluded_params2:
  142. optimized_params_dict2[par] = name_value_dict2[par]
  143. # Step 6: Ensure that everything stays in order in the final dictionary
  144. # This will maintain the order of parameters as they appear in the original `name_value_dict2`
  145. final_dict2 = {par: optimized_params_dict2.get(par, name_value_dict2[par]) for par in name_value_dict2}
  146. # Step 2: Run optimization
  147. clean_dir(jobDir)
  148. start_point2= runSolver.findStartPoint("NONE",setup2)
  149. t,sol,se,qt,sOut,full_t,full_sol2 = runSolver.solve(model2,setup2,start_point2,jobDir)
  150. result = least_squares(
  151. cost_function, initial_guesses2,
  152. args=(param_names2, full_sol, model2, start_point2, setup2, jobDir)
  153. )
  154. # Step 3: Retrieve optimized parameters
  155. optimized_params3 = result.x
  156. print(result.x)
  157. # Step 4: Create a new dictionary for the optimized parameters
  158. # Map the optimized parameters back to the correct order in the original parameter dictionary
  159. optimized_params_dict3 = {par: optimized_params3[i] for i, par in enumerate(param_names2)}
  160. # Step 5: Include the excluded parameters with their original values
  161. for par in excluded_params2:
  162. optimized_params_dict3[par] = name_value_dict2[par]
  163. # Step 6: Ensure that everything stays in order in the final dictionary
  164. # This will maintain the order of parameters as they appear in the original `name_value_dict2`
  165. final_optimized_dict3 = {par: optimized_params_dict3.get(par, name_value_dict2[par]) for par in name_value_dict2}
  166. # Now, final_optimized_dict contains the optimized values in the same order as in `name_value_dict2`
  167. print(name_value_dict2)
  168. print(final_optimized_dict3)
  169. vrednosti3 = np.array(
  170. [val for par, val in final_optimized_dict3.items()],
  171. dtype=np.float64
  172. )
  173. param_names3 = [par for par in final_optimized_dict3.keys()]
  174. #model2.setValues(param_names3,vrednosti3)
  175. #################################################################################################################################
  176. # PREVRBA ČE SO 3 različne rešitve
  177. clean_dir(jobDir)
  178. t,sol,se,qt,sOut,full_t,full_sol1 = runSolver.solve(model1,setup1,start_point,jobDir)
  179. clean_dir(jobDir)
  180. t,sol,se,qt,sOut,full_t,full_sol2 = runSolver.solve(model2,setup2,start_point2,jobDir)
  181. model2.setValues(param_names3,vrednosti3)
  182. clean_dir(jobDir)
  183. t,sol,se,qt,sOut,full_t,full_sol3 = runSolver.solve(model2,setup2,start_point,jobDir)
  184. print(np.array(full_sol2)/np.array(full_sol1))
  185. print(np.array(full_sol3)/np.array(full_sol1))
  186. print(np.array(full_sol3)/np.array(full_sol2))
  187. print(initial_guesses2/initial_guesses)
  188. print(optimized_params3/initial_guesses2)
  189. print(optimized_params3/initial_guesses)
  190. ##################################################################################################################################
  191. # SHRANIMO REŠITVE ZA PARAMETRE
  192. def create_or_clean_dir(directory):
  193. """Create the directory if it doesn't exist, otherwise clean it."""
  194. if os.path.exists(directory):
  195. shutil.rmtree(directory) # Remove the existing directory and its contents
  196. os.makedirs(directory) # Create a fresh directory
  197. # Example structure to match your requested output format
  198. def save_parameters(file_path, param_dict):
  199. """
  200. Overwrites the original file with the updated parameters.
  201. Parameters:
  202. file_path (str): The path where the updated parameters will be saved.
  203. param_dict (dict): The updated parameters to save.
  204. """
  205. # Ensure the directory exists
  206. os.makedirs(os.path.dirname(file_path), exist_ok=True)
  207. # Open the original file and load its content to preserve its structure
  208. with open(file_path, 'r') as f:
  209. data = json.load(f)
  210. # Update the 'parameters' field with the new parameters
  211. data['parameters'] = param_dict
  212. # Save the updated structure back to the same file
  213. with open(file_path, 'w') as f:
  214. json.dump(data, f, indent=4)
  215. print(f"Updated parameters have been written to {file_path}")
  216. return file_path # Make sure the file path is returned
  217. # Define unique subdirectories
  218. jobDir1 = os.path.join(jobDir, "run1")
  219. jobDir2 = os.path.join(jobDir, "run2")
  220. jobDir3 = os.path.join(jobDir, "run3")
  221. # Ensure directories exist and are clean
  222. create_or_clean_dir(jobDir1)
  223. create_or_clean_dir(jobDir2)
  224. create_or_clean_dir(jobDir3)
  225. #ZA ORIGNAL
  226. # Solve and save results in respective directories
  227. t, sol, se, qt, sOut, full_t, full_sol1 = runSolver.solve(model1, setup1, start_point, jobDir1)
  228. # Define file paths for the new parameter file
  229. new_param_file1 = os.path.join(jobDir1, "parameters.json")
  230. # Update parameters and save them to the new file
  231. model1.updateParameters(final_dict1, parameter_file1, new_param_file1)
  232. # Save updated parameters to the respective directory
  233. save_parameters(os.path.join(jobDir1, "parameters.json"), model1.parSetup['parameters'])
  234. #ZA DRUGI ORIGINAL
  235. new_param_file2 = os.path.join(jobDir2, "parameters.json")
  236. t, sol, se, qt, sOut, full_t, full_sol2 = runSolver.solve(model2, setup2, start_point, jobDir2)
  237. model2.updateParameters(final_dict2, parameter_file2, new_param_file2)
  238. save_parameters(os.path.join(jobDir2, "parameters.json"), model2.parSetup['parameters'])
  239. # Posodobljeni parametri in rešitev
  240. new_param_file3 = os.path.join(jobDir3, "updated_parameters.json")
  241. model2.setValues(param_names3, vrednosti3)
  242. t, sol, se, qt, sOut, full_t, full_sol3 = runSolver.solve(model2, setup2, start_point, jobDir3)
  243. model2.updateParameters(final_optimized_dict3, parameter_file2, new_param_file3)
  244. # Save parameters and immediately store the path for further use
  245. param_file3 = save_parameters(os.path.join(jobDir3, "updated_parameters.json"), model2.parSetup['parameters'])
  246. # Now you can directly use param_file3 in further processing
  247. print(f"Parameters for run3 saved at: {param_file3}")
  248. ########################################################################################################################
  249. #ZGRADIMO 3 MODEL (da bo lažje pol risat)
  250. ##############################################################################################################################################
  251. # param_file3 already contains the full path to "parameters.json"
  252. import os
  253. import glob
  254. directory = os.path.dirname(param_file3)
  255. jobDir3 = os.path.join(fh, 'Documents', 'Sola', 'IJS', 'PBPK_ociscen',"rezultati","run3")
  256. # Make sure param_file3 contains the correct file path, including file name.
  257. # If param_file3 only has the directory, append the file name
  258. parameter_file3 = os.path.join(directory, "updated_parameters.json") # Specify the file name
  259. # Check if it's a valid file
  260. if os.path.isfile(parameter_file3):
  261. with open(parameter_file3, 'r') as f:
  262. # Your code to process the file
  263. pass
  264. else:
  265. print(f"Error: {parameter_file3} is not a valid file.")
  266. import os
  267. import glob
  268. def clean_files(directory):
  269. """Deletes all .txt and .csv files in the given directory."""
  270. # Use glob to find all .txt and .csv files in the directory
  271. txt_files = glob.glob(os.path.join(directory, "*.txt"))
  272. csv_files = glob.glob(os.path.join(directory, "*.csv"))
  273. # Combine both lists of files
  274. all_files = txt_files + csv_files
  275. # Loop through the list of files and delete each one
  276. for file in all_files:
  277. try:
  278. os.remove(file)
  279. print(f"Deleted: {file}")
  280. except Exception as e:
  281. print(f"Error deleting {file}: {e}")
  282. clean_files(jobDir3)
  283. clean_files(jobDir)
  284. clean_files(jobDir1)
  285. clean_files(jobDir2)
  286. #Saves alll the necessary information for drawing in the right files
  287. runSolver.main([setup_file,model_file,parameter_file2,srcDir],jobDir2)
  288. runSolver.main([setup_file,model_file,parameter_file1,srcDir],jobDir1)
  289. runSolver.main([setup_file,model_file,parameter_file3,srcDir],jobDir3)
  290. ########################################################################################################3333
  291. #RISANJE
  292. ########################################################################################################################
  293. job_configs = {
  294. 'cDiazepam_IVP': {
  295. 'jobDir': os.path.join(fh, 'Documents', 'Sola', 'IJS', 'PBPK_ociscen', 'rezultati','run1')
  296. },
  297. 'cDiazepam1_IVP': {
  298. 'jobDir': os.path.join(fh, 'Documents', 'Sola', 'IJS', 'PBPK_ociscen', 'rezultati','run2')
  299. },
  300. 'cDiazepamF_IVP': {
  301. 'jobDir': os.path.join(fh, 'Documents', 'Sola', 'IJS', 'PBPK_ociscen', 'rezultati','run3')
  302. }
  303. }
  304. def mergeSolutions(seq):
  305. """
  306. Merge multiple solution dictionaries into a single dictionary.
  307. """
  308. out = {}
  309. for v in ['t', 'sol', 'se', 'qt', 'sOut']: # Merge arrays from each solution
  310. out[v] = np.concatenate([x[v] for x in seq])
  311. for v in ['lut', 'lutSE', 'setup', 'model', 'parameters', 'qt', 'sOut']: # Use data from the last solution for these keys
  312. out[v] = seq[-1][v]
  313. return out # Return the merged dictionary