diff --git a/Energy.py b/Energy.py index 064cca612fd9e3ac23e70fb2139937635c6e1ada..d84d3ceae41180d334cef1529735f12f1c899c3e 100644 --- a/Energy.py +++ b/Energy.py @@ -2,7 +2,7 @@ ################################################################################ ### ### -### Created by Martin Genet, 2016-2018 ### +### Created by Martin Genet, 2016-2019 ### ### ### ### École Polytechnique, Palaiseau, France ### ### ### diff --git a/Energy_Regularization.py b/Energy_Regularization.py index 651d89d813210528acfebed45ec15370954f6b26..1596d14bba92707c0faa4cca6839ff4c6295b62d 100644 --- a/Energy_Regularization.py +++ b/Energy_Regularization.py @@ -2,7 +2,7 @@ ################################################################################ ### ### -### Created by Martin Genet, 2016-2018 ### +### Created by Martin Genet, 2016-2019 ### ### ### ### École Polytechnique, Palaiseau, France ### ### ### diff --git a/Energy_WarpedImage.py b/Energy_WarpedImage.py index 454865a43e676fe073247e1a9de1c554daeead63..6ad2162dcdaa50ce6b97e6bab886b670bfdf7be4 100644 --- a/Energy_WarpedImage.py +++ b/Energy_WarpedImage.py @@ -2,7 +2,7 @@ ################################################################################ ### ### -### Created by Martin Genet, 2016-2018 ### +### Created by Martin Genet, 2016-2019 ### ### ### ### École Polytechnique, Palaiseau, France ### ### ### @@ -30,6 +30,7 @@ class WarpedImageEnergy(Energy): name="im", w=1., ref_frame=0, + im_is_cone=0, dynamic_scaling=False): self.problem = problem @@ -182,20 +183,32 @@ class WarpedImageEnergy(Energy): # Phi_ref self.Phi_Iref = dolfin.Expression( cppcode=ddic.get_ExprCharFuncIm_cpp( - im_dim=self.image_series.dimension), + im_dim=self.image_series.dimension, + im_is_def=0, + im_is_cone=im_is_cone), element=self.fe) self.Phi_Iref.init_image(self.ref_image_filename) + # Phi_def + self.Phi_Idef = dolfin.Expression( + cppcode=ddic.get_ExprCharFuncIm_cpp( + im_dim=self.image_series.dimension, + im_is_def=1, + im_is_cone=im_is_cone), + element=self.fe) + self.Phi_Idef.init_image(self.ref_image_filename) + self.Phi_Idef.init_disp(self.problem.U) + # Psi_c - self.Psi_c = self.Phi_Iref * (self.Idef - self.Iref)**2/2 - self.DPsi_c = self.Phi_Iref * (self.Idef - self.Iref) * dolfin.dot(self.DIdef, self.problem.dU_test) + self.Psi_c = self.Phi_Idef * self.Phi_Iref * (self.Idef - self.Iref)**2/2 + self.DPsi_c = self.Phi_Idef * self.Phi_Iref * (self.Idef - self.Iref) * dolfin.dot(self.DIdef, self.problem.dU_test) - self.DDPsi_c = self.Phi_Iref * dolfin.dot(self.DIdef, self.problem.dU_trial) * dolfin.dot(self.DIdef, self.problem.dU_test) - self.DDPsi_c_old = self.Phi_Iref * dolfin.dot(self.DIold, self.problem.dU_trial) * dolfin.dot(self.DIold, self.problem.dU_test) - self.DDPsi_c_ref = self.Phi_Iref * dolfin.dot(self.DIref, self.problem.dU_trial) * dolfin.dot(self.DIref, self.problem.dU_test) + self.DDPsi_c = self.Phi_Idef * self.Phi_Iref * dolfin.dot(self.DIdef, self.problem.dU_trial) * dolfin.dot(self.DIdef, self.problem.dU_test) + self.DDPsi_c_old = self.Phi_Idef * self.Phi_Iref * dolfin.dot(self.DIold, self.problem.dU_trial) * dolfin.dot(self.DIold, self.problem.dU_test) + self.DDPsi_c_ref = self.Phi_Idef * self.Phi_Iref * dolfin.dot(self.DIref, self.problem.dU_trial) * dolfin.dot(self.DIref, self.problem.dU_test) - self.Psi_c_old = self.Phi_Iref * (self.Idef - self.Iold)**2/2 - self.DPsi_c_old = self.Phi_Iref * (self.Idef - self.Iold) * dolfin.dot(self.DIdef, self.problem.dU_test) + self.Psi_c_old = self.Phi_Idef * self.Phi_Iref * (self.Idef - self.Iold)**2/2 + self.DPsi_c_old = self.Phi_Idef * self.Phi_Iref * (self.Idef - self.Iold) * dolfin.dot(self.DIdef, self.problem.dU_test) # forms self.ener_form = self.Psi_c * self.dV diff --git a/ImageIterator.py b/ImageIterator.py index 07e1072df59bcc6cc974e7a3707a5058ac2a4ee5..378d6161066de73bbc00990ff782a0d6a14a7752 100644 --- a/ImageIterator.py +++ b/ImageIterator.py @@ -2,15 +2,18 @@ ################################################################################ ### ### -### Created by Martin Genet, 2016-2018 ### +### Created by Martin Genet, 2016-2019 ### ### ### ### École Polytechnique, Palaiseau, France ### ### ### ################################################################################ +import dolfin import glob +import numpy import os import time +import vtk import myPythonLibrary as mypy import myVTKPythonLibrary as myvtk @@ -35,6 +38,11 @@ class ImageIterator(): self.working_folder = parameters["working_folder"] if ("working_folder" in parameters) else "." self.working_basename = parameters["working_basename"] if ("working_basename" in parameters) else "sol" self.register_ref_frame = parameters["register_ref_frame"] if ("register_ref_frame" in parameters) else False + self.initialize_U_from_file = parameters["initialize_U_from_file"] if ("initialize_U_from_file" in parameters) else False + self.initialize_U_folder = parameters["initialize_U_folder"] if ("initialize_U_folder" in parameters) else "." + self.initialize_U_basename = parameters["initialize_U_basename"] if ("initialize_U_basename" in parameters) else None + self.initialize_U_ext = parameters["initialize_U_ext"] if ("initialize_U_ext" in parameters) else "vtu" + self.initialize_U_array_name = parameters["initialize_U_array_name"] if ("initialize_U_array_name" in parameters) else "displacement" self.initialize_DU_with_DUold = parameters["initialize_DU_with_DUold"] if ("initialize_DU_with_DUold" in parameters) else False @@ -77,6 +85,15 @@ class ImageIterator(): self.printer.print_str("Looping over frames…") + if (self.initialize_U_from_file): + mesh_series = ddic.MeshSeries( + problem=self.problem, + folder=self.initialize_U_folder, + basename=self.initialize_U_basename, + ext=self.initialize_U_ext) + + dof_to_vertex_map = dolfin.dof_to_vertex_map(self.problem.U_fs) + n_iter_tot = 0 global_success = True for forward_or_backward in ["forward","backward"]: @@ -108,7 +125,18 @@ class ImageIterator(): k_frame_old = k_frame+1 #self.printer.print_var("k_frame_old",k_frame_old,-1) - if (self.initialize_DU_with_DUold): + if (self.initialize_U_from_file): + mesh = mesh_series.get_mesh(k_frame) + array_U = mesh.GetPointData().GetArray(self.initialize_U_array_name) + array_U = vtk.util.numpy_support.vtk_to_numpy(array_U)[:,:self.problem.mesh_dimension] + # print array_U + # array_U = array_U.astype(float) + # print array_U + array_U = numpy.reshape(array_U, array_U.size) + # print array_U + self.problem.U.vector()[:] = array_U[dof_to_vertex_map] + + elif (self.initialize_DU_with_DUold): self.problem.U.vector().axpy(1., self.problem.DUold.vector()) self.problem.call_before_solve( diff --git a/ImageSeries.py b/ImageSeries.py index 89eea3b992c6fd2b86b054d77f3fe6051043f2ef..c3c219f2d6ea2720acbdbccc64258493c04e50a7 100644 --- a/ImageSeries.py +++ b/ImageSeries.py @@ -2,7 +2,7 @@ ################################################################################ ### ### -### Created by Martin Genet, 2016-2018 ### +### Created by Martin Genet, 2016-2019 ### ### ### ### École Polytechnique, Palaiseau, France ### ### ### diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..65c5ca88a67c30becee01c5a8816d964b03862f9 --- /dev/null +++ b/LICENSE @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/MeshSeries.py b/MeshSeries.py new file mode 100644 index 0000000000000000000000000000000000000000..e61c69241269a811c66fe8ca755fb85b40856b5c --- /dev/null +++ b/MeshSeries.py @@ -0,0 +1,73 @@ +#coding=utf8 + +################################################################################ +### ### +### Created by Martin Genet, 2016-2018 ### +### ### +### École Polytechnique, Palaiseau, France ### +### ### +################################################################################ + +import glob + +import myPythonLibrary as mypy +import myVTKPythonLibrary as myvtk + +import dolfin_dic as ddic + +################################################################################ + + + +class MeshSeries(): + + + + def __init__(self, + problem, + folder, + basename, + n_frames=None, + ext="vtu"): + + self.problem = problem + self.printer = self.problem.printer + self.folder = folder + self.basename = basename + self.n_frames = n_frames + self.ext = ext + + self.printer.print_str("Reading mesh series…") + self.printer.inc() + + self.filenames = glob.glob(self.folder+"/"+self.basename+"_[0-9]*"+"."+self.ext) + assert (len(self.filenames) >= 1),\ + "Not enough meshes ("+self.folder+"/"+self.basename+"_[0-9]*"+"."+self.ext+"). Aborting." + + if (self.n_frames is None): + self.n_frames = len(self.filenames) + else: + assert (self.n_frames <= len(self.filenames)) + assert (self.n_frames >= 1),\ + "n_frames = "+str(self.n_frames)+" < 2. Aborting." + self.printer.print_var("n_frames",self.n_frames) + + self.zfill = len(self.filenames[0].rsplit("_",1)[-1].split(".",1)[0]) + + self.printer.dec() + + + + def get_mesh_filename(self, + k_frame): + + return self.folder+"/"+self.basename+"_"+str(k_frame).zfill(self.zfill)+"."+self.ext + + + + def get_mesh(self, + k_frame): + + return myvtk.readDataSet( + filename=self.get_mesh_filename( + k_frame=k_frame)) diff --git a/NonlinearSolver.py b/NonlinearSolver.py index c983d8dbc25274030d3f1af97b4953c3a2f2ea15..959741fab26b2df58b21cd1ac2c73f3005faa559 100644 --- a/NonlinearSolver.py +++ b/NonlinearSolver.py @@ -2,7 +2,7 @@ ################################################################################ ### ### -### Created by Martin Genet, 2016-2018 ### +### Created by Martin Genet, 2016-2019 ### ### ### ### École Polytechnique, Palaiseau, France ### ### ### @@ -322,7 +322,7 @@ class NonlinearSolver(): self.printer.print_var("dener_min",dener_min) relax_err = dener_min/ener_list[0] self.printer.print_var("relax_err",relax_err) - if (relax_min != 0.) and (relax_err < self.relax_tol): + if (relax_min != 0.) and (abs(relax_err) < self.relax_tol): break if (relax_k == self.relax_n_iter_max): break diff --git a/Problem.py b/Problem.py index cdbba9bc1076127ebeb4b5fd8467c4274c38d03a..a4028765883fc4571e4de301aaf64dd3830ac8bb 100644 --- a/Problem.py +++ b/Problem.py @@ -2,7 +2,7 @@ ################################################################################ ### ### -### Created by Martin Genet, 2016-2018 ### +### Created by Martin Genet, 2016-2019 ### ### ### ### École Polytechnique, Palaiseau, France ### ### ### diff --git a/Problem_ImageRegistration.py b/Problem_ImageRegistration.py index d0898f9edd6cf8346c5add70472f96fb5b00ebb5..f4aa4f23b9cec6dfb54e2871a9d4181ec557c94b 100644 --- a/Problem_ImageRegistration.py +++ b/Problem_ImageRegistration.py @@ -2,7 +2,7 @@ ################################################################################ ### ### -### Created by Martin Genet, 2016-2018 ### +### Created by Martin Genet, 2016-2019 ### ### ### ### École Polytechnique, Palaiseau, France ### ### ### @@ -68,7 +68,7 @@ class ImageRegistrationProblem(Problem): self.mesh_filebasename = self.mesh_folder+"/"+self.mesh_basename self.mesh_filename = self.mesh_filebasename+"."+"xml" assert (os.path.exists(self.mesh_filename)),\ - "No mesh in "+mesh_filename+". Aborting." + "No mesh in "+self.mesh_filename+". Aborting." self.mesh = dolfin.Mesh(self.mesh_filename) else: self.mesh = mesh @@ -192,14 +192,22 @@ class ImageRegistrationProblem(Problem): def assemble_ener(self): - ener_form = 0. + ener = 0. for energy in self.energies: - ener_form += dolfin.Constant(energy.w) * energy.ener_form - - ener = dolfin.assemble( - ener_form) + ener_ = dolfin.assemble( + energy.ener_form) + self.printer.print_var("ener_"+energy.name,ener_) + ener += energy.w * ener_ #self.printer.print_var("ener",ener) + # ener_form = 0. + # for energy in self.energies: + # ener_form += dolfin.Constant(energy.w) * energy.ener_form + # + # ener = dolfin.assemble( + # ener_form) + # #self.printer.print_var("ener",ener) + return ener diff --git a/__init__.py b/__init__.py index 9deddd46220b2a07376a6436b44c404b8e61fc0f..222a8f73c40a23f4d98e50fcb7e42f302b820a07 100644 --- a/__init__.py +++ b/__init__.py @@ -1,30 +1,31 @@ #this file was generated by __init__.py.py -from fedic2 import * -from NonlinearSolver import * -from compute_warped_mesh import * -from image_expressions_py import * -from compute_warped_images import * +from compute_displacement_error import * +from compute_displacements import * +from compute_quadrature_degree import * +from compute_strains import * from compute_unwarped_images import * +from compute_warped_images import * +from compute_warped_mesh import * +from Energy import * +from Energy_Regularization import * +from Energy_WarpedImage import * from fedic import * +from fedic2 import * from generate_images import * -from plot_binned_strains_vs_radius import * -from plot_regional_strains import * -from ImageIterator import * -from Problem import * -from Energy_WarpedImage import * from generate_undersampled_images import * -from Energy_Regularization import * -from compute_strains import * -from compute_displacements import * -from compute_displacement_error import * -from ImageSeries import * -from compute_quadrature_degree import * from generated_image_expressions_cpp import * -from write_VTU_file import * -from Energy import * from image_expressions_cpp import * -from Problem_ImageRegistration import * -from plot_strains import * +from image_expressions_py import * +from ImageIterator import * +from ImageSeries import * +from MeshSeries import * +from NonlinearSolver import * +from plot_binned_strains_vs_radius import * from plot_displacement_error import * +from plot_regional_strains import * +from plot_strains import * from plot_strains_vs_radius import * +from Problem import * +from Problem_ImageRegistration import * +from write_VTU_file import * diff --git a/compute_displacement_error.py b/compute_displacement_error.py index 8e7b6acef8b31dd91f13539e33ee576436b1f34d..74afebb4d0aececa71b7e612315fc99fb533ea2b 100644 --- a/compute_displacement_error.py +++ b/compute_displacement_error.py @@ -2,7 +2,7 @@ ################################################################################ ### ### -### Created by Martin Genet, 2016-2018 ### +### Created by Martin Genet, 2016-2019 ### ### ### ### École Polytechnique, Palaiseau, France ### ### ### diff --git a/compute_displacements.py b/compute_displacements.py index 17332be5a0a4d7f1a45f20ffac4f3aa3705687cc..8b539df001f97dbcfcf6d08b6fdcac08998d24d1 100644 --- a/compute_displacements.py +++ b/compute_displacements.py @@ -2,7 +2,7 @@ ################################################################################ ### ### -### Created by Martin Genet, 2016-2018 ### +### Created by Martin Genet, 2016-2019 ### ### ### ### École Polytechnique, Palaiseau, France ### ### ### diff --git a/compute_quadrature_degree.py b/compute_quadrature_degree.py index 78755d55ebbca9ecfc145024a437b94374b02cc4..e507fc5e5b3e9dd93471ec1c476ebf4da6564c94 100644 --- a/compute_quadrature_degree.py +++ b/compute_quadrature_degree.py @@ -2,7 +2,7 @@ ################################################################################ ### ### -### Created by Martin Genet, 2016-2018 ### +### Created by Martin Genet, 2016-2019 ### ### ### ### École Polytechnique, Palaiseau, France ### ### ### diff --git a/compute_strains.py b/compute_strains.py index 6c69d3c810d36730bcdaad3a2fa9e074a26eea66..a1f37c4c2e7d3290662e14e7378cc12414c41c98 100644 --- a/compute_strains.py +++ b/compute_strains.py @@ -2,7 +2,7 @@ ################################################################################ ### ### -### Created by Martin Genet, 2016-2018 ### +### Created by Martin Genet, 2016-2019 ### ### ### ### École Polytechnique, Palaiseau, France ### ### ### @@ -46,7 +46,7 @@ def compute_strains( verbose=verbose) ref_mesh_n_cells = ref_mesh.GetNumberOfCells() if (verbose): print "ref_mesh_n_cells = " + str(ref_mesh_n_cells) - + if (ref_mesh.GetCellData().HasArray("sector_id")): iarray_sector_id = ref_mesh.GetCellData().GetArray("sector_id") n_sector_ids = 0 @@ -57,7 +57,14 @@ def compute_strains( n_sector_ids = sector_id+1 if (verbose): print "n_sector_ids = " + str(n_sector_ids) else: + iarray_sector_id = None n_sector_ids = 0 + + if (ref_mesh.GetCellData().HasArray("part_id")): + part_id_array = ref_mesh.GetCellData().GetArray("part_id") + else: + part_id_array = None + else: ref_mesh = None n_sector_ids = 0 @@ -104,10 +111,10 @@ def compute_strains( n_cells = mesh.GetNumberOfCells() if (ref_mesh is not None): assert (n_cells == ref_mesh_n_cells), "ref_mesh_n_cells ("+str(ref_mesh_n_cells)+") ≠n_cells ("+str(n_cells)+"). Aborting." - if (ref_mesh.GetCellData().HasArray("part_id")): - mesh.GetCellData().AddArray(ref_mesh.GetCellData().GetArray("part_id")) - if (ref_mesh.GetCellData().HasArray("sector_id")): - mesh.GetCellData().AddArray(ref_mesh.GetCellData().GetArray("sector_id")) + if (part_id_array is not None): + mesh.GetCellData().AddArray(part_id_array) + if (iarray_sector_id is not None): + mesh.GetCellData().AddArray(iarray_sector_id) myvtk.addDeformationGradients( mesh=mesh, disp_array_name=disp_array_name, diff --git a/compute_unwarped_images.py b/compute_unwarped_images.py index cd73bdfed22fc12d0593de0473617b959d2d8e41..1e4c832b5670df7aaf97bca65072c6f52988345f 100644 --- a/compute_unwarped_images.py +++ b/compute_unwarped_images.py @@ -2,10 +2,10 @@ ################################################################################ ### ### -### Created by Martin Genet, 2012-2016 ### +### Created by Martin Genet, 2012-2019 ### ### ### -### University of California at San Francisco (UCSF), USA ### -### Swiss Federal Institute of Technology (ETH), Zurich, Switzerland ### +### University of California at San Francisco (UCSF), USA ### +### Swiss Federal Institute of Technology (ETH), Zurich, Switzerland ### ### École Polytechnique, Palaiseau, France ### ### ### ################################################################################ diff --git a/compute_warped_images.py b/compute_warped_images.py index db65cd05f475aae8e3608828cb7ee34315befa6b..8e0d366e6e566c5bdf127f08198c5fa8d27e0e46 100644 --- a/compute_warped_images.py +++ b/compute_warped_images.py @@ -2,10 +2,10 @@ ################################################################################ ### ### -### Created by Martin Genet, 2012-2016 ### +### Created by Martin Genet, 2012-2019 ### ### ### -### University of California at San Francisco (UCSF), USA ### -### Swiss Federal Institute of Technology (ETH), Zurich, Switzerland ### +### University of California at San Francisco (UCSF), USA ### +### Swiss Federal Institute of Technology (ETH), Zurich, Switzerland ### ### École Polytechnique, Palaiseau, France ### ### ### ################################################################################ @@ -27,7 +27,10 @@ def compute_warped_images( working_folder, working_basename, ref_frame=0, + ref_image_model=None, working_ext="vtu", + working_displacement_field_name="displacement", + print_warped_mesh=0, verbose=0): ref_image_zfill = len(glob.glob(ref_image_folder+"/"+ref_image_basename+"_*.vti")[0].rsplit("_")[-1].split(".")[0]) @@ -35,10 +38,11 @@ def compute_warped_images( ref_image = myvtk.readImage( filename=ref_image_filename) - interpolator = myvtk.getImageInterpolator( - image=ref_image) - #I = numpy.empty(1) - #interpolator.Interpolate([0.35, 0.25, 0.], I) + if (ref_image_model is None): + ref_image_interpolator = myvtk.getImageInterpolator( + image=ref_image) + #I = numpy.empty(1) + #ref_image_interpolator.Interpolate([0.35, 0.25, 0.], I) image = vtk.vtkImageData() image.SetOrigin(ref_image.GetOrigin()) @@ -54,7 +58,7 @@ def compute_warped_images( working_zfill = len(glob.glob(working_folder+"/"+working_basename+"_*."+working_ext)[0].rsplit("_")[-1].split(".")[0]) n_frames = len(glob.glob(working_folder+"/"+working_basename+"_"+"[0-9]"*working_zfill+"."+working_ext)) - #n_frames = 1 + # n_frames = 1 X = numpy.empty(3) U = numpy.empty(3) @@ -66,7 +70,9 @@ def compute_warped_images( mesh = myvtk.readUGrid( filename=working_folder+"/"+working_basename+"_"+str(k_frame).zfill(working_zfill)+"."+working_ext) - #print mesh + # print mesh + assert (mesh.GetPointData().HasArray(working_displacement_field_name)), "no array '" + working_displacement_field_name + "' in mesh" + mesh.GetPointData().SetActiveVectors(working_displacement_field_name) warp = vtk.vtkWarpVector() if (vtk.vtkVersion.GetVTKMajorVersion() >= 6): @@ -75,9 +81,10 @@ def compute_warped_images( warp.SetInput(mesh) warp.Update() warped_mesh = warp.GetOutput() - #myvtk.writeUGrid( - #ugrid=warped_mesh, - #filename=working_folder+"/"+working_basename+"-warped_"+str(k_frame).zfill(working_zfill)+"."+working_ext) + if print_warped_mesh: + myvtk.writeUGrid( + ugrid=warped_mesh, + filename=working_folder+"/"+working_basename+"-warped_"+str(k_frame).zfill(working_zfill)+"."+working_ext) probe = vtk.vtkProbeFilter() if (vtk.vtkVersion.GetVTKMajorVersion() >= 6): @@ -89,7 +96,7 @@ def compute_warped_images( probe.Update() probed_image = probe.GetOutput() scalars_mask = probed_image.GetPointData().GetArray("vtkValidPointMask") - scalars_U = probed_image.GetPointData().GetArray("displacement") + scalars_U = probed_image.GetPointData().GetArray(working_displacement_field_name) #myvtk.writeImage( #image=probed_image, #filename=working_folder+"/"+working_basename+"_"+str(k_frame).zfill(working_zfill)+".vti") @@ -102,7 +109,10 @@ def compute_warped_images( image.GetPoint(k_point, x) scalars_U.GetTuple(k_point, U) X = x - U - interpolator.Interpolate(X, I) + if (ref_image_model is None): + ref_image_interpolator.Interpolate(X, I) + else: + I[0] = ref_image_model(X) scalars.SetTuple(k_point, I) myvtk.writeImage( diff --git a/compute_warped_mesh.py b/compute_warped_mesh.py index e1968c9e6512214628f8c8799417e60d6f965c53..cbe4af546cf9929e8d859a2c6f2e833daeafbcd6 100644 --- a/compute_warped_mesh.py +++ b/compute_warped_mesh.py @@ -2,10 +2,10 @@ ################################################################################ ### ### -### Created by Martin Genet, 2012-2016 ### +### Created by Martin Genet, 2012-2019 ### ### ### -### University of California at San Francisco (UCSF), USA ### -### Swiss Federal Institute of Technology (ETH), Zurich, Switzerland ### +### University of California at San Francisco (UCSF), USA ### +### Swiss Federal Institute of Technology (ETH), Zurich, Switzerland ### ### École Polytechnique, Palaiseau, France ### ### ### ################################################################################ @@ -72,7 +72,7 @@ def compute_warped_mesh( myvtk.addStrainsFromDisplacements( mesh=mesh, disp_array_name="displacement", - ref_mesh=ref_mesh, + mesh_w_local_basis=ref_mesh, verbose=verbose-1) myvtk.writeUGrid( diff --git a/fedic.py b/fedic.py index ee505f8193732d74952ae7c3d9f1207472a357af..d7bfac8586cb43c885905babdc8a649bbbb0c1bf 100644 --- a/fedic.py +++ b/fedic.py @@ -2,7 +2,7 @@ ################################################################################ ### ### -### Created by Martin Genet, 2016-2018 ### +### Created by Martin Genet, 2016-2019 ### ### ### ### École Polytechnique, Palaiseau, France ### ### ### diff --git a/fedic2.py b/fedic2.py index ffe4b66b185f2c02de545ae6f8c3ee97d58f8f1e..a3b5f2a00b164cf9045b00e8278441aec7e29086 100644 --- a/fedic2.py +++ b/fedic2.py @@ -2,7 +2,7 @@ ################################################################################ ### ### -### Created by Martin Genet, 2016-2018 ### +### Created by Martin Genet, 2016-2019 ### ### ### ### École Polytechnique, Palaiseau, France ### ### ### @@ -28,6 +28,7 @@ def fedic2( images_quadrature_from="points_count", # points_count, integral images_expressions_type="cpp", # cpp, py images_dynamic_scaling=1, + images_is_cone=0, mesh=None, mesh_folder=None, mesh_basename=None, @@ -41,6 +42,11 @@ def fedic2( residual_type="Iref", # Iref, Iold, Iref-then-Iold relax_type="gss", # constant, aitken, gss relax_init=1.0, + initialize_U_from_file=0, + initialize_U_folder=None, + initialize_U_basename=None, + initialize_U_ext="vtu", + initialize_U_array_name="displacement", initialize_DU_with_DUold=0, tol_res=None, tol_res_rel=None, @@ -59,6 +65,8 @@ def fedic2( "residual_type must be \"Iref\". Aborting." assert (relax_init == 1.),\ "relax_init must be 1. Aborting." + assert (not ((initialize_U_from_file) and (initialize_DU_with_DUold))),\ + "Cannot initialize U from file and DU with DUold together. Aborting." assert (tol_res is None),\ "tol_res is deprecated. Aborting." assert (tol_im is None),\ @@ -83,6 +91,8 @@ def fedic2( ext=images_ext) if (images_quadrature is None): + problem.printer.print_str("Computing quadrature degree…") + problem.printer.inc() if (images_quadrature_from == "points_count"): images_quadrature = ddic.compute_quadrature_degree_from_points_count( image_filename=image_series.get_image_filename(images_ref_frame), @@ -95,6 +105,8 @@ def fedic2( verbose=1) else: assert (0), "\"images_quadrature_from\" (="+str(images_quadrature_from)+") must be \"points_count\" or \"integral\". Aborting." + problem.printer.print_var("images_quadrature",images_quadrature) + problem.printer.dec() warped_image_energy = ddic.WarpedImageEnergy( problem=problem, @@ -102,7 +114,8 @@ def fedic2( quadrature_degree=images_quadrature, w=1.-regul_level, ref_frame=images_ref_frame, - dynamic_scaling=images_dynamic_scaling) + dynamic_scaling=images_dynamic_scaling, + im_is_cone=images_is_cone) problem.add_image_energy(warped_image_energy) regularization_energy = ddic.RegularizationEnergy( @@ -131,6 +144,11 @@ def fedic2( parameters={ "working_folder":working_folder, "working_basename":working_basename, + "initialize_U_from_file":initialize_U_from_file, + "initialize_U_folder":initialize_U_folder, + "initialize_U_basename":initialize_U_basename, + "initialize_U_ext":initialize_U_ext, + "initialize_U_array_name":initialize_U_array_name, "initialize_DU_with_DUold":initialize_DU_with_DUold}) image_iterator.iterate() diff --git a/generate_images.py b/generate_images.py index fe2a56f9a64679ed4efea8717598bfa7ce2879cf..ffcf5017505b02462e51095b3336ea617e00016c 100644 --- a/generate_images.py +++ b/generate_images.py @@ -2,7 +2,7 @@ ################################################################################ ### ### -### Created by Martin Genet, 2016-2018 ### +### Created by Martin Genet, 2016-2019 ### ### ### ### École Polytechnique, Palaiseau, France ### ### ### @@ -103,6 +103,10 @@ class Image(): # structure if (structure["type"] == "no"): self.I0_structure = self.I0_structure_no + elif (structure["type"] == "box"): + self.I0_structure = self.I0_structure_box + self.Xmin = structure["Xmin"] + self.Xmax = structure["Xmax"] elif (structure["type"] == "heart"): if (images["n_dim"] == 2): self.I0_structure = self.I0_structure_heart_2 @@ -201,6 +205,13 @@ class Image(): i[0] = 1. if (g is not None): g[:] = 1. # MG 20180806: gradient is given by texture; here it is just indicator function + def I0_structure_box(self, X, i, g=None): + if all(numpy.greater_equal(X, self.Xmin)) and all(numpy.less_equal(X, self.Xmax)): + i[0] = 1. + else: + i[0] = 0. + if (g is not None): g[:] = 0. # MG 20180806: gradient is given by texture; here it is just indicator function + def I0_structure_heart_2(self, X, i, g=None): self.R = ((X[0]-self.L[0]/2)**2 + (X[1]-self.L[1]/2)**2)**(1./2) if (self.R >= self.Ri) and (self.R <= self.Re): @@ -437,9 +448,10 @@ class Mapping: pass def init_t_translation(self, t): - self.D[0] = self.deformation["Dx"]*self.phi(t) if ("Dx" in self.deformation.keys()) else 0. - self.D[1] = self.deformation["Dy"]*self.phi(t) if ("Dy" in self.deformation.keys()) else 0. - self.D[2] = self.deformation["Dz"]*self.phi(t) if ("Dz" in self.deformation.keys()) else 0. + self.D[0] = self.deformation["Dx"] if ("Dx" in self.deformation.keys()) else 0. + self.D[1] = self.deformation["Dy"] if ("Dy" in self.deformation.keys()) else 0. + self.D[2] = self.deformation["Dz"] if ("Dz" in self.deformation.keys()) else 0. + self.D *= self.phi(t) def init_t_rotation(self, t): self.C[0] = self.deformation["Cx"] if ("Cx" in self.deformation.keys()) else 0. @@ -461,23 +473,31 @@ class Mapping: self.Rinv[:,:] = numpy.linalg.inv(self.R) def init_t_homogeneous(self, t): - Exx = self.deformation["Exx"]*self.phi(t) if ("Exx" in self.deformation.keys()) else 0. - Eyy = self.deformation["Eyy"]*self.phi(t) if ("Eyy" in self.deformation.keys()) else 0. - Ezz = self.deformation["Ezz"]*self.phi(t) if ("Ezz" in self.deformation.keys()) else 0. - Exy = self.deformation["Exy"]*self.phi(t) if ("Exy" in self.deformation.keys()) else 0. - Eyx = self.deformation["Eyx"]*self.phi(t) if ("Eyx" in self.deformation.keys()) else 0. - Exz = self.deformation["Exz"]*self.phi(t) if ("Exz" in self.deformation.keys()) else 0. - Ezx = self.deformation["Ezx"]*self.phi(t) if ("Ezx" in self.deformation.keys()) else 0. - Eyz = self.deformation["Eyz"]*self.phi(t) if ("Eyz" in self.deformation.keys()) else 0. - Ezy = self.deformation["Ezy"]*self.phi(t) if ("Ezy" in self.deformation.keys()) else 0. - self.F = numpy.array([[Exx, Exy, Exz], - [Eyx, Eyy, Eyz], - [Ezx, Ezy, Ezz]]) - self.F *= 2 - self.F += numpy.eye(3) - w, v = numpy.linalg.eig(self.F) - #assert (numpy.diag(numpy.dot(numpy.dot(numpy.transpose(v), self.F), v)) == w).all(), str(numpy.dot(numpy.dot(numpy.transpose(v), self.F), v))+" ≠"+str(numpy.diag(w))+". Aborting." - self.F = numpy.dot(numpy.dot(v, numpy.diag(numpy.sqrt(w))), numpy.transpose(v)) + if (any(E in self.deformation.keys() for E in ("Exx", "Eyy", "Ezz"))): # build F from E + Exx = self.deformation["Exx"] if ("Exx" in self.deformation.keys()) else 0. + Eyy = self.deformation["Eyy"] if ("Eyy" in self.deformation.keys()) else 0. + Ezz = self.deformation["Ezz"] if ("Ezz" in self.deformation.keys()) else 0. + self.F = numpy.array([[Exx, 0., 0.], + [ 0., Eyy, 0.], + [ 0., 0., Ezz]])*self.phi(t) + self.F *= 2 + self.F += numpy.eye(3) + w, v = numpy.linalg.eig(self.F) + # assert (numpy.diag(numpy.dot(numpy.dot(numpy.transpose(v), self.F), v)) == w).all(), str(numpy.dot(numpy.dot(numpy.transpose(v), self.F), v))+" ≠"+str(numpy.diag(w))+". Aborting." + self.F = numpy.dot(numpy.dot(v, numpy.diag(numpy.sqrt(w))), numpy.transpose(v)) + else: + Fxx = self.deformation["Fxx"] if ("Fxx" in self.deformation.keys()) else 0. + Fyy = self.deformation["Fyy"] if ("Fyy" in self.deformation.keys()) else 0. + Fzz = self.deformation["Fzz"] if ("Fzz" in self.deformation.keys()) else 0. + Fxy = self.deformation["Fxy"] if ("Fxy" in self.deformation.keys()) else 0. + Fyx = self.deformation["Fyx"] if ("Fyx" in self.deformation.keys()) else 0. + Fyz = self.deformation["Fyz"] if ("Fyz" in self.deformation.keys()) else 0. + Fzy = self.deformation["Fzy"] if ("Fzy" in self.deformation.keys()) else 0. + Fzx = self.deformation["Fzx"] if ("Fzx" in self.deformation.keys()) else 0. + Fxz = self.deformation["Fxz"] if ("Fxz" in self.deformation.keys()) else 0. + self.F = numpy.eye(3) + (numpy.array([[Fxx, Fxy, Fxz], + [Fyx, Fyy, Fyz], + [Fzx, Fzy, Fzz]])-numpy.eye(3))*self.phi(t) self.Finv = numpy.linalg.inv(self.F) def init_t_heart(self, t): diff --git a/generate_undersampled_images.py b/generate_undersampled_images.py index 7deda2065669f79fd0344e841c06dfa30800d3c5..bcd23330727d1434c3800bd410a834aa49fa30b8 100644 --- a/generate_undersampled_images.py +++ b/generate_undersampled_images.py @@ -2,7 +2,7 @@ ################################################################################ ### ### -### Created by Martin Genet, 2016-2018 ### +### Created by Martin Genet, 2016-2019 ### ### ### ### École Polytechnique, Palaiseau, France ### ### ### diff --git a/generated_grad_expressions_cpp.py b/generated_grad_expressions_cpp.py new file mode 100644 index 0000000000000000000000000000000000000000..fc64124bbb8141e2c149c1d2feb565aa8c94a9f0 --- /dev/null +++ b/generated_grad_expressions_cpp.py @@ -0,0 +1,176 @@ +#coding=utf8 + +################################################################################ +### ### +### Created by Martin Genet, 2016-2019 ### +### ### +### École Polytechnique, Palaiseau, France ### +### ### +################################################################################ + +################################################################################ + +def get_ExprGenGrad_cpp( + im_dim, + im_type="grad", + im_is_def=0, + disp_type="fenics", # "vtk" + verbose=0): + + assert (im_dim in (2,3)) + assert (im_type in ("grad")) + + ExprGenGrad_cpp = '''\ +#include <string.h> + +#include <vtkSmartPointer.h> +#include <vtkStructuredPointsReader.h> +#include <vtkXMLImageDataReader.h> +#include <vtkImageData.h> +#include <vtkImageGradient.h> +#include <vtkImageInterpolator.h> + +double getStaticScalingFactor(const char* scalar_type_as_string) +{ + if (strcmp(scalar_type_as_string, "unsigned char" ) == 0) return pow(2, 8)-1; + if (strcmp(scalar_type_as_string, "unsigned short") == 0) return pow(2, 16)-1; + if (strcmp(scalar_type_as_string, "unsigned int" ) == 0) return pow(2, 32)-1; + if (strcmp(scalar_type_as_string, "unsigned long" ) == 0) return pow(2, 64)-1; + if (strcmp(scalar_type_as_string, "float" ) == 0) return 1.; + if (strcmp(scalar_type_as_string, "double" ) == 0) return 1.; + assert (0); +} + +namespace dolfin +{ + +class MyExpr : public Expression +{ + vtkSmartPointer<vtkImageData> image; + vtkSmartPointer<vtkImageGradient> gradient; + vtkSmartPointer<vtkImageInterpolator> interpolator; + double static_scaling; + std::shared_ptr<dolfin::Mesh> mesh; + std::shared_ptr<dolfin::Function> U; + mutable Array<double> UX; + mutable Array<double> x; + +public: + + MyExpr(): + Expression('''+str(im_dim)*(im_type in ("grad"))+'''), + UX('''+str(im_dim)+'''), + x(3), + interpolator(vtkSmartPointer<vtkImageInterpolator>::New()) + + { + } + + void init_mesh( + const std::shared_ptr<dolfin::Mesh> mesh_) + { + mesh = mesh_; + + std::cout << mesh->num_vertices() << std::endl; + std::cout << mesh->num_cells() << std::endl; + } + + void init_disp( + const std::shared_ptr<dolfin::Function> U_) + { + U = U_; + } + + void init_image() + { + image = vtkSmartPointer<vtkImageData>::New(); // MG20180913: another way to instantiate object + gradient = vtkSmartPointer<vtkImageGradient>::New(); + } + + + + void eval(Array<double>& expr, const Array<double>& X) const + {'''+(''' + + std::cout << "X = " << X.str(1) << std::endl;''')*(verbose)+''' + + U->eval(UX, X);'''+(''' + std::cout << "UX = " << UX.str(1) << std::endl;''')*(verbose)+(''' + x[0] = X[0] + UX[0]; + x[1] = X[1] + UX[1];''')*(im_dim==2)+(''' + x[0] = X[0] + UX[0]; + x[1] = X[1] + UX[1]; + x[2] = X[2] + UX[2];''')*(im_dim==3)+(''' + std::cout << "x = " << x.str(1) << std::endl;''')*(verbose)+''' + + interpolator->Interpolate(x.data(), expr.data());'''+(''' + std::cout << "expr = " << expr.str(1) << std::endl;''')*(verbose)+(''' + + expr[0] /= static_scaling;''')*(im_type=="im")+(''' + + expr[0] /= static_scaling; + expr[1] /= static_scaling;''')*(im_type=="grad")*(im_dim==2)+(''' + + expr[0] /= static_scaling; + expr[1] /= static_scaling; + expr[2] /= static_scaling;''')*(im_type=="grad")*(im_dim==3)+(''' + std::cout << "expr = " << expr.str(1) << std::endl;''')*(verbose)+''' + } + + + void prepareImage( int n1, int n2, int n3, float origin1, float origin2, float origin3, float spac1, float spac2, float spac3) + { + image->SetDimensions(n1,n2,n3); + image->AllocateScalars(VTK_FLOAT,1); + + image->SetSpacing(spac1, spac2, spac3); + image->SetOrigin(origin1, origin2, origin3); + + static_scaling = getStaticScalingFactor("double"); + } + + + void assignValues( int i, int j, int k, float value) + { + image->SetScalarComponentFromFloat(i,j,k,0,value); + } + + void setGradient_Interpol() + { + interpolator->SetInterpolationModeToLinear(); + interpolator->SetOutValue(.0); + + gradient->SetInputData(image); + gradient->SetDimensionality('''+str(im_dim)+'''); + gradient->Update(); + interpolator->Initialize(gradient->GetOutput()); + + interpolator->Update(); + } + + + void prepareImage_2D( int n1, int n2, float origin1, float origin2, float spac1, float spac2) + { + const double &Z=0.; + image->SetExtent(0, n1-1, 0, n2-1, 0, 0); + + image->AllocateScalars(VTK_FLOAT,1); + + image->SetSpacing(spac1, spac2, 1); + image->SetOrigin(origin1, origin2, 0); + + static_scaling = getStaticScalingFactor("double"); + x[2] = Z; + + } + + + void assignValues_2D( int i, int j, float value) + { + image->SetScalarComponentFromFloat(i,j,0,0,value); + } +}; + +}''' + #print ExprIm_cpp + return ExprGenGrad_cpp diff --git a/generated_image_expressions_cpp.py b/generated_image_expressions_cpp.py index 814ea78cb56374a8d5a186fb30fe60e74fd6d55c..dbbef064dcae8e2dc297b4d3916acae035d97b20 100644 --- a/generated_image_expressions_cpp.py +++ b/generated_image_expressions_cpp.py @@ -2,7 +2,7 @@ ################################################################################ ### ### -### Created by Martin Genet, 2016-2018 ### +### Created by Martin Genet, 2016-2019 ### ### ### ### École Polytechnique, Palaiseau, France ### ### ### @@ -61,8 +61,8 @@ public: reader->SetFileName(filename); reader->Update(); - image = reader->GetOutput(); // image = vtkSmartPointer<vtkImageData>::New(); // MG20180913: another way to instantiate object + image = reader->GetOutput(); static_scaling = getStaticScalingFactor(image->GetScalarTypeAsString()); diff --git a/image_expressions_cpp.py b/image_expressions_cpp.py index 361fe93094eb34320c0ead07f6bf9cec2b04de09..9eb43bb04e367af99e061cac04e3ab890d2191fc 100644 --- a/image_expressions_cpp.py +++ b/image_expressions_cpp.py @@ -2,7 +2,7 @@ ################################################################################ ### ### -### Created by Martin Genet, 2016-2018 ### +### Created by Martin Genet, 2016-2019 ### ### ### ### École Polytechnique, Palaiseau, France ### ### ### @@ -15,6 +15,7 @@ def get_ExprIm_cpp( im_type="im", im_is_def=0, disp_type="fenics", # "vtk" + u_is_vtk=0, verbose=0): assert (im_dim in (2,3)) @@ -29,6 +30,12 @@ def get_ExprIm_cpp( #include <vtkImageData.h>'''+(''' #include <vtkImageGradient.h>''')*(im_type=="grad")+''' #include <vtkImageInterpolator.h> +#include <vtkXMLUnstructuredGridReader.h> +#include <vtkUnstructuredGrid.h> +#include <vtkProbeFilter.h> +#include <vtkPointData.h> +#include <vtkPolyData.h> + double getStaticScalingFactor(const char* scalar_type_as_string) { @@ -50,8 +57,11 @@ class MyExpr : public Expression double static_scaling;'''+(''' Array<double>* dynamic_scaling; // does not work double dynamic_scaling_a; // should not be needed - double dynamic_scaling_b; // should not be needed - Function* U; + double dynamic_scaling_b; // should not be needed'''+(''' + Function* U;''')*(not u_is_vtk)+(''' + vtkSmartPointer<vtkProbeFilter> probe_filter; + vtkSmartPointer<vtkPoints> probe_points; + vtkSmartPointer<vtkPolyData> probe_polydata;''')*(u_is_vtk)+''' mutable Array<double> UX; mutable Array<double> x;''')*(im_is_def)+(''' mutable Array<double> X3D;''')*(not im_is_def)*(im_dim==2)+''' @@ -65,7 +75,10 @@ public: UX('''+str(im_dim)+'''), x(3)''')*(im_is_def)+(''', X3D(3)''')*(not im_is_def)*(im_dim==2)+''' - { + {'''+(''' + probe_filter = vtkSmartPointer<vtkProbeFilter>::New(); + probe_points = vtkSmartPointer<vtkPoints>::New(); + probe_polydata = vtkSmartPointer<vtkPolyData>::New();''')*(u_is_vtk)+''' }'''+(''' void init_dynamic_scaling( @@ -84,11 +97,23 @@ public: dynamic_scaling_b = scaling[1]; // should not be needed } // should not be needed + '''+(''' void init_disp( Function* UU) { U = UU; - }''')*(im_is_def)+''' + }''')*(not u_is_vtk)+(''' + void init_disp( + const char* mesh_filename) + { + vtkSmartPointer<vtkXMLUnstructuredGridReader> reader = vtkSmartPointer<vtkXMLUnstructuredGridReader>::New(); + reader->SetFileName(mesh_filename); + reader->Update(); + + vtkSmartPointer<vtkUnstructuredGrid> mesh = reader->GetOutput(); + + probe_filter->SetSourceData(mesh); + }''')*(u_is_vtk))*(im_is_def)+''' void init_image( const char* filename, @@ -140,9 +165,18 @@ public: void eval(Array<double>& expr, const Array<double>& X) const {'''+(''' - std::cout << "X = " << X.str(1) << std::endl;''')*(verbose)+(''' + std::cout << "X = " << X.str(1) << std::endl;''')*(verbose)+((''' + + U->eval(UX, X);''')*(not u_is_vtk)+(''' + + probe_points->SetNumberOfPoints(1); + probe_points->SetPoint(0,X.data()); + probe_polydata->SetPoints(probe_points); + probe_filter->SetInputData(probe_polydata); + probe_filter->Update(); + probe_filter->GetOutput()->GetPointData()->GetArray("U")->GetTuple(0, UX.data()); - U->eval(UX, X);'''+(''' + ''')*(u_is_vtk)+(''' std::cout << "UX = " << UX.str(1) << std::endl;''')*(verbose)+(''' x[0] = X[0] + UX[0]; x[1] = X[1] + UX[1];''')*(im_dim==2)+(''' @@ -209,13 +243,19 @@ public: #print ExprIm_cpp return ExprIm_cpp + def get_ExprCharFuncIm_cpp( im_dim, + im_is_def=0, + im_is_cone=0, verbose=0): assert (im_dim in (2,3)) + if (im_is_cone): + assert (im_dim == 3) ExprCharFuncIm_cpp = '''\ +#include <math.h> #include <string.h> #include <vtkSmartPointer.h> @@ -228,13 +268,35 @@ namespace dolfin class MyExpr : public Expression { double xmin, xmax, ymin, ymax, zmin, zmax; + mutable Array<double> UX; + mutable Array<double> x;'''+(''' + Function* U;''')*(im_is_def)+(''' + Array<double> O; + Array<double> n1; + Array<double> n2; + Array<double> n3; + Array<double> n4; + mutable double d1, d2, d3, d4;''')*(im_is_cone)+''' public: MyExpr(): - Expression() + Expression(), + UX('''+str(im_dim)+'''), + x('''+str(im_dim)+''')'''+(''', + O(3), + n1(3), + n2(3), + n3(3), + n4(3)''')*(im_is_cone)+''' { - } + }'''+(''' + + void init_disp( + Function* UU) + { + U = UU; + }''')*(im_is_def)+''' void init_image( const char* filename) @@ -257,16 +319,71 @@ public: std::cout << "ymin = " << ymin << std::endl; std::cout << "ymax = " << ymax << std::endl; std::cout << "zmin = " << zmin << std::endl; - std::cout << "zmax = " << zmax << std::endl;''')*(verbose)+''' + std::cout << "zmax = " << zmax << std::endl;''')*(verbose)+(''' + + O[0] = (xmin+xmax)/2; + O[1] = (ymin+ymax)/2; + O[2] = zmax; + + n1[0] = +cos(35. * M_PI/180.); + n1[1] = 0.; + n1[2] = -sin(35. * M_PI/180.); + + n2[0] = -cos(35. * M_PI/180.); + n2[1] = 0.; + n2[2] = -sin(35. * M_PI/180.); + + n3[0] = 0.; + n3[1] = +cos(40. * M_PI/180.); + n3[2] = -sin(40. * M_PI/180.); + + n4[0] = 0.; + n4[1] = -cos(40. * M_PI/180.); + n4[2] = -sin(40. * M_PI/180.);''')*(im_is_cone)+''' } void eval(Array<double>& expr, const Array<double>& X) const {'''+(''' std::cout << "X = " << X.str(1) << std::endl;''')*(verbose)+(''' - if ((X[0] >= xmin) && (X[0] <= xmax) && (X[1] >= ymin) && (X[1] <= ymax))''')*(im_dim==2)+(''' + U->eval(UX, X);''')*(im_is_def)+(''' + std::cout << "UX = " << UX.str(1) << std::endl;''')*(verbose)+(''' - if ((X[0] >= xmin) && (X[0] <= xmax) && (X[1] >= ymin) && (X[1] <= ymax) && (X[2] >= zmin) && (X[2] <= zmax))''')*(im_dim==3)+''' + x[0] = X[0] + UX[0]; + x[1] = X[1] + UX[1];''')*(im_dim==2)+(''' + x[0] = X[0] + UX[0]; + x[1] = X[1] + UX[1]; + x[2] = X[2] + UX[2];''')*(im_dim==3)+(''' + std::cout << "x = " << x.str(1) << std::endl;''')*(verbose)+((''' + + if ((x[0] >= xmin) + && (x[0] <= xmax) + && (x[1] >= ymin) + && (x[1] <= ymax))''')*(im_dim==2)+(''' + if ((x[0] >= xmin) + && (x[0] <= xmax) + && (x[1] >= ymin) + && (x[1] <= ymax) + && (x[2] >= zmin) + && (x[2] <= zmax))''')*(im_dim==3))*(not im_is_cone)+(''' + + d1 = (x[0]-O[0])*n1[0] + + (x[1]-O[1])*n1[1] + + (x[2]-O[2])*n1[2]; + d2 = (x[0]-O[0])*n2[0] + + (x[1]-O[1])*n2[1] + + (x[2]-O[2])*n2[2]; + d3 = (x[0]-O[0])*n3[0] + + (x[1]-O[1])*n3[1] + + (x[2]-O[2])*n3[2]; + d4 = (x[0]-O[0])*n4[0] + + (x[1]-O[1])*n4[1] + + (x[2]-O[2])*n4[2]; + + if ((d1 >= 0.) + && (d2 >= 0.) + && (d3 >= 0.) + && (d4 >= 0.))''')*(im_is_cone)+''' { expr[0] = 1.; } @@ -279,5 +396,5 @@ public: }; }''' - #print ExprCharFuncIm_cpp + # print ExprCharFuncIm_cpp return ExprCharFuncIm_cpp diff --git a/image_expressions_py.py b/image_expressions_py.py index 7e7585bc81d09ab4128da02d85643cfc37fee449..dabb8f138c3cc5a6ba4b0f1cd839cfaa54c4d89b 100644 --- a/image_expressions_py.py +++ b/image_expressions_py.py @@ -2,7 +2,7 @@ ################################################################################ ### ### -### Created by Martin Genet, 2016-2018 ### +### Created by Martin Genet, 2016-2019 ### ### ### ### École Polytechnique, Palaiseau, France ### ### ### diff --git a/plot_binned_strains_vs_radius.py b/plot_binned_strains_vs_radius.py index 25bfc6fce9bc2c39451dd575ef8f0e7315fc5edd..8d0033e959bb4783d2e2e2216af647a8e770917b 100644 --- a/plot_binned_strains_vs_radius.py +++ b/plot_binned_strains_vs_radius.py @@ -2,7 +2,7 @@ ################################################################################ ### ### -### Created by Martin Genet, 2016-2018 ### +### Created by Martin Genet, 2016-2019 ### ### ### ### École Polytechnique, Palaiseau, France ### ### ### diff --git a/plot_displacement_error.py b/plot_displacement_error.py index 727e80dc5f294f19f764cf04604f0af4a9d4d017..57a575678a2f47592b05baed7e082325e8bed488 100644 --- a/plot_displacement_error.py +++ b/plot_displacement_error.py @@ -2,7 +2,7 @@ ################################################################################ ### ### -### Created by Martin Genet, 2016-2018 ### +### Created by Martin Genet, 2016-2019 ### ### ### ### École Polytechnique, Palaiseau, France ### ### ### diff --git a/plot_regional_strains.py b/plot_regional_strains.py index 4237804bb5dc51375a0de51e06b3db3b86824d54..ab3472bfeb05f4dc27ad81d0e58c0075dffa9368 100644 --- a/plot_regional_strains.py +++ b/plot_regional_strains.py @@ -2,7 +2,7 @@ ################################################################################ ### ### -### Created by Martin Genet, 2016-2018 ### +### Created by Martin Genet, 2016-2019 ### ### ### ### École Polytechnique, Palaiseau, France ### ### ### diff --git a/plot_strains.py b/plot_strains.py index 90872397ca9841c7a74ca58e27bd9f777001b90c..ffa967bed80b6d20056eaa742c987f587529a6df 100644 --- a/plot_strains.py +++ b/plot_strains.py @@ -2,7 +2,7 @@ ################################################################################ ### ### -### Created by Martin Genet, 2016-2018 ### +### Created by Martin Genet, 2016-2019 ### ### ### ### École Polytechnique, Palaiseau, France ### ### ### diff --git a/plot_strains_vs_radius.py b/plot_strains_vs_radius.py index 73b4e8d8f6d3fc07d5ca45a1ad24d510546b5f6d..8294398de7e47abaf53d647c77817fa6cf015cc6 100644 --- a/plot_strains_vs_radius.py +++ b/plot_strains_vs_radius.py @@ -2,7 +2,7 @@ ################################################################################ ### ### -### Created by Martin Genet, 2016-2018 ### +### Created by Martin Genet, 2016-2019 ### ### ### ### École Polytechnique, Palaiseau, France ### ### ### diff --git a/project.py b/project.py new file mode 100644 index 0000000000000000000000000000000000000000..62d518487c7ba588c8d5de39248f19f9a9359ea4 --- /dev/null +++ b/project.py @@ -0,0 +1,121 @@ +#coding=utf8 + +################################################################################ +### ### +### Created by Ezgi Berberoğlu, 2018-2019 ### +### ### +### Swiss Federal Institute of Technology (ETH), Zurich, Switzerland ### +### ### +### And Martin Genet, 2016-2019 ### +### ### +### École Polytechnique, Palaiseau, France ### +### ### +################################################################################ + +import dolfin +import numpy + +import myPythonLibrary as mypy +import myVTKPythonLibrary as myvtk + +import dolfin_dic as ddic + +################################################################################ + +def project( + mesh, + image_filename, + image_field_name="displacement", + image_quadrature=1): + + dV = dolfin.Measure("dx", domain=mesh) + form_compiler_parameters_for_images = {} + form_compiler_parameters_for_images["quadrature_degree"] = image_quadrature + + vfe = dolfin.VectorElement( + family="Quadrature", + cell=mesh.ufl_cell(), + degree=image_quadrature, + quad_scheme="default") + + vfs = dolfin.VectorFunctionSpace( + mesh=mesh, + family="Lagrange", + degree=1) + + projected_func = dolfin.Function( + vfs, + name=image_field_name) + U = dolfin.TrialFunction( + vfs) + V = dolfin.TestFunction( + vfs) + + source_expr = dolfin.Expression( + cppcode='''\ +#include <vtkSmartPointer.h> +#include <vtkStructuredGridReader.h> +#include <vtkProbeFilter.h> +#include <vtkStructuredGrid.h> +#include <vtkPolyData.h> +#include <vtkPointData.h> + +namespace dolfin +{ + +class MyExpr : public Expression +{ + vtkSmartPointer<vtkStructuredGrid> sgrid; + vtkSmartPointer<vtkPoints> probe_points; + vtkSmartPointer<vtkPolyData> probe_polydata; + vtkSmartPointer<vtkProbeFilter> probe_filter; + +public: + + MyExpr(): + Expression(3) + { + sgrid = vtkSmartPointer<vtkStructuredGrid>::New(); + probe_points = vtkSmartPointer<vtkPoints>::New(); + probe_polydata = vtkSmartPointer<vtkPolyData>::New(); + probe_filter = vtkSmartPointer<vtkProbeFilter>::New(); + } + + void init_image( + const char* image_filename) + { + vtkSmartPointer<vtkStructuredGridReader> reader = vtkSmartPointer<vtkStructuredGridReader>::New(); + reader->SetFileName(image_filename); + reader->Update(); + sgrid = reader->GetOutput(); + probe_filter->SetSourceData(sgrid); +} + + void eval( + Array<double>& expr, + const Array<double>& X) const + { + probe_points->SetNumberOfPoints(1); + probe_points->SetPoint(0, X.data()); + probe_polydata->SetPoints(probe_points); + probe_filter->SetInputData(probe_polydata); + probe_filter->Update(); + probe_filter->GetOutput()->GetPointData()->GetArray("'''+image_field_name+'''")->GetTuple(0, expr.data()); + } +}; + +}''', + element=vfe) + source_expr.init_image( + image_filename) + + M = dolfin.assemble( + dolfin.inner(U,V)*dV) + + N = dolfin.assemble( + dolfin.inner(source_expr,V)*dV, + form_compiler_parameters=form_compiler_parameters_for_images) + + dolfin.solve(M, projected_func.vector(), N) + + return projected_func diff --git a/write_VTU_file.py b/write_VTU_file.py index 9a71f67414a5b5c34e6861c7171a0fc721998709..512d1b46e966665464213e2d098a789eb5e30c1e 100644 --- a/write_VTU_file.py +++ b/write_VTU_file.py @@ -2,7 +2,7 @@ ################################################################################ ### ### -### Created by Martin Genet, 2016-2018 ### +### Created by Martin Genet, 2016-2019 ### ### ### ### École Polytechnique, Palaiseau, France ### ### ###