├── LDDMM_Python ├── lddmm_python │ ├── lib │ │ ├── __init__.py │ │ └── plotly │ │ │ ├── version.py │ │ │ ├── plotly │ │ │ ├── chunked_requests │ │ │ │ └── __init__.py │ │ │ └── __init__.py │ │ │ ├── matplotlylib │ │ │ ├── mplexporter │ │ │ │ ├── __init__.py │ │ │ │ ├── renderers │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── vincent_renderer.py │ │ │ │ │ └── fake_renderer.py │ │ │ │ ├── _py3k_compat.py │ │ │ │ └── tools.py │ │ │ └── __init__.py │ │ │ ├── widgets │ │ │ └── __init__.py │ │ │ ├── grid_objs │ │ │ └── __init__.py │ │ │ ├── offline │ │ │ └── __init__.py │ │ │ ├── graph_objs │ │ │ └── __init__.py │ │ │ ├── __init__.py │ │ │ └── files.py │ ├── modules │ │ ├── math_utils │ │ │ ├── __init__.py │ │ │ ├── points_clouds.py │ │ │ ├── kernels.py │ │ │ └── real_fft.py │ │ ├── __init__.py │ │ ├── data_attachment │ │ │ ├── __init__.py │ │ │ └── currents.py │ │ ├── models │ │ │ ├── __init__.py │ │ │ ├── frechet_mean.py │ │ │ ├── hypertemplate_atlas.py │ │ │ ├── free_atlas.py │ │ │ └── free_1D_atlas.py │ │ ├── io │ │ │ ├── __init__.py │ │ │ ├── show_code.py │ │ │ ├── my_iplot.py │ │ │ ├── level_lines.py │ │ │ ├── anim3D.py │ │ │ └── read_vtk.py │ │ └── manifolds │ │ │ ├── __init__.py │ │ │ ├── theano_surfacescarrier.py │ │ │ ├── theano_surfaces.py │ │ │ ├── theano_curves.py │ │ │ ├── torus.py │ │ │ ├── theano_hamiltoniancarrier.py │ │ │ └── theano_shapescarrier.py │ └── __init__.py └── demo │ └── Notebooks │ └── Feb2017_paper │ └── data │ ├── source.png │ └── target.png ├── Pytorch ├── data │ ├── amoeba_1.png │ └── amoeba_2.png ├── __pycache__ │ ├── curve.cpython-35.pyc │ ├── kernel.cpython-35.pyc │ ├── shooting.cpython-35.pyc │ └── data_attachment.cpython-35.pyc ├── kernel.py ├── shooting.py ├── curve.py └── data_attachment.py ├── Simple_script ├── amoeba_1.png ├── amoeba_2.png ├── test_pytorch.py └── pytorch_memory_overflow.py ├── matlab ├── Bin │ ├── optim │ │ ├── hanso (third party) │ │ │ ├── .DS_Store │ │ │ ├── isposreal.m │ │ │ ├── isposint.m │ │ │ ├── isnonnegint.m │ │ │ ├── isnaninf.m │ │ │ ├── hgprod.m │ │ │ ├── getbundle.m │ │ │ ├── gradsamp1run.m │ │ │ ├── setx0.m │ │ │ ├── postprocess.m │ │ │ ├── setdefaults.m │ │ │ ├── setdefaultshanso.m │ │ │ └── gradsampfixed.m │ │ ├── perform_bfgs.m │ │ └── set_optim_option.m │ ├── norms │ │ ├── common │ │ │ ├── area.m │ │ │ ├── dcross.m │ │ │ ├── darea.m │ │ │ ├── fcatoms.m │ │ │ └── pVectors.m │ │ ├── shape │ │ │ ├── wasserstein │ │ │ │ ├── getoptions.m │ │ │ │ ├── dsinkhorn_log_cuda.m │ │ │ │ ├── sinkhorn_log_cuda.m │ │ │ │ ├── cost_varifold.m │ │ │ │ ├── fshape_wasserstein_distance.m │ │ │ │ ├── dcost_varifold.m │ │ │ │ ├── sinkhorn_log.m │ │ │ │ └── dfshape_wasserstein_distance.m │ │ │ ├── matchterm.m │ │ │ ├── dmatchterm.m │ │ │ └── chain_rule.m │ │ ├── deformations │ │ │ ├── scalarProductRkhsV.m │ │ │ └── dnormRkhsV.m │ │ └── compute_coefficents_normalization.m │ ├── io │ │ ├── disp_iteration_info.m │ │ ├── dispstructure.m │ │ ├── disp_info_dimension.m │ │ ├── setoptions.m │ │ ├── export_mom_vtk.m │ │ ├── export_fshape_vtk.m │ │ └── import_fshape_vtk.m │ ├── models │ │ ├── matching │ │ │ ├── tan │ │ │ │ ├── enr_match_tan.m │ │ │ │ ├── fsmatch_tan.m │ │ │ │ └── jnfmatch_tan.m │ │ │ └── geom │ │ │ │ ├── match_geom.m │ │ │ │ └── jnfmatch_geom.m │ │ └── atlas │ │ │ └── tan_free │ │ │ ├── enr_tan_free.m │ │ │ └── denr_tan_free.m │ ├── kernels │ │ ├── matlab │ │ │ ├── rho.m │ │ │ └── radial_function_geom.m │ │ └── cuda │ │ │ ├── kernels_old.cx~ │ │ │ ├── kernels_old.cx │ │ │ ├── makefile_cuda.sh~ │ │ │ └── makefile_cuda.sh │ └── deformations │ │ ├── set_defo_option.m │ │ └── tangential │ │ ├── backward_tan.m │ │ ├── forward_tan.m │ │ ├── dHr_tan.m │ │ ├── shoot_and_flow_tan.m │ │ └── ddHrtP_tan.m ├── Script │ ├── hands │ │ ├── data │ │ │ ├── tribute_to_franquin.jpeg │ │ │ ├── read_off.m │ │ │ └── generate_fiber.m │ │ └── script_hands_matching_tan_bundle_ot.m │ ├── bundles │ │ └── script_bundle_matching_ot.m │ └── skulls │ │ └── script_skulls_matching.m ├── README.txt~ └── README.txt ├── .gitignore ├── LICENSE └── README.md /LDDMM_Python/lddmm_python/lib/__init__.py: -------------------------------------------------------------------------------- 1 | __all__ = ['plotly'] 2 | -------------------------------------------------------------------------------- /LDDMM_Python/lddmm_python/lib/plotly/version.py: -------------------------------------------------------------------------------- 1 | __version__ = '1.12.9' 2 | -------------------------------------------------------------------------------- /LDDMM_Python/lddmm_python/modules/math_utils/__init__.py: -------------------------------------------------------------------------------- 1 | __all__ = ['kernels'] 2 | -------------------------------------------------------------------------------- /LDDMM_Python/lddmm_python/lib/plotly/plotly/chunked_requests/__init__.py: -------------------------------------------------------------------------------- 1 | from . chunked_request import Stream -------------------------------------------------------------------------------- /Pytorch/data/amoeba_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeanfeydy/lddmm-ot/HEAD/Pytorch/data/amoeba_1.png -------------------------------------------------------------------------------- /Pytorch/data/amoeba_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeanfeydy/lddmm-ot/HEAD/Pytorch/data/amoeba_2.png -------------------------------------------------------------------------------- /Simple_script/amoeba_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeanfeydy/lddmm-ot/HEAD/Simple_script/amoeba_1.png -------------------------------------------------------------------------------- /Simple_script/amoeba_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeanfeydy/lddmm-ot/HEAD/Simple_script/amoeba_2.png -------------------------------------------------------------------------------- /LDDMM_Python/lddmm_python/modules/__init__.py: -------------------------------------------------------------------------------- 1 | __all__ = ['data_attachment', 'io', 'manifolds', 'models', 'math_utils'] 2 | -------------------------------------------------------------------------------- /LDDMM_Python/lddmm_python/modules/data_attachment/__init__.py: -------------------------------------------------------------------------------- 1 | __all__ = ['measures', 'currents', 'varifolds', 'normal_cycles'] 2 | -------------------------------------------------------------------------------- /Pytorch/__pycache__/curve.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeanfeydy/lddmm-ot/HEAD/Pytorch/__pycache__/curve.cpython-35.pyc -------------------------------------------------------------------------------- /Pytorch/__pycache__/kernel.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeanfeydy/lddmm-ot/HEAD/Pytorch/__pycache__/kernel.cpython-35.pyc -------------------------------------------------------------------------------- /Pytorch/__pycache__/shooting.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeanfeydy/lddmm-ot/HEAD/Pytorch/__pycache__/shooting.cpython-35.pyc -------------------------------------------------------------------------------- /LDDMM_Python/lddmm_python/lib/plotly/matplotlylib/mplexporter/__init__.py: -------------------------------------------------------------------------------- 1 | from .renderers import Renderer 2 | from .exporter import Exporter 3 | -------------------------------------------------------------------------------- /matlab/Bin/optim/hanso (third party)/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeanfeydy/lddmm-ot/HEAD/matlab/Bin/optim/hanso (third party)/.DS_Store -------------------------------------------------------------------------------- /matlab/Script/hands/data/tribute_to_franquin.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeanfeydy/lddmm-ot/HEAD/matlab/Script/hands/data/tribute_to_franquin.jpeg -------------------------------------------------------------------------------- /LDDMM_Python/lddmm_python/modules/models/__init__.py: -------------------------------------------------------------------------------- 1 | __all__ = ['atlas', 'frechet_mean', 'free_1D_atlas', 'free_atlas', 'hypertemplate_atlas', 'model'] 2 | -------------------------------------------------------------------------------- /Pytorch/__pycache__/data_attachment.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeanfeydy/lddmm-ot/HEAD/Pytorch/__pycache__/data_attachment.cpython-35.pyc -------------------------------------------------------------------------------- /LDDMM_Python/lddmm_python/__init__.py: -------------------------------------------------------------------------------- 1 | __all__ = ['lib', 'modules'] 2 | 3 | import os, sys 4 | sys.path.append(os.path.join(os.path.dirname(__file__), "lib")) 5 | -------------------------------------------------------------------------------- /LDDMM_Python/lddmm_python/lib/plotly/widgets/__init__.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | 3 | from plotly.widgets.graph_widget import GraphWidget 4 | -------------------------------------------------------------------------------- /LDDMM_Python/lddmm_python/modules/io/__init__.py: -------------------------------------------------------------------------------- 1 | __all__ = ['anim3D', 'interactive_riemannian_geometry', 'my_iplot', 'my_trisurf', 'read_vtk', 'show_code'] 2 | -------------------------------------------------------------------------------- /LDDMM_Python/demo/Notebooks/Feb2017_paper/data/source.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeanfeydy/lddmm-ot/HEAD/LDDMM_Python/demo/Notebooks/Feb2017_paper/data/source.png -------------------------------------------------------------------------------- /LDDMM_Python/demo/Notebooks/Feb2017_paper/data/target.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeanfeydy/lddmm-ot/HEAD/LDDMM_Python/demo/Notebooks/Feb2017_paper/data/target.png -------------------------------------------------------------------------------- /LDDMM_Python/lddmm_python/modules/manifolds/__init__.py: -------------------------------------------------------------------------------- 1 | __all__ = ['landmarks', 'curves', 'thick_curves', 'riemannian_manifold', 'surface_of_revolution', 'torus', 'kendall_triangles', 'theano_curves'] 2 | -------------------------------------------------------------------------------- /LDDMM_Python/lddmm_python/lib/plotly/grid_objs/__init__.py: -------------------------------------------------------------------------------- 1 | """" 2 | grid_objs 3 | ========= 4 | 5 | """ 6 | from __future__ import absolute_import 7 | 8 | from plotly.grid_objs.grid_objs import Grid, Column 9 | -------------------------------------------------------------------------------- /matlab/README.txt~: -------------------------------------------------------------------------------- 1 | This is a software that computes 2 | registration of shapes using a OT fidelity. 3 | 4 | ----------- 5 | Quick start 6 | ----------- 7 | 8 | 1) compile the mex files in ./Bin/kernels/ with the makefile.sh 9 | 2) run the various examples in ./Script/ 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Will ignore result files in the several examples : 2 | *results* 3 | *output* 4 | !/Pytorch/output/.gitkeep 5 | !/Simple_script/output/.gitkeep 6 | 7 | # Will ignore DS_Stores files 8 | .DS_Store 9 | 10 | # Will ignore .nfs files 11 | .nfs* 12 | 13 | #Will ignore vim swap 14 | *.swp 15 | # 16 | #Will ignore temp files 17 | *~ 18 | -------------------------------------------------------------------------------- /LDDMM_Python/lddmm_python/lib/plotly/offline/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | offline 3 | ====== 4 | This module provides offline functionality. 5 | """ 6 | from . offline import ( 7 | download_plotlyjs, 8 | enable_mpl_offline, 9 | init_notebook_mode, 10 | iplot, 11 | iplot_mpl, 12 | plot, 13 | plot_mpl, 14 | _plot_html 15 | ) 16 | -------------------------------------------------------------------------------- /matlab/README.txt: -------------------------------------------------------------------------------- 1 | This is a software that computes 2 | registration of shapes using a OT fidelity. 3 | 4 | Author : B. Charlier (2017) 5 | 6 | ----------- 7 | Quick start 8 | ----------- 9 | 10 | 1) compile the mex files in ./Bin/kernels/ with the makefile.sh 11 | 2) run the various examples in ./Script/ 12 | 3) the results are saved in '.vtk' legacy format (may be vizualized with "paraview") 13 | -------------------------------------------------------------------------------- /LDDMM_Python/lddmm_python/modules/io/show_code.py: -------------------------------------------------------------------------------- 1 | import inspect 2 | from pygments import highlight 3 | from pygments.lexers import PythonLexer 4 | from pygments.formatters import HtmlFormatter, Terminal256Formatter 5 | 6 | def show_code(func): 7 | if type(func) is str : 8 | code = func 9 | else : 10 | code = inspect.getsourcelines(func)[0] 11 | code = ''.join(code) 12 | print(highlight(code, PythonLexer(), Terminal256Formatter())) 13 | 14 | -------------------------------------------------------------------------------- /matlab/Bin/norms/common/area.m: -------------------------------------------------------------------------------- 1 | function [res] = area(pts,tri) 2 | % compute the areas of a set of triangles 3 | % 4 | % Input: 5 | % pts : list of vertices (n x d matrix) 6 | % tri : list of edges (T x M matrix where M==2 for curve and M==3 for surface) 7 | % 8 | % Output 9 | % res : area of each cell (T x 1 column vector); 10 | % Author : B. Charlier (2017) 11 | 12 | 13 | m = 1 ./ factorial(size(tri,2)-1); 14 | res = sqrt(sum(pVectors(pts,tri) .^2,2)) .* m; 15 | 16 | end 17 | 18 | -------------------------------------------------------------------------------- /LDDMM_Python/lddmm_python/lib/plotly/graph_objs/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | graph_objs 3 | ========== 4 | 5 | This package imports definitions for all of Plotly's graph objects. For more 6 | information, run help(Obj) on any of the following objects defined here. 7 | 8 | The reason for the package graph_objs and the module graph_objs is to provide 9 | a clearer API for users. 10 | 11 | """ 12 | from __future__ import absolute_import 13 | 14 | from plotly.graph_objs.graph_objs import * # this is protected with __all__ 15 | -------------------------------------------------------------------------------- /matlab/Bin/io/disp_iteration_info.m: -------------------------------------------------------------------------------- 1 | function disp_iteration_info(nb_iter_total,ENRnew,stopCond,stepsNew,list_of_variables) 2 | % Author : B. Charlier (2017) 3 | 4 | x=['steps sizes :']; 5 | for i = 1 : length(list_of_variables) 6 | x = [x ,' ',list_of_variables{i},' : %4.2e,']; 7 | end 8 | 9 | fprintf(['\nit. %3d : functional value : %4.2e, Stopping condition (MeandENR) : %4.2e \n ',x(1:end-1),'\n\n'],... 10 | nb_iter_total,ENRnew,stopCond(1),stepsNew{1},stepsNew{2}, stepsNew{3},stepsNew{4}); 11 | 12 | end 13 | -------------------------------------------------------------------------------- /LDDMM_Python/lddmm_python/lib/plotly/matplotlylib/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | matplotlylib 3 | ============ 4 | 5 | This module converts matplotlib figure objects into JSON structures which can 6 | be understood and visualized by Plotly. 7 | 8 | Most of the functionality should be accessed through the parent directory's 9 | 'tools' module or 'plotly' package. 10 | 11 | """ 12 | from __future__ import absolute_import 13 | 14 | from plotly.matplotlylib.renderer import PlotlyRenderer 15 | from plotly.matplotlylib.mplexporter import Exporter 16 | -------------------------------------------------------------------------------- /LDDMM_Python/lddmm_python/lib/plotly/matplotlylib/mplexporter/renderers/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | Matplotlib Renderers 3 | ==================== 4 | This submodule contains renderer objects which define renderer behavior used 5 | within the Exporter class. The base renderer class is :class:`Renderer`, an 6 | abstract base class 7 | """ 8 | 9 | from .base import Renderer 10 | from .vega_renderer import VegaRenderer, fig_to_vega 11 | from .vincent_renderer import VincentRenderer, fig_to_vincent 12 | from .fake_renderer import FakeRenderer, FullFakeRenderer 13 | -------------------------------------------------------------------------------- /matlab/Bin/models/matching/tan/enr_match_tan.m: -------------------------------------------------------------------------------- 1 | function [ENR,dENR] = enr_match_tan(variables_vec) 2 | % Simple wrapper function that can be called by Hanso bfgs. 3 | % Author : B. Charlier (2017) 4 | 5 | global deflag templatexc templatefc 6 | 7 | n = deflag(end) ; 8 | d = size(templatexc{1},2); 9 | 10 | 11 | mom_cell = {reshape(variables_vec(1:d*n),n,d)}; 12 | 13 | ENR = enr_tan_free(templatexc,mom_cell); 14 | 15 | 16 | [~,dnom] = denr_tan_free(templatexc,mom_cell) ; 17 | 18 | 19 | dENR = [cell2mat(dnom )]; 20 | dENR = dENR(:); 21 | 22 | end 23 | 24 | 25 | -------------------------------------------------------------------------------- /matlab/Bin/norms/common/dcross.m: -------------------------------------------------------------------------------- 1 | function [dG1,dG2,dG3,dD1,dD2,dD3] = dcross(G,D,H) 2 | % Differential of (. \wedge .) at points (G,D) and applied to H. In short : d_(G,D) (G\wedge D) (H) 3 | % Author : B. Charlier (2017) 4 | 5 | dG1 = ( -D(:,3) .* H(:,2) + D(:,2) .* H(:,3)); 6 | dG2 = ( +D(:,3) .* H(:,1) - D(:,1) .* H(:,3)); 7 | dG3 = ( -D(:,2) .* H(:,1) + D(:,1) .* H(:,2)); 8 | 9 | dD1 = ( +G(:,3) .* H(:,2) - G(:,2) .* H(:,3)); 10 | dD2 = ( -G(:,3) .* H(:,1) + G(:,1) .* H(:,3)); 11 | dD3 = ( +G(:,2) .* H(:,1) - G(:,1) .* H(:,2)); 12 | 13 | end 14 | -------------------------------------------------------------------------------- /LDDMM_Python/lddmm_python/modules/math_utils/points_clouds.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | def decimate_indices(q, r) : 4 | def rec(l) : 5 | if l == [] : 6 | return [] 7 | else : 8 | new_index = l.pop() 9 | new_point = q[new_index] 10 | s = [] 11 | for i in l : 12 | curr_point = q[i] 13 | if sum((curr_point - new_point)**2) > r**2 : 14 | s.append(i) 15 | m = rec(s) 16 | m.append(new_index) 17 | return m 18 | 19 | return rec([j for j in range(q.shape[0])]) 20 | 21 | def decimate(q, r) : 22 | return np.array([q[i] for i in decimate_indices(q,r)]) 23 | 24 | -------------------------------------------------------------------------------- /LDDMM_Python/lddmm_python/lib/plotly/matplotlylib/mplexporter/_py3k_compat.py: -------------------------------------------------------------------------------- 1 | """ 2 | Simple fixes for Python 2/3 compatibility 3 | """ 4 | import sys 5 | PY3K = sys.version_info[0] >= 3 6 | 7 | 8 | if PY3K: 9 | import builtins 10 | import functools 11 | reduce = functools.reduce 12 | zip = builtins.zip 13 | xrange = builtins.range 14 | map = builtins.map 15 | else: 16 | import __builtin__ 17 | import itertools 18 | builtins = __builtin__ 19 | reduce = __builtin__.reduce 20 | zip = itertools.izip 21 | xrange = __builtin__.xrange 22 | map = itertools.imap 23 | -------------------------------------------------------------------------------- /LDDMM_Python/lddmm_python/lib/plotly/plotly/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | plotly 3 | ====== 4 | 5 | This module defines functionality that requires interaction between your 6 | local machine and Plotly. Almost all functionality used here will require a 7 | verifiable account (username/api-key pair) and a network connection. 8 | 9 | """ 10 | from . plotly import ( 11 | sign_in, 12 | update_plot_options, 13 | get_credentials, 14 | iplot, 15 | plot, 16 | iplot_mpl, 17 | plot_mpl, 18 | get_figure, 19 | Stream, 20 | image, 21 | grid_ops, 22 | meta_ops, 23 | file_ops, 24 | get_config 25 | ) 26 | -------------------------------------------------------------------------------- /matlab/Bin/norms/shape/wasserstein/getoptions.m: -------------------------------------------------------------------------------- 1 | function v = getoptions(options, name, v, mendatory) 2 | % getoptions - retrieve options parameter 3 | % 4 | % v = getoptions(options, 'entry', v0, mendatory); 5 | % is equivalent to the code: 6 | % if isfield(options, 'entry') 7 | % v = options.entry; 8 | % else 9 | % v = v0; 10 | % end 11 | % Author : B. Charlier (2017) 12 | 13 | 14 | if nargin<3 15 | error('Not enough arguments.'); 16 | end 17 | if nargin<4 18 | mendatory = 0; 19 | end 20 | 21 | if isfield(options, name) 22 | v = eval(['options.' name ';']); 23 | elseif mendatory 24 | error(['You have to provide options.' name '.']); 25 | end 26 | -------------------------------------------------------------------------------- /LDDMM_Python/lddmm_python/modules/io/my_iplot.py: -------------------------------------------------------------------------------- 1 | from plotly.offline import iplot, _plot_html 2 | from IPython.display import HTML, display 3 | import ipywidgets as widgets 4 | 5 | def my_iplot(figure_or_data, show_link=False, link_text='Export to plot.ly', 6 | validate=True, image=None, filename='plot_image', image_width=800, 7 | image_height=600) : 8 | plot_html, plotdivid, width, height = _plot_html( 9 | figure_or_data, show_link, link_text, validate, 10 | '100%', 525, global_requirejs=True) 11 | #display(HTML(plot_html)) 12 | wid = widgets.HTML( 13 | value=plot_html, 14 | placeholder='Some HTML', 15 | description='Some HTML', 16 | disabled=False 17 | ) 18 | 19 | return (wid, plotdivid) 20 | -------------------------------------------------------------------------------- /matlab/Bin/kernels/matlab/rho.m: -------------------------------------------------------------------------------- 1 | function r=rho(x,opt,sig) 2 | % r=RHO(x,opt,sig) implements the Gaussian kernel and its derivatives : 3 | % 4 | % rho(t)=exp(-t/lam^2); 5 | % 6 | % Computation of rho(x^2/2) (ie opt==0), rho'(x^2/2) (ie opt==1) and 7 | % rho"(x^2/2) (ie opt==2) 8 | % 9 | % Input : 10 | % x : a matrix 11 | % opt : a integer 12 | % sig : vector with kernel bandwidths 13 | % 14 | % Output : 15 | % r : matrix of the size of x 16 | % Author : B. Charlier (2017) 17 | 18 | 19 | r=zeros(size(x)); 20 | for l=sig 21 | 22 | if opt==0 23 | r=r + exp(-x/l^2); 24 | elseif opt==1 25 | r=r -exp(-x/l^2)/l^2; 26 | elseif opt==2 27 | r=r +exp(-x/l^2)/l^4; 28 | end 29 | end 30 | 31 | end 32 | -------------------------------------------------------------------------------- /matlab/Bin/io/dispstructure.m: -------------------------------------------------------------------------------- 1 | function mesg=dispstructure(structvar) 2 | % This function outputs a caracter array with nested structures. May be enhanced.... 3 | % Author : B. Charlier (2017) 4 | 5 | 6 | mesg = []; 7 | structvar = orderfields(structvar); 8 | 9 | 10 | fields=fieldnames(structvar); 11 | for k=1:length(fields) 12 | if isstruct(eval(['structvar.' fields{k}])) 13 | str = orderfields(eval(['structvar.',fields{k}])); 14 | mesg = [mesg,[' ',fields{k},'.',char(10)],evalc(' disp( str )')]; 15 | structvar = rmfield(structvar, fields{k}); 16 | end 17 | end 18 | 19 | 20 | mesg_root = evalc('disp(structvar)'); 21 | 22 | mesg = [mesg_root,mesg]; 23 | 24 | 25 | end 26 | -------------------------------------------------------------------------------- /Pytorch/kernel.py: -------------------------------------------------------------------------------- 1 | # Import the relevant tools 2 | import numpy as np # standard array library 3 | import torch 4 | 5 | def _squared_distances(x, y) : 6 | "Returns the matrix of $\|x_i-y_j\|^2$." 7 | x_col = x.unsqueeze(1) # Theano : x.dimshuffle(0, 'x', 1) 8 | y_lin = y.unsqueeze(0) # Theano : y.dimshuffle('x', 0, 1) 9 | return torch.sum( (x_col - y_lin)**2 , 2 ) 10 | 11 | def _k(x, y, s) : 12 | "Returns the matrix of k(x_i,y_j)." 13 | sq = _squared_distances(x, y) / (s**2) 14 | #return torch.exp( -sq ) 15 | return torch.pow( 1. / ( 1. + sq ), .25 ) 16 | 17 | def _cross_kernels(q, x, s) : 18 | "Returns the full k-correlation matrices between two point clouds q and x." 19 | K_qq = _k(q, q, s) 20 | K_qx = _k(q, x, s) 21 | K_xx = _k(x, x, s) 22 | return (K_qq, K_qx, K_xx) 23 | -------------------------------------------------------------------------------- /LDDMM_Python/lddmm_python/modules/math_utils/kernels.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import theano 3 | import theano.tensor as T 4 | 5 | 6 | def _squared_distances(x, y) : 7 | return (x ** 2).sum(1).reshape((x.shape[0], 1)) \ 8 | + (y ** 2).sum(1).reshape((1, y.shape[0])) \ 9 | - 2* x.dot(y.T) 10 | 11 | def _gaussian_kernel(x, y, s) : 12 | if type(s) is not list : 13 | s = [(1., s)] 14 | res = s[0][0] * T.exp(- _squared_distances(x,y) / (2 * s[0][1]**2) ) 15 | for (coeff,sigm) in s[1:] : 16 | res = res + coeff * T.exp(- _squared_distances(x,y) / (2 * sigm**2) ) 17 | return res 18 | 19 | def _gaussian_cross_kernels(q, x, s) : 20 | K_qq = _gaussian_kernel(q, q, s) 21 | K_qx = _gaussian_kernel(q, x, s) 22 | K_xx = _gaussian_kernel(x, x, s) 23 | 24 | return (K_qq, K_qx, K_xx) 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /matlab/Bin/norms/shape/matchterm.m: -------------------------------------------------------------------------------- 1 | function g= matchterm(fshape1,fshape2,objfun) 2 | % g= MATCHTERM(fshape1,fshape2,objfun) computes the distance between 3 | % fshape1 and fshape2 wrt various norms. Options 4 | % are given by the structure objfun. 5 | % 6 | %Input 7 | % fshape1 : fshape structure 8 | % fshape2 : fshape structure 9 | % objfun : structure containing the parameters : 10 | %Output 11 | % g = real number 12 | % Author : B. Charlier (2017) 13 | 14 | 15 | % Some checks 16 | if (size(fshape1.x,2) ~= size(fshape2.x,2)) || (size(fshape1.G,2) ~= size(fshape2.G,2)) 17 | error('fshapes should be in the same space') 18 | end 19 | 20 | switch objfun.distance 21 | 22 | case 'wasserstein' 23 | G = @fshape_wasserstein_distance; 24 | 25 | end 26 | 27 | 28 | g = G(fshape1,fshape2,objfun); 29 | 30 | end 31 | 32 | -------------------------------------------------------------------------------- /LDDMM_Python/lddmm_python/modules/manifolds/theano_surfacescarrier.py: -------------------------------------------------------------------------------- 1 | # Import of the relevant tools 2 | import time 3 | import numpy as np 4 | import theano 5 | import theano.tensor as T 6 | from theano import pp, config 7 | 8 | 9 | from plotly.tools import FigureFactory as FF 10 | import plotly.graph_objs as go 11 | 12 | from ..io.read_vtk import ReadVTK 13 | 14 | 15 | from .theano_shapescarrier import TheanoShapesCarrier 16 | from .surfaces_manifold import SurfacesManifold 17 | 18 | class TheanoSurfacesCarrier(SurfacesManifold, TheanoShapesCarrier) : 19 | """ 20 | Surface + HamiltonianDynamics with control points. 21 | """ 22 | def __init__(self, *args, **kwargs) : 23 | """ 24 | Creates a TheanoSurfaces manifold. 25 | Compilation takes place here. 26 | """ 27 | TheanoShapesCarrier.__init__(self, *args, **kwargs) 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /matlab/Bin/norms/shape/wasserstein/dsinkhorn_log_cuda.m: -------------------------------------------------------------------------------- 1 | function [u,grad_x] = dsinkhorn_log_cuda(mu,nu,x,y,epsilon,options,d) 2 | % A wrapper function calling a cuda implementation of sinkhorn_log - stabilized 3 | % sinkhorn over log domain with acceleration. It computes the derivative 4 | % with respect to x. 5 | % 6 | % See : Sinkhorn_log and dfshapes_wasserstein_distance functions for details 7 | % Author : B. Charlier (2017) 8 | 9 | 10 | options.null = 0; 11 | rho = getoptions(options, 'rho', Inf); 12 | 13 | if rho==Inf 14 | %balanced 15 | lambda=1; 16 | else 17 | % unbalanced 18 | lambda = rho/(rho+epsilon); 19 | end 20 | 21 | % Sinkhorn 22 | u = zeros(size(mu)); 23 | v = zeros(size(nu)); 24 | 25 | [u,grad_x] = dsinkhornGpuConv(u',x,y,v',epsilon,lambda,mu',nu',options.weight_cost_varifold,int32(options.niter)); 26 | 27 | u = u'; grad_x = grad_x'; 28 | 29 | end 30 | -------------------------------------------------------------------------------- /matlab/Bin/norms/shape/dmatchterm.m: -------------------------------------------------------------------------------- 1 | function [dxg]= dmatchterm(fshape1,fshape2,objfun) 2 | % g= DMATCHTERM(fshape1,fshape2,objfun) computes the distance between 3 | % fshape1 and fshape2 wrt various norms. Options 4 | % are given by the structure objfun. 5 | % 6 | %Input 7 | % fshape1 : a fshape structure 8 | % fshape2 : a fshape structure 9 | % objfun : structure containing the parameters 10 | %Output 11 | % dxg : derivative wrt x (matrix n x d) 12 | % dfg : derivative wrt f (vector n x 1) 13 | % Author : B. Charlier (2017) 14 | 15 | % Some checks 16 | if (size(fshape1.x,2) ~= size(fshape2.x,2)) || (size(fshape1.G,2) ~= size(fshape2.G,2)) 17 | error('fshapes should be in the same space') 18 | end 19 | 20 | 21 | switch objfun.distance 22 | case 'wasserstein' 23 | DG = @dfshape_wasserstein_distance; 24 | end 25 | 26 | 27 | 28 | [dxg] = DG(fshape1,fshape2,objfun); 29 | 30 | end 31 | -------------------------------------------------------------------------------- /matlab/Bin/io/disp_info_dimension.m: -------------------------------------------------------------------------------- 1 | function msg = disp_info_dimension(data,template,silent) 2 | % print some informations about the dimension of the problem 3 | % Author : B. Charlier (2017) 4 | 5 | deflag = [0,cumsum(cellfun(@(y) size(y.x,1),template))]; 6 | nlist = diff(deflag); % number of point in each shape 7 | 8 | [nb_obs,nb_match] = size(data); 9 | x = repmat(' %d,',1,nb_match); 10 | msg = [sprintf('\n----------- Dimensions of the problem -----------\n'),... 11 | sprintf('Data : %d observations containing %d fshape(s) each.',nb_obs,nb_match),... 12 | sprintf([' The mean number of points in each shape is : ',x(1+1:end-1),'.'],floor(mean(cellfun(@(y) size(y.x,1),data)))),... 13 | sprintf('\nMean Template : contains %d fshape(s). The number of points is : ',size(template,2)),... 14 | sprintf([x(1+1:end-1),'.'],nlist),... 15 | sprintf('\n')]; 16 | 17 | if nargin ==2 || (silent == 0) 18 | disp(msg) 19 | end 20 | 21 | end 22 | -------------------------------------------------------------------------------- /matlab/Bin/norms/common/darea.m: -------------------------------------------------------------------------------- 1 | function [dArea] = darea(pts,tri) 2 | % compute the derivative of the areas of a set of triangles 3 | % 4 | % Input: 5 | % pts : nb_points x d matrix 6 | % tri : nb_tri x M matrix (M==2 for curve and M==3 for surface) 7 | % 8 | % Output 9 | % dArea : (M* nb_tri) x d matrix; 10 | % Author : B. Charlier (2017) 11 | 12 | 13 | [~,M] = size(tri); 14 | [~,d] = size(pts); 15 | 16 | N = pVectors(pts,tri); 17 | N = bsxfun(@rdivide,N,sqrt(sum(N.^2,2))); 18 | 19 | if (M==2) && (d<=3) 20 | 21 | dArea = [-N;N]; 22 | elseif (M==3) && (d==3) 23 | 24 | E21 = (pts(tri(:,2),:) - pts(tri(:,1),:)); 25 | E31 = (pts(tri(:,3),:) - pts(tri(:,1),:)); 26 | 27 | [dG1,dG2,dG3,dD1,dD2,dD3] = dcross(E21,E31,N); 28 | 29 | dArea = .5* [[-dG1-dD1;+dG1 ;+dD1 ],... 30 | [-dG2-dD2;+dG2 ;+dD2 ],... 31 | [-dG3-dD3;+dG3 ;+dD3 ]]; 32 | end 33 | 34 | end 35 | -------------------------------------------------------------------------------- /matlab/Bin/norms/shape/wasserstein/sinkhorn_log_cuda.m: -------------------------------------------------------------------------------- 1 | function [u,v,Wprimal,Wdual,err] = sinkhorn_log_cuda(mu,nu,x,y,epsilon,options) 2 | % A wrapper function calling a cuda implementation of sinkhorn_log - stabilized sinkhorn over log domain without acceleration 3 | % 4 | % See : Sinkhorn_log function for details 5 | % Author : B. Charlier (2017) 6 | 7 | 8 | rho = getoptions(options, 'rho', Inf); 9 | 10 | % Sinkhorn 11 | u = zeros(size(mu)); 12 | v = zeros(size(nu)); 13 | 14 | if rho==Inf 15 | %balanced 16 | lambda=1; 17 | [u,v,Wdual] = sinkhornGpuConv(u',x,y,v',epsilon,lambda,mu',nu',options.weight_cost_varifold,int32(options.niter)); 18 | else 19 | % unbalanced 20 | lambda = rho/(rho+epsilon); 21 | [u,v,Wdual] = sinkhornGpuConv_unbalanced(u',x,y,v',epsilon,lambda,rho,mu',nu',options.weight_cost_varifold,int32(options.niter)); 22 | end 23 | 24 | 25 | 26 | Wprimal = []; 27 | err =0; 28 | 29 | u = u'; v = v'; 30 | 31 | end 32 | 33 | 34 | -------------------------------------------------------------------------------- /LDDMM_Python/lddmm_python/lib/plotly/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | https://plot.ly/python/ 3 | 4 | Plotly's Python API allows users to programmatically access Plotly's 5 | server resources. 6 | 7 | This package is organized as follows: 8 | 9 | Subpackages: 10 | 11 | - plotly: all functionality that requires access to Plotly's servers 12 | 13 | - graph_objs: objects for designing figures and visualizing data 14 | 15 | - matplotlylib: tools to convert matplotlib figures 16 | 17 | Modules: 18 | 19 | - tools: some helpful tools that do not require access to Plotly's servers 20 | 21 | - utils: functions that you probably won't need, but that subpackages use 22 | 23 | - version: holds the current API version 24 | 25 | - exceptions: defines our custom exception classes 26 | 27 | """ 28 | 29 | from __future__ import absolute_import 30 | 31 | from plotly import (plotly, graph_objs, grid_objs, tools, utils, session, 32 | offline, colors) 33 | from plotly.version import __version__ 34 | -------------------------------------------------------------------------------- /LDDMM_Python/lddmm_python/modules/manifolds/theano_surfaces.py: -------------------------------------------------------------------------------- 1 | # Import of the relevant tools 2 | import time 3 | import numpy as np 4 | import theano 5 | import theano.tensor as T 6 | from theano import pp, config 7 | 8 | 9 | from plotly.tools import FigureFactory as FF 10 | import plotly.graph_objs as go 11 | 12 | from ..io.read_vtk import ReadVTK 13 | 14 | # a TheanoCurves manifold will be created from a regular Curve, 15 | # with information about connectivity and number of points. 16 | # Basically, a TheanoCurves is an efficient implementation of 17 | # a shape orbit. 18 | from .theano_shapes import TheanoShapes 19 | from .surfaces_manifold import SurfacesManifold 20 | 21 | class TheanoSurfaces(SurfacesManifold, TheanoShapes) : 22 | """ 23 | Surface + HamiltonianDynamics with dense momentum field. 24 | """ 25 | def __init__(self, *args, **kwargs) : 26 | """ 27 | Creates a TheanoSurfaces manifold. 28 | Compilation takes place here. 29 | """ 30 | TheanoShapes.__init__(self, *args, **kwargs) 31 | 32 | 33 | -------------------------------------------------------------------------------- /LDDMM_Python/lddmm_python/modules/manifolds/theano_curves.py: -------------------------------------------------------------------------------- 1 | # Import of the relevant tools 2 | import time 3 | import numpy as np 4 | import theano 5 | import theano.tensor as T 6 | from theano import pp, config 7 | 8 | 9 | from plotly.tools import FigureFactory as FF 10 | import plotly.graph_objs as go 11 | 12 | from ..io.read_vtk import ReadVTK 13 | 14 | # a TheanoCurves manifold will be created from a regular Curve, 15 | # with information about connectivity and number of points. 16 | # Basically, a TheanoCurves is an efficient implementation of 17 | # a shape orbit. 18 | from .theano_shapes import TheanoShapes 19 | from .curves_manifold import CurvesManifold 20 | 21 | class TheanoCurves(CurvesManifold, TheanoShapes) : 22 | """ 23 | Curve + HamiltonianDynamics with dense momentum field. 24 | """ 25 | def __init__(self, *args, **kwargs) : 26 | """ 27 | Creates a TheanoCurves manifold. 28 | Compilation takes place here. 29 | """ 30 | TheanoShapes.__init__(self, *args, **kwargs) 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /matlab/Bin/deformations/set_defo_option.m: -------------------------------------------------------------------------------- 1 | function [ndefo,mesg] = set_defo_option(defo,list_of_variables) 2 | % This function check the defo structure and set default values if needed. 3 | % Author : B. Charlier (2017) 4 | 5 | is_algo_met =(sum(strcmp(list_of_variables(:),'pf')) >0); 6 | 7 | ndefo = defo; 8 | 9 | ndefo = setoptions(ndefo,'method','matlab',{'cuda','matlab','grid'}); 10 | 11 | if (strcmp(defo.method,'grid')) && ( ~isfield(defo,'gridratio') || (defo.gridratio < 0) || (defo.gridratio >1) ) 12 | ndefo.gridratio = .2; 13 | %fprintf('deformation : gridratio set to %f\n',ndefo.gridratio) 14 | end 15 | 16 | ndefo = setoptions(ndefo,'nb_euler_steps',10); 17 | ndefo = setoptions(ndefo,'kernel_size_mom'); 18 | 19 | if is_algo_met 20 | ndefo = setoptions(ndefo,'weight_coef_pen_p',1); 21 | ndefo = setoptions(ndefo,'weight_coef_pen_pf',1); 22 | end 23 | 24 | % save message and display 25 | mesg = [sprintf('\n----------- Deformation parameters -----------\n' ),... 26 | evalc('disp(orderfields(ndefo))')]; 27 | fprintf('%s',mesg); 28 | 29 | end 30 | -------------------------------------------------------------------------------- /matlab/Bin/io/setoptions.m: -------------------------------------------------------------------------------- 1 | function v = setoptions(struct, fieldname, default_value, possible_value) 2 | % setoptions(struct, fieldname, default_value, possible_value) - given a struct, 3 | % check if the field 'fieldname' exists. If not it create the field with 4 | % the default value. If it exists and possible_value is 5 | % given, it checks that the existing value is in possible value. 6 | % 7 | % Input 8 | % struct : a structure 9 | % fieldname : a string with the fieldname 10 | % default_value : a default value 11 | % Output 12 | % struct : the checked structure. 13 | % Author : B. Charlier (2017) 14 | 15 | v = struct; 16 | 17 | if ~isfield(struct, fieldname) && (nargin ==2) 18 | 19 | error([fieldname,' is mandatory!']) 20 | 21 | elseif ~isfield(struct, fieldname) && (nargin > 2) 22 | 23 | v.(fieldname) = default_value; 24 | 25 | elseif nargin == 4 && ischar(default_value) 26 | 27 | if sum(strcmp(possible_value(:),v.(fieldname))) == 0 28 | error(['Possible values for ',fieldname,' is ',cell2mat(possible_value)]) 29 | end 30 | 31 | end 32 | 33 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 jeanfeydy 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /matlab/Script/hands/data/read_off.m: -------------------------------------------------------------------------------- 1 | function [vertex,face] = read_off(filename) 2 | 3 | % read_off - read data from OFF file. 4 | % 5 | % [vertex,face] = read_off(filename); 6 | % 7 | % 'vertex' is a 'nb.vert x 3' array specifying the position of the vertices. 8 | % 'face' is a 'nb.face x 3' array specifying the connectivity of the mesh. 9 | 10 | 11 | fid = fopen(filename,'r'); 12 | if( fid==-1 ) 13 | error('Can''t open the file.'); 14 | return; 15 | end 16 | 17 | str = fgets(fid); % -1 if eof 18 | if ~strcmp(str(1:3), 'OFF') 19 | error('The file is not a valid OFF one.'); 20 | end 21 | 22 | str = fgets(fid); 23 | [a,str] = strtok(str); nvert = str2num(a); 24 | [a,str] = strtok(str); nface = str2num(a); 25 | 26 | 27 | 28 | [A,cnt] = fscanf(fid,'%f %f %f', 3*nvert); 29 | if cnt~=3*nvert 30 | warning('Problem in reading vertices.'); 31 | end 32 | A = reshape(A, 3, cnt/3); 33 | vertex = A; 34 | % read Face 1 1088 480 1022 35 | [A,cnt] = fscanf(fid,'%d %d %d %d\n', 4*nface); 36 | if cnt~=4*nface 37 | warning('Problem in reading faces.'); 38 | end 39 | A = reshape(A, 4, cnt/4); 40 | face = A(2:4,:)+1; 41 | 42 | 43 | fclose(fid); 44 | 45 | -------------------------------------------------------------------------------- /LDDMM_Python/lddmm_python/modules/math_utils/real_fft.py: -------------------------------------------------------------------------------- 1 | import theano.tensor as T 2 | from theano.tensor.fft import rfft, irfft 3 | #from theano.gpuarray.fft import curfft as rfft 4 | #from theano.gpuarray.fft import cuirfft as irfft 5 | _rfft1d = rfft 6 | _irfft1d = irfft 7 | 8 | def _rfft2d(x) : 9 | """ 10 | Outputs a tensor3 of size (im.shape//2+1)+(4,). 11 | At each location, 4 real fourier transforms which respectively encode 12 | Re.Re, Re.Im, Im.Re, Im.Im. 13 | 14 | This routine is provided for you to understand its inverse the _irfft2d routine... 15 | """ 16 | # First, take the real FFT along dimension 1 17 | f_x = _rfft1d(x).dimshuffle(1,0,2) # dimshuffle in order to take the FFT along dim 0 18 | f_x_re = _rfft1d(f_x[:,:,0]).dimshuffle(1,0,2) 19 | f_x_im = _rfft1d(f_x[:,:,1]).dimshuffle(1,0,2) 20 | return T.concatenate([f_x_re, f_x_im], axis = 2) 21 | 22 | def _irfft2d(f_x) : 23 | """ 24 | Inverse of the _rfft2d(x) routine. 25 | """ 26 | f_x = f_x.dimshuffle(1,0,2) 27 | f_x_re = _irfft1d(f_x[:,:,0:2]).dimshuffle(1,0) 28 | f_x_im = _irfft1d(f_x[:,:,2:4]).dimshuffle(1,0) 29 | x = _irfft1d( T.stack([f_x_re, f_x_im], axis = 2) ) 30 | return(x) 31 | 32 | 33 | -------------------------------------------------------------------------------- /matlab/Bin/kernels/matlab/radial_function_geom.m: -------------------------------------------------------------------------------- 1 | function r=radial_function_geom(x,derivative_order,objfun) 2 | % r=RHO(x,opt,sig) implements the Gaussian kernel and its derivatives : 3 | % 4 | % rho(t)=exp(-t/lam^2); 5 | % 6 | % Computation of rho(x^2/2) (ie opt==0), rho'(x^2/2) (ie opt==1) and 7 | % rho"(x^2/2) (ie opt==2) 8 | % 9 | % Input : 10 | % x : a matrix 11 | % opt : a integer 12 | % sig : vector with kernel bandwidths 13 | % 14 | % Output : 15 | % r : matrix of the size of x 16 | % Author : B. Charlier (2017) 17 | 18 | r=zeros(size(x)); 19 | 20 | 21 | 22 | switch lower(objfun.kernel_geom) 23 | case 'gaussian' 24 | 25 | for l=objfun.kernel_size_geom 26 | if derivative_order==0 27 | r=r + exp(-x/l^2); 28 | elseif derivative_order==1 29 | r=r -exp(-x/l^2)/l^2; 30 | end 31 | end 32 | 33 | case 'cauchy' 34 | 35 | for l=objfun.kernel_size_geom 36 | if derivative_order==0 37 | r=r + 1 ./ (1 + (x/l^2)); 38 | elseif derivative_order==1 39 | r=r -1 ./ (l^2 * (1 + (x/l^2)) .^2); 40 | end 41 | end 42 | 43 | 44 | end 45 | 46 | end 47 | -------------------------------------------------------------------------------- /LDDMM_Python/lddmm_python/modules/manifolds/torus.py: -------------------------------------------------------------------------------- 1 | from pylab import * 2 | from .surface_of_revolution import SurfaceOfRevolution 3 | 4 | class Torus(SurfaceOfRevolution) : 5 | def __init__(self, a=2, b=1, vis_mode='3D') : 6 | """A Torus, seen as a Riemannian Manifold. 7 | 8 | Arguments : 9 | a -- radius of the donut 10 | b -- radius of its section 11 | vis_mode -- '2D', '3D' : mode for displaying results 12 | """ 13 | R = lambda r : a + b * cos(r / b) 14 | Rp = lambda r : -sin(r / b) 15 | Rpp = lambda r : - cos(r / b) / b 16 | Z = lambda r : b * sin(r / b) 17 | Zp = lambda r : cos(r / b) 18 | 19 | D = array([[-b*pi,b*pi], 20 | [-pi, pi ]]) 21 | 22 | SurfaceOfRevolution.__init__(self, R, Rp, Rpp, Z, Zp, D, vis_mode) 23 | 24 | self.a = a 25 | self.b = b 26 | 27 | 28 | """ Projection & Distances """ 29 | def projection_onto(self, X) : 30 | """Orthogonal projection from R^3 to the torus.""" 31 | x = X[:,0] 32 | y = X[:,1] 33 | z = X[:,2] 34 | Theta = angle(x + 1j * y) 35 | Pl = sqrt(x**2 + y**2) - self.a 36 | Xhi = angle( Pl + 1j * z) 37 | r = Xhi / self.b 38 | return vstack((r , Theta)) 39 | def squared_distance_from(self, Xt) : 40 | """.5*(d(Xt, Torus)^2) from R^3 to the torus.""" 41 | Q = self.projection_onto(Xt) 42 | X = self.I(q = Q) 43 | return .5*sum( (Xt - X)**2, 1) 44 | 45 | -------------------------------------------------------------------------------- /matlab/Bin/optim/hanso (third party)/isposreal.m: -------------------------------------------------------------------------------- 1 | function ipr = isposreal(x) 2 | % return true if x is a positive real scalar, false otherwise 3 | % 4 | % Send comments/bug reports to Michael Overton, overton@cs.nyu.edu, 5 | % with a subject header containing the string "hanso". 6 | % Version 2.0, 2010, see GPL license info below. 7 | 8 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 9 | %% HANSO 2.0 Copyright (C) 2010 Michael Overton 10 | %% This program is free software: you can redistribute it and/or modify 11 | %% it under the terms of the GNU General Public License as published by 12 | %% the Free Software Foundation, either version 3 of the License, or 13 | %% (at your option) any later version. 14 | %% 15 | %% This program is distributed in the hope that it will be useful, 16 | %% but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | %% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | %% GNU General Public License for more details. 19 | %% 20 | %% You should have received a copy of the GNU General Public License 21 | %% along with this program. If not, see . 22 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 23 | 24 | if ~isscalar(x) 25 | ipr = 0; 26 | else % following is OK since x is scalar 27 | ipr = isreal(x) & x > 0; 28 | end -------------------------------------------------------------------------------- /matlab/Bin/optim/hanso (third party)/isposint.m: -------------------------------------------------------------------------------- 1 | function ipi = isposint(x) 2 | % return true if x is a positive integer, false otherwise 3 | % 4 | % Send comments/bug reports to Michael Overton, overton@cs.nyu.edu, 5 | % with a subject header containing the string "hanso". 6 | % Version 2.0, 2010, see GPL license info below. 7 | 8 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 9 | %% HANSO 2.0 Copyright (C) 2010 Michael Overton 10 | %% This program is free software: you can redistribute it and/or modify 11 | %% it under the terms of the GNU General Public License as published by 12 | %% the Free Software Foundation, either version 3 of the License, or 13 | %% (at your option) any later version. 14 | %% 15 | %% This program is distributed in the hope that it will be useful, 16 | %% but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | %% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | %% GNU General Public License for more details. 19 | %% 20 | %% You should have received a copy of the GNU General Public License 21 | %% along with this program. If not, see . 22 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 23 | 24 | if ~isscalar(x) 25 | ipi = 0; 26 | else % following is OK since x is scalar 27 | ipi = isreal(x) & round(x) == x & x > 0; 28 | end -------------------------------------------------------------------------------- /matlab/Bin/norms/deformations/scalarProductRkhsV.m: -------------------------------------------------------------------------------- 1 | function res=scalarProductRkhsV(p1,x,defo,p2) 2 | % res=SCALARPRODUCTRKHSV(p1,x,defo,p2) implements the scalar 3 | % product (p,K(x,x)p)/2 where the kernel size is given by 4 | % defo.kernel_size_mom. Several method are implemented (cuda, matlab...) 5 | % 6 | % scalarProductRkhsV(p1,x,defo) is equivalent to scalarProductRkhsV(p1,x,defo,p1) 7 | % that is returns the norm squared of p1. 8 | % 9 | % Inputs : 10 | % p1 : is a n x d matrix containing initial momenta 11 | % x : is a n x d matrix containing positions 12 | % defo : structure containing the parameters of deformations 13 | % p2 : is a n x d matrix containing initial momenta 14 | % 15 | % Output : 16 | % res : is a real number (scalar product) 17 | % 18 | % See also : dnormRkhsV 19 | % Author : B. Charlier (2017) 20 | 21 | 22 | if nargin == 3 23 | p2=p1; 24 | end 25 | 26 | [n,d] = size(x); 27 | 28 | switch defo.method 29 | case 'cuda' 30 | 31 | res=0; 32 | for sig=defo.kernel_size_mom 33 | res= res + sum(sum(GaussGpuConv(x',x',p2',sig)' .* p1)); 34 | end 35 | 36 | otherwise 37 | 38 | % Calcul de A=exp(-|x_i -x_j|^2/(2*lam^2)) 39 | S=zeros(n); 40 | for l=1:d 41 | S=S+(repmat(x(:,l),1,n)-repmat(x(:,l)',n,1)).^2; 42 | end 43 | res=trace(p1' * rho(S,0,defo.kernel_size_mom) * p2); 44 | end 45 | 46 | 47 | end 48 | -------------------------------------------------------------------------------- /matlab/Bin/norms/common/fcatoms.m: -------------------------------------------------------------------------------- 1 | function [X,Xi] = fcatoms(pts,tri) 2 | % [X,tf,Xi] = FCATOMS(pts,f,tri,signal_type) compute the dirac representation of meshes (1D or 2D) 3 | % 4 | % Input : 5 | % pts : matrix with vertices (one column per dimension, matrix nxd) 6 | % tri : connectivity matrix. if tri is of size (M x 2) this is a 1d current 7 | % (so each line of tri contains the two indexes of the points defining 8 | % an oriented segment), if tri is (M x 3) this to be considered 9 | % as a 2d current (so each line of tri contains the three indexes of 10 | % the points defining an oriented triangle). 11 | % f : column vector of functional values (n x1) 12 | % signal_type : optional string. If type_signal=='face', f is assumed to be 13 | % the values of the signal at the center of the faces else f is assumed to 14 | % be the values of the signal at the vertices (ie pts) 15 | % 16 | % Output 17 | % X : the matrix of the centers of the faces (M x d) 18 | % Xi: is the matric of p-vectors (tangent (1d current) or normal 2d current) (M x 2 or 3) 19 | % Author : B. Charlier (2017) 20 | 21 | 22 | [T,M]=size(tri); 23 | d = size(pts,2); 24 | 25 | %normals 26 | m = factorial(M-1); 27 | Xi = pVectors(pts,tri) / m; % normals or tangent vectors 28 | 29 | %centers 30 | if M==1 31 | X = pts; 32 | else 33 | X=sum(reshape(pts(tri(:),:)',d,T,M ),3)'/M; % center of the faces 34 | end 35 | 36 | end 37 | 38 | -------------------------------------------------------------------------------- /matlab/Bin/optim/hanso (third party)/isnonnegint.m: -------------------------------------------------------------------------------- 1 | function inni = isnonnegint(x) 2 | % return true if x is a nonnegative integer, false otherwise 3 | % 4 | % Send comments/bug reports to Michael Overton, overton@cs.nyu.edu, 5 | % with a subject header containing the string "hanso". 6 | % Version 2.0, 2010, see GPL license info below. 7 | 8 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 9 | %% HANSO 2.0 Copyright (C) 2010 Michael Overton 10 | %% This program is free software: you can redistribute it and/or modify 11 | %% it under the terms of the GNU General Public License as published by 12 | %% the Free Software Foundation, either version 3 of the License, or 13 | %% (at your option) any later version. 14 | %% 15 | %% This program is distributed in the hope that it will be useful, 16 | %% but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | %% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | %% GNU General Public License for more details. 19 | %% 20 | %% You should have received a copy of the GNU General Public License 21 | %% along with this program. If not, see . 22 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 23 | if ~isscalar(x) 24 | inni = 0; 25 | else % following is OK since x is scalar 26 | inni = (isreal(x) & round(x) == x & x >= 0); 27 | end 28 | -------------------------------------------------------------------------------- /matlab/Bin/optim/hanso (third party)/isnaninf.m: -------------------------------------------------------------------------------- 1 | function ini = isnaninf(M) 2 | % returns the scalar 1 if ANY entry of M is nan or inf; 0 otherwise 3 | % note: isnan and isinf return matrices if M is a matrix, and 4 | % if treats [0 1] as false, not true. 5 | % ini = sum(sum(isnan(M))) > 0 | sum(sum(isinf(M))) > 0; 6 | ini = any(any(isnan(M))) | any(any(isinf(M))); 7 | % 8 | % Send comments/bug reports to Michael Overton, overton@cs.nyu.edu, 9 | % with a subject header containing the string "hanso". 10 | % Version 2.0, 2010, see GPL license info below. 11 | 12 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 13 | %% HANSO 2.0 Copyright (C) 2010 Michael Overton 14 | %% This program is free software: you can redistribute it and/or modify 15 | %% it under the terms of the GNU General Public License as published by 16 | %% the Free Software Foundation, either version 3 of the License, or 17 | %% (at your option) any later version. 18 | %% 19 | %% This program is distributed in the hope that it will be useful, 20 | %% but WITHOUT ANY WARRANTY; without even the implied warranty of 21 | %% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 | %% GNU General Public License for more details. 23 | %% 24 | %% You should have received a copy of the GNU General Public License 25 | %% along with this program. If not, see . 26 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 27 | 28 | -------------------------------------------------------------------------------- /matlab/Bin/optim/perform_bfgs.m: -------------------------------------------------------------------------------- 1 | function [x,summary] = perform_bfgs(Grad, x, options) 2 | 3 | % perform_bfgs - wrapper to HANSO code 4 | % 5 | % [f, R, info] = perform_bfgs(Grad, f, options); 6 | % 7 | % Grad should return (value, gradient) 8 | % f is an initialization 9 | % options.niter is the number of iterations. 10 | % options.bfgs_memory is the memory for the hessian bookeeping. 11 | % R is filled using options.repport which takes as input (f,val). 12 | % Author : B. Charlier (2017) 13 | 14 | 15 | n = length(x); 16 | pars.nvar = n; 17 | pars.fgname = @(f,pars) eval([Grad,'(f)']); 18 | 19 | options.x0 = x; 20 | 21 | tstart = tic; 22 | [x, energy, ~, ~, iter, info, ~, ~, ~, fevalrec, xrec, ~] = bfgs(pars,options); 23 | 24 | 25 | info_exit = {'tolerance on smallest vector in convex hull of saved gradients met',... 26 | 'max number of iterations reached',... 27 | 'f reached target value',... 28 | 'norm(x) exceeded limit',... 29 | 'cpu time exceeded limit',... 30 | 'f is inf or nan at initial point',... 31 | 'direction not a descent direction due to rounding error',... 32 | 'line search bracketed minimizer but Wolfe conditions not satisfied',... 33 | 'line search did not bracket minimizer: f may be unbounded below'}; 34 | 35 | 36 | summary.bfgs.list_of_energy = [fevalrec{1}(1),cellfun(@(x) x(end), fevalrec)]; 37 | summary.bfgs.exit_flags=info_exit{info+1}; 38 | summary.bfgs.nb_of_iterations=iter; 39 | summary.bfgs.computation_time = toc(tstart); 40 | summary.bfgs.xrec = xrec; 41 | 42 | 43 | end 44 | -------------------------------------------------------------------------------- /matlab/Bin/norms/common/pVectors.m: -------------------------------------------------------------------------------- 1 | function res = pVectors(pts,tri) 2 | % computes (a representation of) the p-vector (ie tangent vector for curve and normals for surfaces). 3 | % 4 | % Input: 5 | % pts: list of vertices (n x d matrix) 6 | % tri: list of edges (T x M matrix of indices) 7 | % 8 | % Output: 9 | % res: list of p-vectors (d x M matrix) 10 | % Author : B. Charlier (2017) 11 | 12 | 13 | M = size(tri,2); 14 | d = size(pts,2); 15 | 16 | if (M==2) % curves 17 | 18 | res=pts(tri(:,2),:)-pts(tri(:,1),:); 19 | 20 | elseif (M==3) && (d==3) % surfaces 21 | 22 | u=pts(tri(:,2),:)-pts(tri(:,1),:); 23 | v=pts(tri(:,3),:)-pts(tri(:,1),:); 24 | 25 | res =[u(:,2).*v(:,3)-u(:,3).*v(:,2),... 26 | u(:,3).*v(:,1)-u(:,1).*v(:,3),... 27 | u(:,1).*v(:,2)-u(:,2).*v(:,1)]; 28 | 29 | elseif (M==1) % points 30 | 31 | res = repmat( 1./size(tri,1) ,size(tri,1),1) ; 32 | 33 | elseif (M==3) && (d==2)% simplexes 34 | 35 | u=pts(tri(:,2),:)-pts(tri(:,1),:); 36 | v=pts(tri(:,3),:)-pts(tri(:,1),:); 37 | 38 | res = u(:,1).*v(:,2) - u(:,2).*v(:,1); 39 | 40 | elseif (M==4) && (d==3)% simplexes 41 | 42 | u=pts(tri(:,2),:)-pts(tri(:,1),:); 43 | v=pts(tri(:,3),:)-pts(tri(:,1),:); 44 | w=pts(tri(:,4),:)-pts(tri(:,1),:); 45 | 46 | res = u(:,1).*v(:,2).*w(:,3) + v(:,1).*w(:,2).*u(:,3) + w(:,1).*u(:,2).*v(:,3)... 47 | - u(:,3).*v(:,2).*w(:,1) - v(:,3).*w(:,2).*u(:,1) - w(:,3).*u(:,2).*v(:,1); %det with Sarrus formula 48 | 49 | end 50 | 51 | end 52 | -------------------------------------------------------------------------------- /matlab/Bin/io/export_mom_vtk.m: -------------------------------------------------------------------------------- 1 | function []=export_mom_vtk(pos,mom,fname,encod_type) 2 | % Author : B. Charlier (2017) 3 | 4 | if nargin ==3 5 | encod_type = 'ascii'; 6 | end 7 | 8 | if size(pos,2)<=2 9 | pos = [pos,zeros(size(pos,1),3-size(pos,2))]; 10 | end 11 | 12 | if size(mom,2)<=2 13 | mom = [mom,zeros(size(mom,1),3-size(mom,2))]; 14 | end 15 | 16 | 17 | nb_points = size(mom,1); 18 | 19 | fid = fopen(fname, 'w'); 20 | 21 | 22 | %------------- 23 | % header 24 | %------------- 25 | 26 | %ASCII file header 27 | fprintf(fid, '# vtk DataFile Version 3.0\n'); 28 | fprintf(fid, 'VTK from fshapesTk\n'); 29 | if strcmp(encod_type,'ascii') 30 | fprintf(fid, 'ASCII\n\n'); 31 | else 32 | fprintf(fid, 'BINARY\n\n'); 33 | end 34 | 35 | %------------- 36 | % Position 37 | %------------- 38 | 39 | %ASCII sub header 40 | fprintf(fid, 'DATASET STRUCTURED_GRID\n'); 41 | fprintf(fid, ['DIMENSIONS ',num2str(nb_points),' 1 1\n']); 42 | %Record position 43 | fprintf(fid, ['POINTS ',num2str(nb_points),' float\n']); 44 | if strcmp(encod_type,'ascii') 45 | fprintf(fid,'%G %G %G\n',pos'); 46 | else 47 | fwrite(fid,pos','float','b'); 48 | end 49 | 50 | %------------- 51 | % vectors 52 | %------------- 53 | 54 | %ASCII sub header 55 | fprintf(fid, ['\nPOINT_DATA ',num2str(nb_points),'\n']); 56 | %Record vectors 57 | fprintf(fid, 'VECTORS momentum float\n'); 58 | if strcmp(encod_type,'ascii') 59 | fprintf(fid,'%G %G %G\n',mom'); 60 | else 61 | fwrite(fid, mom','float','b'); 62 | end 63 | 64 | fclose(fid); 65 | 66 | fprintf('\nFile saved in %s',fname) 67 | 68 | end 69 | -------------------------------------------------------------------------------- /matlab/Bin/norms/deformations/dnormRkhsV.m: -------------------------------------------------------------------------------- 1 | function [dx,dp]=dnormRkhsV(x,p,defo) 2 | % [dx,dp]=DNORMrKHSV(x,p,defo) computes the gradient of (p,K(x,x)p)/2 wrt 3 | % x and p. The kernel size is given by defo.kernel_size_mom. 4 | % Several method are implemented (cuda, matlab...) 5 | % 6 | % Inputs : 7 | % x : is a n x d matrix containing positions 8 | % p : is a n x d matrix containing momentums 9 | % defo : structure containing the parameters of deformations 10 | % 11 | % Output : 12 | % dx : is a (n x d) column vector 13 | % dp : is a (n x d) column vector 14 | % 15 | % See also : scalarProductRkhsV 16 | % Author : B. Charlier (2017) 17 | 18 | 19 | [n,d] = size(x); 20 | 21 | switch defo.method 22 | case 'cuda' 23 | 24 | dx=zeros(n,d); 25 | dp=zeros(n,d); 26 | for t=size(defo.kernel_size_mom,2) 27 | dx = dx + GaussGpuGrad1Conv(p',x',x',p',defo.kernel_size_mom(t))'; 28 | dp = dp + GaussGpuConv(x',x',p',defo.kernel_size_mom(t))'; 29 | end 30 | 31 | otherwise 32 | 33 | % Calcul de A=exp(-|x_i -x_j|^2/(2*lam^2)) 34 | dx=zeros(n,d); 35 | dp=zeros(n,d); 36 | S=zeros(n); 37 | pp=zeros(n); 38 | for l=1:d 39 | S=S+(repmat(x(:,l),1,n)-repmat(x(:,l)',n,1)).^2; 40 | pp=pp+p(:,l)*p(:,l)'; 41 | end 42 | A=rho(S,0,defo.kernel_size_mom); 43 | B=2*rho(S,1,defo.kernel_size_mom).*pp; 44 | 45 | for r=1:d 46 | dx(:,r)=sum(B.*(repmat(x(:,r),1,n)-repmat(x(:,r)',n,1)),2); 47 | dp(:,r)=A*p(:,r); 48 | end 49 | end 50 | end 51 | 52 | -------------------------------------------------------------------------------- /matlab/Bin/optim/hanso (third party)/hgprod.m: -------------------------------------------------------------------------------- 1 | function r = hgprod(H0, g, S, Y) 2 | % compute the product required by the LM-BFGS method 3 | % see Nocedal and Wright 4 | % Send comments/bug reports to Michael Overton, overton@cs.nyu.edu, 5 | % with a subject header containing the string "hanso" or "gradsamp". 6 | % Version 2.0, 2010, see GPL license info below. 7 | 8 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 9 | %% HANSO 2.0 Copyright (C) 2010 Michael Overton 10 | %% This program is free software: you can redistribute it and/or modify 11 | %% it under the terms of the GNU General Public License as published by 12 | %% the Free Software Foundation, either version 3 of the License, or 13 | %% (at your option) any later version. 14 | %% 15 | %% This program is distributed in the hope that it will be useful, 16 | %% but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | %% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | %% GNU General Public License for more details. 19 | %% 20 | %% You should have received a copy of the GNU General Public License 21 | %% along with this program. If not, see . 22 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 23 | 24 | N = size(S,2); % number of saved vector pairs (s,y) 25 | q = g; 26 | for i = N:-1:1 27 | s = S(:,i); 28 | y = Y(:,i); 29 | rho(i) = 1/(s'*y); 30 | alpha(i) = rho(i)*(s'*q); 31 | q = q - alpha(i)*y; 32 | end 33 | r = H0*q; 34 | for i=1:N 35 | s = S(:,i); 36 | y = Y(:,i); 37 | beta = rho(i)*(y'*r); 38 | r = r + (alpha(i)-beta)*s; 39 | end 40 | -------------------------------------------------------------------------------- /LDDMM_Python/lddmm_python/modules/models/frechet_mean.py: -------------------------------------------------------------------------------- 1 | from pylab import * 2 | from pprint import pprint 3 | import plotly.graph_objs as go 4 | 5 | from .model import Model 6 | 7 | class FrechetMean(Model): 8 | """Simple Frechet Mean - L2 or L1 depending on the cost function 9 | N.B.: this is a Frechet mean according to the "embedding" metric. 10 | To get an intrinsic Frechet mean, with geodesic distance, 11 | one needs to solve an atlas estimation problem.""" 12 | def __init__(self, M, C, nobs, s, Q0 = array([0,0])) : 13 | Model.__init__(self, M, C, nobs, s) 14 | self.Q0 = Q0 15 | 16 | def training_step(self, Xt) : 17 | (C, dQ) = self.C(vstack((self.Q0,)*Xt.shape[1]).T, Xt) # Compute gradients 18 | dQ = - self.s * mean(dQ, 1) # Rescale and Aggregate 19 | self.Q0 = self.Q0 + dQ # Update 20 | 21 | # Display 22 | self.M.marker(self.Q0, marker = dict(size = 20, color='red'), name='Frechet Mean', visible=False) 23 | self.show_data_attachment(C) # 'Targets' + 'Distances' 24 | 25 | # We use a simple hide/show scheme for the plot updates 26 | frame = [dict(visible = False), dict(visible = True)] 27 | return (self.Q0,C,dQ, frame) 28 | def situation(self, Xt) : 29 | Q = vstack((self.Q0,)*Xt.shape[1]).T 30 | (C, dQ) = self.C(Q, Xt) 31 | return (Q,C,dQ) 32 | def get_frame(self, f) : 33 | # Three plotly traces per frame : 'Frechet Mean', 'Targets', 'Distances' 34 | list1 = str([ 1 + 3*self.current_frame, 2 + 3*self.current_frame, 3 + 3*self.current_frame])[1:-1] 35 | self.current_frame = f 36 | list2 = str([ 1 + 3*self.current_frame, 2 + 3*self.current_frame, 3 + 3*self.current_frame])[1:-1] 37 | return (self.frames[f] , [list1, list2]) 38 | -------------------------------------------------------------------------------- /LDDMM_Python/lddmm_python/lib/plotly/files.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | # file structure 4 | PLOTLY_DIR = os.path.join(os.path.expanduser("~"), ".plotly") 5 | CREDENTIALS_FILE = os.path.join(PLOTLY_DIR, ".credentials") 6 | CONFIG_FILE = os.path.join(PLOTLY_DIR, ".config") 7 | GRAPH_REFERENCE_FILE = os.path.join(PLOTLY_DIR, ".graph_reference") 8 | TEST_DIR = os.path.join(os.path.expanduser("~"), ".test") 9 | TEST_FILE = os.path.join(PLOTLY_DIR, ".permission_test") 10 | 11 | # this sets both the DEFAULTS and the TYPES for these files 12 | FILE_CONTENT = {CREDENTIALS_FILE: {'username': '', 13 | 'api_key': '', 14 | 'proxy_username': '', 15 | 'proxy_password': '', 16 | 'stream_ids': []}, 17 | CONFIG_FILE: {'plotly_domain': 'https://plot.ly', 18 | 'plotly_streaming_domain': 'stream.plot.ly', 19 | 'plotly_api_domain': 'https://api.plot.ly', 20 | 'plotly_ssl_verification': True, 21 | 'plotly_proxy_authorization': False, 22 | 'world_readable': True, 23 | 'sharing': 'public', 24 | 'auto_open': True}} 25 | 26 | try: 27 | os.mkdir(TEST_DIR) 28 | os.rmdir(TEST_DIR) 29 | if not os.path.exists(PLOTLY_DIR): 30 | os.mkdir(PLOTLY_DIR) 31 | f = open(TEST_FILE, 'w') 32 | f.write('testing\n') 33 | f.close() 34 | os.remove(TEST_FILE) 35 | _file_permissions = True 36 | except: 37 | _file_permissions = False 38 | 39 | 40 | def check_file_permissions(): 41 | return _file_permissions 42 | -------------------------------------------------------------------------------- /LDDMM_Python/lddmm_python/modules/io/level_lines.py: -------------------------------------------------------------------------------- 1 | from numpy import * 2 | from skimage.measure import find_contours 3 | from scipy import misc 4 | from scipy.ndimage.filters import gaussian_filter 5 | from scipy.interpolate import interp1d 6 | 7 | from ..manifolds.curves import Curve 8 | 9 | 10 | def arclength_param(line) : 11 | vel = line[1:, :] - line[:-1, :] 12 | vel = sqrt(sum( vel ** 2, 1 )) 13 | return hstack( ( [0], cumsum( vel, 0 ) ) ) 14 | def arclength(line) : 15 | return arclength_param(line)[-1] 16 | 17 | def resample(line, npoints) : 18 | s = arclength_param(line) 19 | f = interp1d(s, line, kind = 'linear', axis = 0, assume_sorted = True) 20 | 21 | t = linspace(0, s[-1], npoints) 22 | p = f(t) 23 | 24 | connec = vstack( (arange(0, len(p) - 1), arange(1, len(p)) ) ).T 25 | return (p, connec) 26 | 27 | def level_curves(fname, npoints, smoothing = 10, level = 0.5) : 28 | # Find the contour lines 29 | img = misc.imread(fname, flatten = True) # Grayscale 30 | img = img.T[:, ::-1] 31 | img = img / 255. 32 | img = gaussian_filter(img, smoothing, mode='nearest') 33 | lines = find_contours(img, level) 34 | 35 | # Compute the sampling ratio 36 | lengths = [] 37 | for line in lines : 38 | lengths.append( arclength(line) ) 39 | lengths = array(lengths) 40 | points_per_line = ceil( npoints * lengths / sum(lengths) ) 41 | 42 | # Interpolate accordingly 43 | points = [] 44 | connec = [] 45 | index_offset = 0 46 | for ppl, line in zip(points_per_line, lines) : 47 | (p, c) = resample(line, ppl) 48 | points.append(p) 49 | connec.append(c + index_offset) 50 | index_offset += len(p) 51 | 52 | points = vstack(points) 53 | connec = vstack(connec) 54 | return Curve(points.ravel(), connec, 2) # Dimension 2 ! 55 | 56 | -------------------------------------------------------------------------------- /matlab/Bin/kernels/cuda/kernels_old.cx~: -------------------------------------------------------------------------------- 1 | 2 | /////////////////////// 3 | // Gaussian Kernel // 4 | /////////////////////// 5 | 6 | 7 | template < typename TYPE > 8 | __device__ TYPE KernelGauss(TYPE *u, TYPE *v, TYPE ooSigma2, int DIM){ 9 | 10 | TYPE r2 = 0.0f; 11 | TYPE temp; 12 | // norm squared 13 | for(int k=0; k 26 | __device__ TYPE Kerneld1Gauss(TYPE *u, TYPE *v, TYPE ooSigma2, int l, int DIM){ 27 | 28 | TYPE r2 = 0.0f; 29 | TYPE temp; 30 | // norm squared 31 | for(int k=0; k 49 | __device__ TYPE KernelGaussVar(TYPE *u, TYPE *v, TYPE ooSigma2, int DIM){ 50 | 51 | TYPE temp; 52 | 53 | // norm(u) squared 54 | TYPE normu2 = 0.0f; 55 | for(int k=0; k 9 | __device__ TYPE KernelGauss(TYPE *u, TYPE *v, TYPE ooSigma2, int DIM){ 10 | 11 | TYPE r2 = 0.0f; 12 | TYPE temp; 13 | // norm squared 14 | for(int k=0; k 27 | __device__ TYPE Kerneld1Gauss(TYPE *u, TYPE *v, TYPE ooSigma2, int l, int DIM){ 28 | 29 | TYPE r2 = 0.0f; 30 | TYPE temp; 31 | // norm squared 32 | for(int k=0; k 50 | __device__ TYPE KernelGaussVar(TYPE *u, TYPE *v, TYPE ooSigma2, int DIM){ 51 | 52 | TYPE temp; 53 | 54 | // norm(u) squared 55 | TYPE normu2 = 0.0f; 56 | for(int k=0; k' 52 | display(HTML(html)) 53 | -------------------------------------------------------------------------------- /Simple_script/test_pytorch.py: -------------------------------------------------------------------------------- 1 | # Import the relevant tools 2 | import time # to measure performance 3 | import numpy as np # standard array library 4 | import torch 5 | from torch.autograd import Variable 6 | import torch.optim as optim 7 | 8 | 9 | use_cuda = torch.cuda.is_available() 10 | dtype = torch.cuda.FloatTensor if use_cuda else torch.FloatTensor 11 | 12 | 13 | 14 | def _squared_distances(x, y) : 15 | "Returns the matrix of $\|x_i-y_j\|^2$." 16 | x_col = x.unsqueeze(1) #x.dimshuffle(0, 'x', 1) 17 | y_lin = y.unsqueeze(0) #y.dimshuffle('x', 0, 1) 18 | return torch.sum( (x_col - y_lin)**2 , 2 ) 19 | 20 | def _k(x, y, s) : 21 | "Returns the matrix of k(x_i,y_j)." 22 | sq = _squared_distances(x, y) / (s**2) 23 | return torch.exp(-sq) #torch.pow( 1. / ( 1. + sq ), .25 ) 24 | 25 | def _cross_kernels(q, x, s) : 26 | "Returns the full k-correlation matrices between two point clouds q and x." 27 | K_qq = _k(q, q, s) 28 | K_qx = _k(q, x, s) 29 | K_xx = _k(x, x, s) 30 | return (K_qq, K_qx, K_xx) 31 | 32 | def _Hqp(q, p, sigma) : 33 | "The hamiltonian, or kinetic energy of the shape q with momenta p." 34 | pKqp = _k(q, q, sigma) * (p @ p.t()) # Use a simple isotropic kernel 35 | return .5 * pKqp.sum() # $H(q,p) = \frac{1}{2} * sum_{i,j} k(x_i,x_j) p_i.p_j$ 36 | 37 | 38 | # Part 2 : Geodesic shooting ==================================================================== 39 | # The partial derivatives of the Hamiltonian are automatically computed ! 40 | def _dq_Hqp(q,p,sigma) : 41 | return torch.autograd.grad(_Hqp(q,p,sigma), q, create_graph=True)[0] 42 | def _dp_Hqp(q,p,sigma) : 43 | return torch.autograd.grad(_Hqp(q,p,sigma), p, create_graph=True)[0] 44 | 45 | 46 | q0 = Variable(torch.from_numpy( Q0.points ).type(dtype), requires_grad=False) 47 | p0 = Variable(torch.from_numpy( 0.*Q0.points ).type(dtype), requires_grad=True ) 48 | s = Variable(torch.from_numpy( 1.).type(dtype), requires_grad=False) 49 | 50 | _dp_Hqp(q,p,1.) 51 | 52 | -------------------------------------------------------------------------------- /matlab/Bin/models/atlas/tan_free/enr_tan_free.m: -------------------------------------------------------------------------------- 1 | function [ENR,dist,penp] = enr_tan_free(templatex,momentums) 2 | % enr_tan_free(templatex,momentum) computes the energy functional 3 | % in the tangential and free framework. 4 | % 5 | % Input : 6 | % templatex : cell with the points position 7 | % momentums : cell with the momentums attached to each point 8 | % 9 | %Output : 10 | % ENR: energy (a number) 11 | % dist,penp : terms composing the energy 12 | % Author : B. Charlier (2017) 13 | 14 | 15 | global data objfunc defoc deflag templateG 16 | 17 | tstart =tic; 18 | 19 | %--------------- 20 | % indiv. terms 21 | %--------------- 22 | 23 | [nb_obs,nb_match] = size(data); 24 | 25 | enrg = zeros(nb_obs,1); 26 | enru = zeros(nb_obs,1); 27 | 28 | templatextotal = cell2mat(templatex'); 29 | 30 | for sh_ind=1:nb_obs %parallel computations 31 | 32 | %sliced variable in parfor 33 | datac = data(sh_ind,:); 34 | momentumc = momentums{sh_ind}; 35 | 36 | % compute the energy of the deformation 37 | enru(sh_ind) = objfunc{1}.weight_coef_pen_p *objfunc{1}.mC*scalarProductRkhsV(momentumc,templatextotal,defoc); % objfunc{1}.mC est commun! 38 | 39 | % shoot the template 40 | [shootingx,~]=forward_tan(templatextotal,momentumc,defoc); 41 | 42 | for l = 1:nb_match 43 | 44 | %load the deformed fshape number l (== final position) 45 | templatefinal= struct('x',shootingx{end}(deflag(l)+1:deflag(l+1),:),'G',templateG{l}); 46 | 47 | %load current target 48 | targetc = struct('x',datac{l}.x,'G',datac{l}.G); 49 | 50 | enrg(sh_ind) = enrg(sh_ind) + objfunc{l}.weight_coef_dist * objfunc{l}.gC * matchterm(templatefinal,targetc,objfunc{l}); 51 | 52 | end 53 | end 54 | 55 | 56 | %--------------- 57 | % Energy term 58 | %--------------- 59 | 60 | dist=sum(enrg); 61 | penp=sum(enru); 62 | ENR = penp + dist ; 63 | 64 | if nargout ==1 65 | fprintf('enr %4.2e: dist %4.2e, pen_p %4.2e, time %f\n', ENR, dist,penp,toc(tstart)) 66 | end 67 | 68 | end 69 | -------------------------------------------------------------------------------- /matlab/Bin/norms/shape/wasserstein/cost_varifold.m: -------------------------------------------------------------------------------- 1 | function res = cost_varifold(X,Y,weight) 2 | % This function compute the cost function used in the OT for discrete measure 3 | % composed with varifold Dirac mass. 4 | % 5 | % Input : 6 | % X is a discrete varifold measure : a d x 2n matrix where d is the dimension of 7 | % the ambient space and n is the number of points in the cloud. The first 8 | % n rows encode the position and en last n rows encode the orientation 9 | % Y : idem as X. 10 | % 11 | % Output : 12 | % res : a nx x ny matrix of positive real numbers. 13 | % Author : B. Charlier (2017) 14 | 15 | 16 | [d,nx] = size(X);%nx = nx/2; 17 | [~,ny] = size(Y);%ny = ny/2; 18 | 19 | d = d/2; %dimension ambient space 20 | 21 | %------------------% 22 | %-Cost on position-% 23 | %------------------% 24 | 25 | % C(x,y)=1/2*|x-y|^2 26 | nablaC1 = @(x,y)repmat(x,[1 1 size(y,2)]) - ... 27 | repmat(reshape(y,[size(y,1) 1 size(y,2)]),[1 size(x,2)]); 28 | C1 = @(x,y)squeeze( sum(nablaC1(x,y).^2)/2 ); 29 | 30 | 31 | %---------------------% 32 | %-Cost on orientation-% 33 | %---------------------% 34 | 35 | normalsX = X(d+1:2*d,:)'; 36 | normalsY = Y(d+1:2*d,:)'; 37 | 38 | % Compute unit normals 39 | norm_normalsX = sqrt(sum(normalsX .^2,2)); 40 | norm_normalsY = sqrt(sum(normalsY .^2,2)); 41 | 42 | unit_normalsX = normalsX ./ repmat(norm_normalsX,1,size(normalsX,2)); 43 | unit_normalsY = normalsY ./ repmat(norm_normalsY,1,size(normalsY,2)); 44 | 45 | prs_unit_norm = zeros(nx,ny); 46 | for l=1:d 47 | prs_unit_norm = prs_unit_norm + (repmat(unit_normalsX(:,l),1,ny).*repmat(unit_normalsY(:,l)',nx,1)); 48 | end 49 | 50 | 51 | % unoriented : 52 | %C2 = (2 - 2 * prs_unit_norm .^2); 53 | 54 | % oriented : 55 | C2 = (1 - prs_unit_norm) ; 56 | 57 | %--------% 58 | %-Result-% 59 | %--------% 60 | 61 | % canonical metric (c1 + c2) 62 | res = weight(1) * C1(X(1:d,:) ,Y(1:d,:) ) + weight(2) * C2; 63 | 64 | % Other pseudo metric tricks... (c1 + c1 * c2) 65 | %res = C1(X(1:d,:) ,Y(1:d,:) ) .* (1 + weight(2) * C2) ; 66 | 67 | end 68 | -------------------------------------------------------------------------------- /matlab/Bin/deformations/tangential/forward_tan.m: -------------------------------------------------------------------------------- 1 | function [x_evol,p_evol]=forward_tan(x_init,p_init,defo,tf) 2 | % [x_evol,p_evol]=FORWARD(x_init,p_init,defo,final_time) compute 3 | % Forward integration of the Hamiltonian flow from initial coupled 4 | % configuration of points/momentums. 5 | % 6 | % Input : 7 | % x_init : initial coordinates of the points (position) in a (n x d) matrix. 8 | % p_init : initial momentums in a (n x d) matrix. 9 | % defo : structure containing the parameters of deformations (kernel_size_mom,method,nstep,...) 10 | % final_time : final time (optional, and fixed by default to 1) 11 | % 12 | % Output 13 | % x_evol : a cell list containing evolution path of positions ( points_evol{i} is a n x d matrix and i ranges from 1 to defo_options.nstep+1) 14 | % p_evol : a cell list containing evolution path of momentums ( nomentums_evol{i} is a n x d matrix and i ranges from 1 to defo_options.nstep+1) 15 | % 16 | % See also : backward_tan, dHr_tan, ddHrtP_tan 17 | % Author : B. Charlier (2017) 18 | 19 | 20 | if nargin == 3 21 | tf=1; 22 | end 23 | 24 | x_evol=cell(1,defo.nb_euler_steps+1); 25 | p_evol=cell(1,defo.nb_euler_steps+1); 26 | 27 | dt=tf/defo.nb_euler_steps; 28 | 29 | x_evol{1} =deal(x_init); 30 | p_evol{1} = deal(p_init); 31 | 32 | for i=1:defo.nb_euler_steps 33 | 34 | % Midpoint method 35 | [x2,p2]=fdh(x_evol{i},p_evol{i},defo,dt/2); 36 | [x3,p3]=fdh(x2,p2,defo,dt); 37 | 38 | x_evol{i+1} = x3 - x2 + x_evol{i}; 39 | p_evol{i+1} = p3 - p2 + p_evol{i}; 40 | 41 | end 42 | 43 | end 44 | 45 | function [nx,np]=fdh(x,p,defo,h) 46 | % This fonction implements an elementary Euler Step 47 | % 48 | % Inputs : 49 | % x: is a (n x d) matrix containing the points. 50 | % p: is a (n x d) matrix containing the momentums. 51 | % defo: is a structure of deformations. 52 | % h is the time step. 53 | 54 | % Outputs 55 | % nx : (n x d) matrix containing the new points. 56 | % np :(n x d) matrix containing the new the momentums. 57 | 58 | %here f = dHr 59 | [dp,dx]= dHr_tan(x,p,defo); 60 | 61 | nx=x+h*dx; 62 | np=p-h*dp; 63 | 64 | end 65 | -------------------------------------------------------------------------------- /matlab/Bin/optim/hanso (third party)/getbundle.m: -------------------------------------------------------------------------------- 1 | function [xbundle, gbundle] = getbundle(x, g, samprad, N, pars); 2 | % get bundle of N-1 gradients at points near x, in addition to g, 3 | % which is gradient at x and goes in first column 4 | % intended to be called by gradsampfixed 5 | % 6 | % Send comments/bug reports to Michael Overton, overton@cs.nyu.edu, 7 | % with a subject header containing the string "hanso" or "gradsamp". 8 | % Version 2.0, 2010, see GPL license info below. 9 | 10 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 11 | %% HANSO 2.0 Copyright (C) 2010 Michael Overton 12 | %% This program is free software: you can redistribute it and/or modify 13 | %% it under the terms of the GNU General Public License as published by 14 | %% the Free Software Foundation, either version 3 of the License, or 15 | %% (at your option) any later version. 16 | %% 17 | %% This program is distributed in the hope that it will be useful, 18 | %% but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | %% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | %% GNU General Public License for more details. 21 | %% 22 | %% You should have received a copy of the GNU General Public License 23 | %% along with this program. If not, see . 24 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 25 | 26 | m = length(x); 27 | xbundle(:,1) = x; 28 | gbundle(:,1) = g; 29 | for k = 2:N % note the 2 30 | xpert = x + samprad*(rand(m,1) - 0.5); % uniform distribution 31 | [f,grad] = feval(pars.fgname, xpert, pars); 32 | count = 0; 33 | while isnaninf(f) | isnaninf(grad) % in particular, disallow infinite function values 34 | xpert = (x + xpert)/2; % contract back until feasible 35 | [f,grad] = feval(pars.fgname, xpert, pars); 36 | count = count + 1; 37 | if count > 100 % should never happen, but just in case 38 | error('too many contractions needed to find finite f and grad values') 39 | end 40 | end; % discard function values 41 | xbundle(:,k) = xpert; 42 | gbundle(:,k) = grad; 43 | end 44 | -------------------------------------------------------------------------------- /matlab/Script/skulls/script_skulls_matching.m: -------------------------------------------------------------------------------- 1 | % Matching of two curves : Skulls dataset 2 | % Author : B. Charlier (2017) 3 | 4 | clear all 5 | restoredefaultpath 6 | addpath(genpath('../../Bin')) 7 | 8 | %----------------% 9 | % Data % 10 | %----------------% 11 | 12 | %choose a target 13 | hom = 'australopithecus'; 14 | hom = 'sapiens'; 15 | hom = 'erectus'; 16 | 17 | r =1; %the code should be scale invariant... 18 | 19 | target = import_fshape_vtk(['./Data/skull_',hom,'.vtk']); 20 | target.f = zeros(size(target.x,1),1); 21 | nu = sum(area(target.x,target.G)); 22 | target.x = r* target.x /nu; 23 | 24 | 25 | template = import_fshape_vtk('./Data/template.vtk') 26 | template.f = zeros(size(template.x,1),1); 27 | mu = sum(area(template.x,template.G)); 28 | template.x = r* template.x /mu; 29 | 30 | 31 | %------------------------------% 32 | % parameters % 33 | %------------------------------% 34 | 35 | comp_method = 'matlab';% possible values are 'cuda' or 'matlab' 36 | 37 | % Parameters for the deformations 38 | defo.kernel_size_mom = r*[.06,.03,.013]; % size of the kernel used to generate the deformations 39 | defo.nb_euler_steps =10; % nbr of steps in the (for||back)ward integration 40 | defo.method =comp_method; % possible values are 'cuda' or 'matlab' 41 | 42 | % Parameters for data attachment term 43 | objfun.weight_coef_dist = 10000; % weighting coeff in front of the fidelity term 44 | objfun.distance = 'wasserstein'; % OT fidelity 45 | objfun.wasserstein_distance.method=comp_method; 46 | objfun.wasserstein_distance.epsilon = .5*(r*.01/6)^2; 47 | objfun.wasserstein_distance.niter = 450; 48 | objfun.wasserstein_distance.tau = 0; % basic sinkhorn, no extrapolation (only matlab version) 49 | objfun.wasserstein_distance.rho = Inf; % balanced case 50 | objfun.wasserstein_distance.weight_cost_varifold = [1,0.001]; % weight on spatial and orientation distances 51 | 52 | % Parameters for optimization 53 | optim.method='bfgs' 54 | optim.bfgs.maxit=200; 55 | 56 | [momentums,summary]=match_geom(template,target,defo,objfun,optim); 57 | 58 | export_matching_tan(template,momentums,template.f,target,summary,['results/matching_',hom]) 59 | -------------------------------------------------------------------------------- /matlab/Bin/optim/hanso (third party)/gradsamp1run.m: -------------------------------------------------------------------------------- 1 | function [x, f, g, dnorm, X, G, w] = gradsamp1run(x0, f0, g0, pars, options); 2 | % repeatedly run gradient sampling minimization, for various sampling radii 3 | % return info only from final sampling radius 4 | % intended to be called by gradsamp only 5 | % 6 | % Send comments/bug reports to Michael Overton, overton@cs.nyu.edu, 7 | % with a subject header containing the string "hanso" or "gradsamp". 8 | % Version 2.0, 2010, see GPL license info below. 9 | 10 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 11 | %% HANSO 2.0 Copyright (C) 2010 Michael Overton 12 | %% This program is free software: you can redistribute it and/or modify 13 | %% it under the terms of the GNU General Public License as published by 14 | %% the Free Software Foundation, either version 3 of the License, or 15 | %% (at your option) any later version. 16 | %% 17 | %% This program is distributed in the hope that it will be useful, 18 | %% but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | %% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | %% GNU General Public License for more details. 21 | %% 22 | %% You should have received a copy of the GNU General Public License 23 | %% along with this program. If not, see . 24 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 25 | 26 | samprad = options.samprad; 27 | cpufinish = cputime + options.cpumax; 28 | for choice = 1:length(samprad) 29 | options.cpumax = cpufinish - cputime; % time left 30 | [x, f, g, dnorm, X, G, w, quitall] = ... 31 | gradsampfixed(x0, f0, g0, samprad(choice), pars, options); 32 | % it's not always the case that x = X(:,1), for example when the max 33 | % number of iterations is exceeded: this is mentioned in the 34 | % comments for gradsamp 35 | if quitall % terminate early 36 | return 37 | end 38 | % get ready for next run, with lower sampling radius 39 | x0 = x; % start from where previous one finished, 40 | % because this is lowest function value so far 41 | f0 = f; 42 | g0 = g; 43 | end 44 | -------------------------------------------------------------------------------- /LDDMM_Python/lddmm_python/lib/plotly/matplotlylib/mplexporter/renderers/vincent_renderer.py: -------------------------------------------------------------------------------- 1 | import warnings 2 | from .base import Renderer 3 | from ..exporter import Exporter 4 | 5 | 6 | class VincentRenderer(Renderer): 7 | def open_figure(self, fig, props): 8 | self.chart = None 9 | self.figwidth = int(props['figwidth'] * props['dpi']) 10 | self.figheight = int(props['figheight'] * props['dpi']) 11 | 12 | def draw_line(self, data, coordinates, style, label, mplobj=None): 13 | import vincent # only import if VincentRenderer is used 14 | if coordinates != 'data': 15 | warnings.warn("Only data coordinates supported. Skipping this") 16 | linedata = {'x': data[:, 0], 17 | 'y': data[:, 1]} 18 | line = vincent.Line(linedata, iter_idx='x', 19 | width=self.figwidth, height=self.figheight) 20 | 21 | # TODO: respect the other style settings 22 | line.scales['color'].range = [style['color']] 23 | 24 | if self.chart is None: 25 | self.chart = line 26 | else: 27 | warnings.warn("Multiple plot elements not yet supported") 28 | 29 | def draw_markers(self, data, coordinates, style, label, mplobj=None): 30 | import vincent # only import if VincentRenderer is used 31 | if coordinates != 'data': 32 | warnings.warn("Only data coordinates supported. Skipping this") 33 | markerdata = {'x': data[:, 0], 34 | 'y': data[:, 1]} 35 | markers = vincent.Scatter(markerdata, iter_idx='x', 36 | width=self.figwidth, height=self.figheight) 37 | 38 | # TODO: respect the other style settings 39 | markers.scales['color'].range = [style['facecolor']] 40 | 41 | if self.chart is None: 42 | self.chart = markers 43 | else: 44 | warnings.warn("Multiple plot elements not yet supported") 45 | 46 | 47 | def fig_to_vincent(fig): 48 | """Convert a matplotlib figure to a vincent object""" 49 | renderer = VincentRenderer() 50 | exporter = Exporter(renderer) 51 | exporter.run(fig) 52 | return renderer.chart 53 | -------------------------------------------------------------------------------- /matlab/Bin/models/matching/geom/match_geom.m: -------------------------------------------------------------------------------- 1 | function [momentums,summary]=match_geom(source,target,defo,objfun,optim) 2 | % [momentums,summary]=MATCH_GEOM(source,target,defo,objfun,optim) computes 3 | % a geometric matching of the shape source onto the shape target. 4 | % 5 | % Inputs: 6 | % source: a structure containing the source shape. 7 | % target : a structure containing the target shape. 8 | % defo: is a structure containing the parameters of the deformations. 9 | % objfun: is a structure containing the parameters of attachment term. 10 | % optim: is a structure containing the parameters of the optimization procedure (here gradient descent with adaptative step) 11 | % 12 | % Outputs: 13 | % momentums: a cell array with momentums 14 | % summary: is a structure containing various informations about the 15 | % gradient descent. 16 | % 17 | % See also : enr_geom, jnfmatch_geom 18 | % Author : B. Charlier (2017) 19 | 20 | global data 21 | 22 | %--------% 23 | % DATA % 24 | %--------% 25 | 26 | 27 | if ~iscell(target) 28 | data= {target}; 29 | else 30 | data = target; 31 | end 32 | 33 | [nb_obs,nb_match] = size(data); 34 | 35 | if nb_obs >1 36 | error('target must contain only 1 observation') 37 | end 38 | 39 | 40 | for i = 1:nb_obs 41 | for l=1:nb_match 42 | if ~isfield(data{i,l},'f') 43 | data{i,l}.f = zeros(size(data{i,l}.x,1),1); 44 | end 45 | end 46 | end 47 | 48 | %----------% 49 | % TEMPLATE % 50 | %----------% 51 | 52 | if ~iscell(source) 53 | source= {source}; 54 | end 55 | 56 | for l=1:nb_match 57 | if ~isfield(source{l},'f') 58 | source{l}.f = zeros(size(source{l}.x,1),1); 59 | end 60 | end 61 | 62 | fprintf('\n Performing a pure geometric matching \n') 63 | 64 | switch lower(optim.method) 65 | case 'bfgs' 66 | [momentums,summary]=jnfmatch_geom(source,[],defo,objfun,optim); 67 | 68 | case 'graddesc' 69 | 70 | % put the step size to 0 71 | optim.gradDesc.step_size_x = 0; 72 | optim.gradDesc.step_size_f = 0; 73 | optim.gradDesc.step_size_fr = 0; 74 | 75 | [~,momentums,~,summary]=jnfmean_tan_free(source,[],[],defo,objfun,optim); 76 | 77 | end 78 | 79 | end 80 | 81 | -------------------------------------------------------------------------------- /matlab/Bin/norms/shape/wasserstein/fshape_wasserstein_distance.m: -------------------------------------------------------------------------------- 1 | function g= fshape_wasserstein_distance(fs1,fs2,objfun) 2 | % FSHAPE_KERNEL_DISTANCE(templatefinal,target,objfun) computes kernel based 3 | % distances between fshapes. 4 | % 5 | % \sum_i\sum_j K_signal(f_i-g_j)^2) K_geom(-norm(x_i-y_j)^2) K_tan(angle(V_i,W_j)) 6 | % 7 | % Possible method are 'cuda' or 'matlab'. 8 | % 9 | % Inputs: 10 | % templatefinal : "fshape structure" containing the shooted template 11 | % target : "fshape structure" containing the target. 12 | % objfun : is a structure containing the data attachment term parameters (mandatory fields are : 'kernel_geom', 'kernel_signal' and 'kernel_grass' and the associated bandwidth) 13 | % Output 14 | % g : a real number. 15 | % Author : B. Charlier (2017) 16 | 17 | d=size(fs1.x,2); 18 | m=size(fs1.G,2)-1; 19 | 20 | % discretize the fshapes 21 | [center_faceX,normalsX]=fcatoms(fs1.x,fs1.G); 22 | [center_faceY,normalsY]=fcatoms(fs2.x,fs2.G); 23 | 24 | options = objfun.wasserstein_distance; 25 | 26 | if min(m, d-m) ==0 % for points clouds or simplexes dim or codim == 0 : some simplifications occurs 27 | 28 | x=center_faceX'; 29 | y=center_faceY'; 30 | 31 | mu = fs1.G; 32 | nu = fs2.G; 33 | 34 | %only needed for matlab version. See built-in function for cuda version. 35 | nablaC = @(x,y,~)repmat(x,[1 1 size(y,2)]) - ... 36 | repmat(reshape(y,[size(y,1) 1 size(y,2)]),[1 size(x,2)]); 37 | C = @(x,y,~)squeeze( sum(nablaC(x,y).^2)/2 );% C(x,y)=1/2*|x-y|^2 38 | 39 | elseif min(m,d-m) ==1 % for curves or surface dim or codim ==1; 40 | 41 | mu = area(fs1.x,fs1.G); 42 | nu = area(fs2.x,fs2.G); 43 | 44 | x=[center_faceX';normalsX']; 45 | y=[center_faceY';normalsY']; 46 | 47 | %only needed for matlab version. See built-in function for cuda version. 48 | C = @(X,Y) cost_varifold(X,Y,options.weight_cost_varifold); 49 | 50 | end 51 | 52 | 53 | switch lower(options.method) 54 | case 'matlab' 55 | 56 | [~,~,~,~,g,~] = sinkhorn_log(mu,nu,C(x,y),options.epsilon,options); 57 | g = g(end); 58 | case 'cuda' 59 | 60 | [~,~,~,g,~] = sinkhorn_log_cuda(mu,nu,x,y,options.epsilon,options); 61 | 62 | end 63 | 64 | end 65 | -------------------------------------------------------------------------------- /matlab/Bin/models/matching/tan/fsmatch_tan.m: -------------------------------------------------------------------------------- 1 | function [momentums,summary]=fsmatch_tan(source,target,defo,objfun,optim) 2 | % [momentums,funres,List_energy]=FSMATCH_TAN(source,target,defo,objfun,optim) 3 | % performs a geometrico-functional matching of the fshape "source" to the 4 | % fshape "target" in the tangential framework. 5 | % 6 | % Note: This function is a wrapper function as it simply call the low-level function jnfmeanMultiShape with 7 | % some particular parameters. 8 | % 9 | % Inputs: 10 | % source: is a structure containing the source fshape 11 | % target: is a structure containing the target fshape 12 | % defo: is a structure containing the parameters of the deformations. 13 | % objfun: is a structure containing the parameters of attachment term. 14 | % optim: is a structure containing the parameters of the optimization procedure 15 | % 16 | % Outputs: 17 | % momentums: is a matrix containing the momentums (geometric deformation). 18 | % funres: is a vector with the functional residuals (functional deformation). 19 | % List_energy : is a matrix containing the values of the energy during 20 | % optimization process. 21 | % 22 | % See also: jnfmean_tan_free,fsatlas_tan_free,fsatlas_tan_HT 23 | % Author : B. Charlier (2017) 24 | 25 | 26 | global data 27 | 28 | %--------% 29 | % DATA % 30 | %--------% 31 | 32 | 33 | if ~iscell(target) 34 | data= {target}; 35 | else 36 | data = target; 37 | end 38 | 39 | [nb_obs,nb_match] = size(data); 40 | 41 | if nb_obs >1 42 | error('target must contain only 1 observation') 43 | end 44 | 45 | 46 | for i = 1:nb_obs 47 | for l=1:nb_match 48 | if ~isfield(data{i,l},'f') 49 | data{i,l}.f = zeros(size(data{i,l}.x,1),1); 50 | end 51 | end 52 | end 53 | 54 | %----------% 55 | % TEMPLATE % 56 | %----------% 57 | 58 | if ~iscell(source) 59 | source= {source}; 60 | end 61 | 62 | for l=1:nb_match 63 | if ~isfield(source{l},'f') 64 | source{l}.f = zeros(size(source{l}.x,1),1); 65 | end 66 | end 67 | 68 | 69 | 70 | %--------% 71 | % MATCH % 72 | %--------% 73 | 74 | switch lower(optim.method) 75 | case 'bfgs' 76 | fprintf('\n Performing a geometrico-functional matching \n') 77 | [momentums,summary]=jnfmatch_tan(source,[],[],defo,objfun,optim); 78 | 79 | end 80 | 81 | end 82 | 83 | 84 | 85 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /matlab/Bin/optim/hanso (third party)/setx0.m: -------------------------------------------------------------------------------- 1 | function options = setx0(pars,options) 2 | % set columns of options.x0 randomly if not provided by user 3 | % Send comments/bug reports to Michael Overton, overton@cs.nyu.edu, 4 | % with a subject header containing the string "hanso" or "bfgs". 5 | % Version 2.0, 2010, see GPL license info below. 6 | 7 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 8 | %% HANSO 2.0 Copyright (C) 2010 Michael Overton 9 | %% This program is free software: you can redistribute it and/or modify 10 | %% it under the terms of the GNU General Public License as published by 11 | %% the Free Software Foundation, either version 3 of the License, or 12 | %% (at your option) any later version. 13 | %% 14 | %% This program is distributed in the hope that it will be useful, 15 | %% but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | %% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | %% GNU General Public License for more details. 18 | %% 19 | %% You should have received a copy of the GNU General Public License 20 | %% along with this program. If not, see . 21 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 22 | 23 | nvar = pars.nvar; 24 | if ~isfield(options, 'x0') 25 | options.x0 = []; 26 | end 27 | if isempty(options.x0) 28 | if isfield(options, 'nstart') 29 | if ~isposint(options.nstart) 30 | error('setx0: input "options.nstart" must be a positive integer when "options.x0" is not provided') 31 | else 32 | options.x0 = randn(nvar, options.nstart); 33 | end 34 | else 35 | options.x0 = randn(nvar, 10); 36 | end 37 | else 38 | if size(options.x0,1) ~= nvar 39 | error('setx0: input "options.x0" must have "pars.nvar" rows') 40 | end 41 | if isfield(options, 'nstart') 42 | if ~isnonnegint(options.nstart) 43 | error('setx0: input "options.nstart" must be a nonnegative integer') 44 | elseif options.nstart < size(options.x0,2) 45 | error('setx0: "options.nstart" is less than number of columns of "options.x0"') 46 | else % augment vectors in options.x0 with randomly generated ones 47 | nrand = options.nstart - size(options.x0,2); 48 | options.x0 = [options.x0 randn(nvar, nrand)]; 49 | end 50 | end % no else part, options.x0 is as provided 51 | end -------------------------------------------------------------------------------- /matlab/Bin/io/export_fshape_vtk.m: -------------------------------------------------------------------------------- 1 | function [] = export_fshape_vtk(data,fname,signal_name,signal_type) 2 | % EXPORT_VTK(data,fname,funname) save a fshape structure into a .vtk file 3 | % 4 | %Input 5 | % data : struct with fields 'x','G' and 'f'. (the field 'f' may be optional) 6 | % fname : name of the output file 7 | % signal_name (optional) : name of the functional to be set in the.vtk file 8 | % type_signal : set to 'face' if the signal is defined at the center of 9 | % the face. In that case size(data.f,1) == size(data.G,1). Otherwise 10 | % the signal is assumed to be defined at each vertex. 11 | % Author : B. Charlier (2017) 12 | 13 | 14 | if nargin == 2 || isempty(signal_name) 15 | signal_name = 'signal'; 16 | end 17 | if nargin <= 3 18 | if size(data.f,1) == size(data.x,1) 19 | signal_type = 'vertex'; 20 | elseif size(data.f,1) == size(data.G,1) 21 | signal_type = 'face'; 22 | end 23 | end 24 | 25 | if size(data.x,2)<=2 26 | data.x = [data.x,zeros(size(data.x,1),3-size(data.x,2))]; 27 | end 28 | 29 | 30 | 31 | % open file 32 | fid = fopen(fname,'w'); 33 | 34 | % header 35 | fprintf(fid,'# vtk DataFile Version 3.0\n'); 36 | fprintf(fid,'vtk generated by fshapesTk\n'); 37 | 38 | fprintf(fid,'%s\n','ASCII'); 39 | fprintf(fid,'DATASET POLYDATA\n'); 40 | 41 | %points 42 | fprintf(fid,'POINTS %u float\n', size(data.x,1)); 43 | 44 | x = repmat('%G ',1,size(data.x,2)-1); 45 | fprintf(fid,[x,'%G\n'], data.x'); 46 | 47 | 48 | 49 | %edges 50 | if size(data.G,2) == 3 51 | type = 'POLYGONS'; 52 | elseif size(data.G,2) == 2 53 | type = 'LINES'; 54 | elseif size(data.G,2) == 1 55 | type = 'VERTICES'; 56 | elseif size(data.G,2) == 4 57 | type = 'POLYGONS'; 58 | end 59 | fprintf(fid,['\n%s %u %u\n'], type,size(data.G,1),(size(data.G,2)+1).*size(data.G,1)); 60 | 61 | x = [num2str(size(data.G,2)),' ',repmat('%u ',1,size(data.G,2)-1)]; 62 | fprintf(fid,[x,'%u\n'], (data.G-1)'); 63 | 64 | 65 | % functional 66 | if isfield(data,'f') 67 | if strcmpi(signal_type,'face') 68 | fprintf(fid,['\nCELL_DATA ','%u\n'],size(data.G,1)); % 5== triangle, 1 == vertex, 3 == lines, 69 | else 70 | fprintf(fid,['\nPOINT_DATA ','%u\n'],size(data.x,1)); % 5== triangle, 1 == vertex, 3 == lines, 71 | 72 | end 73 | 74 | fprintf(fid,['SCALARS ',signal_name,' FLOAT\nLOOKUP_TABLE default\n']); 75 | fprintf(fid,['%G\n'],data.f'); 76 | 77 | end 78 | fclose(fid); 79 | 80 | %avoid unnecessary output 81 | if ~strcmpi(fname(end-17:end),'results_iter_c.vtk') 82 | fprintf('File saved in %s\n',fname) 83 | end 84 | 85 | end 86 | -------------------------------------------------------------------------------- /matlab/Bin/norms/shape/wasserstein/dcost_varifold.m: -------------------------------------------------------------------------------- 1 | function res = dcost_varifold(x,y,weight) 2 | % This function compute the derivative wrt X of the cost function used in the OT for discrete measure 3 | % composed with varifold Dirac mass. 4 | % 5 | % Input : 6 | % X is a discrete varifold measure : a d x 2n matrix where d is the dimension of 7 | % the ambient space and n is the number of points in the cloud. The first 8 | % n rows encode the position and en last n rows encode the orientation 9 | % Y : idem as X. 10 | % 11 | % Output : 12 | % res : a (d x size(x,2) x size(y,2)) matrix); 13 | % Author : B. Charlier (2017) 14 | 15 | 16 | [d,nx] = size(x);%nx = nx/2; 17 | [~,ny] = size(y);%ny = ny/2; 18 | 19 | d = d/2; %dimension ambient space 20 | 21 | %------------------% 22 | %-Cost on position-% 23 | %------------------% 24 | 25 | % gradient with respect to x of C(x,y)=1/2*|x-y|^2 26 | 27 | nablaC1 = @(x,y)repmat(x,[1 1 size(y,2)]) - ... 28 | repmat(reshape(y,[size(y,1) 1 size(y,2)]),[1 size(x,2)]); 29 | 30 | 31 | %---------------------% 32 | %-Cost on orientation-% 33 | %---------------------% 34 | 35 | normalsX = x(d+1:2*d,:); 36 | normalsY = y(d+1:2*d,:); 37 | 38 | % Compute unit normals 39 | norm_normalsX = sqrt(sum(normalsX .^2,1)); 40 | norm_normalsY = sqrt(sum(normalsY .^2,1)); 41 | 42 | unit_normalsX = normalsX ./ repmat(norm_normalsX,d,1); 43 | unit_normalsY = normalsY ./ repmat(norm_normalsY,d,1); 44 | 45 | prs_unit_norm = zeros(nx,ny); 46 | for l=1:d 47 | prs_unit_norm = prs_unit_norm + (repmat(unit_normalsY(l,:),nx,1).*repmat(unit_normalsX(l,:)',1,ny)); 48 | end 49 | 50 | dprs_unit_norm = ( -repmat(unit_normalsX,[1 1 ny]) .* repmat(reshape(prs_unit_norm,[1,nx,ny]),[d,1])... 51 | + repmat(reshape(unit_normalsY,[d 1 ny]),[1 nx])) ./ reshape(repmat(norm_normalsX,d,ny),[d,nx,ny]); 52 | 53 | %unoriented : gradient with respect to x of C(x,y)=2 * (1 - ^2) 54 | %nablaC2= -8 .* dprs_unit_norm .* repmat(reshape(prs_unit_norm,[1,nx,ny]),[d,1]); 55 | 56 | 57 | %oriented : gradient with respect to (1 - ) 58 | nablaC2 = - dprs_unit_norm; 59 | 60 | %--------% 61 | %-Result-% 62 | %--------% 63 | 64 | % canonical metric (c1 + c2) 65 | res = [weight(1) * nablaC1(x(1:d,:),y(1:d,:));weight(2) * nablaC2]; 66 | 67 | 68 | % Other pseudo metric tricks... (c1 + c1 * c2) 69 | %C1 = @(x,y)squeeze( sum(nablaC1(x,y).^2)/2 ); 70 | %C2 = (2 - 2 * prs_unit_norm .^2); 71 | %res = [ nablaC1(x(1:d,:),y(1:d,:)) .* repmat(reshape( (1 + weight(2) * C2) , [1,nx,ny]),[d,1]) ;... 72 | % .5 *weight(2) * repmat(reshape( C1(x(1:d,:) ,y(1:d,:) ) , [1,nx,ny]),[d,1]).* nablaC2]; 73 | 74 | 75 | 76 | end 77 | -------------------------------------------------------------------------------- /matlab/Bin/optim/hanso (third party)/postprocess.m: -------------------------------------------------------------------------------- 1 | function [loc, X, G, w] = postprocess(x, g, dnorm, X, G, w) 2 | % postprocessing of set of sampled or bundled gradients 3 | % if x is not one of the columns of X, prepend it to X and 4 | % g to G and recompute w and dnorm: this can only reduce dnorm 5 | % also set loc.dnorm to dnorm and loc.evaldist to the 6 | % max distance from x to columns of X 7 | % note: w is needed as input argument for the usual case that 8 | % w is not recomputed but is just passed back to output 9 | % 10 | % Send comments/bug reports to Michael Overton, overton@cs.nyu.edu, 11 | % with a subject header containing the string "hanso". 12 | % Version 2.0, 2010, see GPL license info below. 13 | 14 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 15 | %% HANSO 2.0 Copyright (C) 2010 Michael Overton 16 | %% This program is free software: you can redistribute it and/or modify 17 | %% it under the terms of the GNU General Public License as published by 18 | %% the Free Software Foundation, either version 3 of the License, or 19 | %% (at your option) any later version. 20 | %% 21 | %% This program is distributed in the hope that it will be useful, 22 | %% but WITHOUT ANY WARRANTY; without even the implied warranty of 23 | %% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 24 | %% GNU General Public License for more details. 25 | %% 26 | %% You should have received a copy of the GNU General Public License 27 | %% along with this program. If not, see . 28 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 29 | 30 | for j = 1:size(X,2) 31 | dist(j) = norm(x - X(:,j)); 32 | end 33 | evaldist = max(dist); % for returning 34 | [mindist, indx] = min(dist); % for checking if x is a column of X 35 | if mindist == 0 & indx == 1 36 | % nothing to do 37 | elseif mindist == 0 & indx > 1 38 | % this should not happen in HANSO 2.0 39 | % swap x and g into first positions of X and G 40 | % might be necessary after local bundle, which is not used in HANSO 2.0 41 | X(:,[1 indx]) = X(:,[indx 1]); 42 | G(:,[1 indx]) = G(:,[indx 1]); 43 | w([1 indx]) = w([indx 1]); 44 | else 45 | % this cannot happen after BFGS, but it may happen after gradient 46 | % sampling, for example if max iterations exceeded: line search found a 47 | % lower point but quit before solving new QP 48 | % prepend x to X and g to G and recompute w 49 | X = [x X]; 50 | G = [g G]; 51 | [w,d] = qpspecial(G); % Anders Skajaa's QP code 52 | dnorm = norm(d); 53 | end 54 | loc.dnorm = dnorm; 55 | loc.evaldist = evaldist; -------------------------------------------------------------------------------- /LDDMM_Python/lddmm_python/modules/manifolds/theano_hamiltoniancarrier.py: -------------------------------------------------------------------------------- 1 | # Import of the relevant tools 2 | import time 3 | import numpy as np 4 | import theano 5 | import theano.tensor as T 6 | from theano import pp, config 7 | 8 | 9 | from plotly.tools import FigureFactory as FF 10 | import plotly.graph_objs as go 11 | 12 | from ..io.read_vtk import ReadVTK 13 | from ..data_attachment.measures import Measures 14 | from ..data_attachment.varifolds import Varifolds 15 | from ..math_utils.kernels import _squared_distances, _gaussian_kernel 16 | 17 | 18 | from .theano_hamiltonianclouds import TheanoHamiltonianClouds 19 | 20 | class TheanoHamiltonianCarrier(TheanoHamiltonianClouds) : 21 | """ 22 | Superseeds the regular Hamiltonian cost, which is not computed wrt to 23 | the final state q1, but with respect to a carried "shape" s1. 24 | This is the class that shall be inherited by any "control points" manifold. 25 | """ 26 | def __init__(self, **kwargs) : 27 | 28 | TheanoHamiltonianClouds.__init__(self, **kwargs) 29 | 30 | 31 | # Symbolic Hamiltonian functions ========================================================================== 32 | 33 | # Part 3 : Cost function and derivatives ------------------------------------------------------- 34 | def _cost(self, q, p, s, *args) : 35 | cost_reg = self._Hqp(q,p) 36 | cost_att = self._data_attachment(self._HamiltonianShootingCarrying(q,p,s)[2], *args) # C(q_0, p_0, s_0) = A(s_1, x_t) 37 | return self.weight_regularization * cost_reg + self.weight_attachment * cost_att[0], cost_att[1] 38 | 39 | # The discrete backward scheme is automatically computed : 40 | def _dcost_q0(self, q,p, s, *args) : # Useful for template estimation 41 | return T.grad(self._cost(q,p,s, *args)[0], q) # The gradients wrt. q_0 is automatically computed 42 | def _dcost_p0(self, q,p,s, *args) : # Useful in a matching problem 43 | return T.grad(self._cost(q,p,s, *args)[0], p) # The gradients wrt. p_0 is automatically computed 44 | 45 | def _opt_shooting_cost(self, q0, p0, s0, *args) : # Wrapper 46 | cost_info = self._cost( q0, p0, s0, *args) # cost + additional information 47 | return [cost_info[0] , # Actual cost 48 | q0,#self._dcost_q0( q0, p0, s0, *args) , 49 | self._dcost_p0( q0, p0, s0, *args) , 50 | self._HamiltonianShootingCarrying(q0,p0,s0)[2], 51 | cost_info[1] ] # Additional information (transport plan, etc.) 52 | 53 | # Appendix : Collection of data attachment terms ----------------------------------------------- 54 | def _data_attachment(self, s1, *args) : 55 | """Selects the appropriate data attachment routine, depending on self's attributes.""" 56 | raise(NotImplementedError) 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /matlab/Bin/deformations/tangential/dHr_tan.m: -------------------------------------------------------------------------------- 1 | function [dxHr,dpHr] = dHr_tan(x,p,defo) 2 | % [dxHr,dpHr] = DHR(x,p,defo) computes the reduced Hamiltonian system. Several 3 | % method are implemented to speedup the compution (matlab, cuda and C). The method used is the one 4 | % given by defo.method 5 | % 6 | % Input : 7 | % x : state (n x d) matrix 8 | % p : costate (n x d) matrix 9 | % defo : structure containing the fields 'method' ('matlab', 'cuda' or 'grid') and 'kernel_size_mom' (kernel size) 10 | % 11 | % Output 12 | % dxHr : gradient of Hr wrt to x at point (x,p) 13 | % dpHr: gradient of Hr wrt to p at point (x,p) 14 | % 15 | % See also : forward_tan, backward_tan, ddHrtP_tan 16 | % Author : B. Charlier (2017) 17 | 18 | 19 | switch defo.method 20 | case 'cuda' 21 | DHR = @dHr_tan_cuda; 22 | case 'grid' 23 | DHR = @dHr_tan_grid; 24 | otherwise 25 | DHR = @dHr_tan_mat; 26 | end 27 | 28 | [dxHr,dpHr] = DHR(x,p,defo); 29 | 30 | end 31 | 32 | function [dxHr,dpHr] = dHr_tan_mat(x,p,defo) 33 | % Matlab version of the reduced Hamiltonian system. 34 | % Input : 35 | % x : state (n x d) matrix 36 | % p : costate (n x d) matrix 37 | % defo : structure containing the field and 'kernel_size_mom' (kernel size) 38 | % 39 | % Output 40 | % dxHr : gradient of Hr wrt to x at point (x,p) 41 | % dpHr: gradient of Hr wrt to p at point (x,p) 42 | 43 | 44 | [n,d]=size(x); 45 | 46 | % Calcul de A=exp(-|x_i -x_j|^2/(lam^2)) 47 | S=zeros(n); 48 | for l=1:d 49 | S=S+(repmat(x(:,l),1,n)-repmat(x(:,l)',n,1)).^2; 50 | end 51 | A = rho(S,0,defo.kernel_size_mom); 52 | B = rho(S,1,defo.kernel_size_mom); 53 | 54 | 55 | dpHr=A*p; 56 | 57 | 58 | dxHr=zeros(n,d); 59 | for r=1:d 60 | % Computation of B=2*|x_i -x_j|*exp(-|x_i -x_j|^2/(lam^2))/(lam^2) 61 | Br=2*(repmat(x(:,r),1,n)-repmat(x(:,r)',n,1)).*B; 62 | dxHr(:,r)=dxHr(:,r)+ sum(p .* (Br*p) ,2); 63 | end 64 | 65 | end 66 | 67 | function [dxHr,dpHr] = dHr_tan_cuda(x,p,defo) 68 | % cuda version of the reduced Hamiltonian system. 69 | % Input : 70 | % x : state (n x d) matrix 71 | % p : costate (n x d) matrix 72 | % defo : structure containing the field 'kernel_size_mom' (kernel size) 73 | % 74 | % Output 75 | % dxHr : gradient of Hr wrt to x at point (x,p) 76 | % dpHr: gradient of Hr wrt to p at point (x,p) 77 | 78 | 79 | dxHr = zeros(size(x)); 80 | dpHr = zeros(size(p)); 81 | 82 | if isfield(defo,'precision') && strcmp(defo.precision,'double') 83 | conv = @GaussGpuConvDouble; 84 | gradconv= @GaussGpuGrad1ConvDouble; 85 | else 86 | conv = @GaussGpuConv; 87 | gradconv= @GaussGpuGrad1Conv; 88 | 89 | end 90 | 91 | for sig = defo.kernel_size_mom 92 | dxHr= dxHr + gradconv(p',x',x',p',sig)'; 93 | dpHr = dpHr + conv(x',x',p',sig)'; 94 | end 95 | 96 | end 97 | -------------------------------------------------------------------------------- /Pytorch/shooting.py: -------------------------------------------------------------------------------- 1 | # Import the relevant tools 2 | import numpy as np # standard array library 3 | import torch 4 | 5 | # No need for a ~/.theanorc file anymore ! 6 | use_cuda = torch.cuda.is_available() 7 | dtype = torch.cuda.FloatTensor if use_cuda else torch.FloatTensor 8 | dtypeint = torch.cuda.LongTensor if use_cuda else torch.LongTensor 9 | 10 | from kernel import _k 11 | 12 | # Pytorch is a fantastic deep learning library : it transforms symbolic python code 13 | # into highly optimized CPU/GPU binaries, which are called in the background seamlessly. 14 | # It can be thought of as a "heir" to the legacy Theano library (RIP :'-( ): 15 | # As you'll see, migrating a codebase from one to another is fairly simple ! 16 | # 17 | # N.B. : On my Dell laptop, I have a GeForce GTX 960M with 640 Cuda cores and 2Gb of memory. 18 | # 19 | # We now show how to code a whole LDDMM pipeline into one (!!!) page of torch symbolic code. 20 | 21 | # Part 1 : cometric on the space of landmarks, kinetic energy on the phase space (Hamiltonian)=== 22 | 23 | def _Hqp(q, p, sigma) : 24 | "The hamiltonian, or kinetic energy of the shape q with momenta p." 25 | pKqp = _k(q, q, sigma) * (p @ p.t()) # Use a simple isotropic kernel 26 | return .5 * pKqp.sum() # $H(q,p) = \frac{1}{2} * sum_{i,j} k(x_i,x_j) p_i.p_j$ 27 | 28 | # Part 2 : Geodesic shooting ==================================================================== 29 | # The partial derivatives of the Hamiltonian are automatically computed ! 30 | def _dq_Hqp(q,p,sigma) : 31 | return torch.autograd.grad(_Hqp(q,p,sigma), q, create_graph=True)[0] 32 | def _dp_Hqp(q,p,sigma) : 33 | return torch.autograd.grad(_Hqp(q,p,sigma), p, create_graph=True)[0] 34 | 35 | def _hamiltonian_step(q,p, sigma) : 36 | "Simplistic euler scheme step with dt = .1." 37 | return [q + .1 * _dp_Hqp(q,p,sigma) , # See eq. 38 | p - .1 * _dq_Hqp(q,p,sigma) ] 39 | 40 | def _HamiltonianShooting(q, p, sigma) : 41 | "Shoots to time 1 a k-geodesic starting (at time 0) from q with momentum p." 42 | for t in range(10) : 43 | q,p = _hamiltonian_step(q, p, sigma) # Let's hardcode the "dt = .1" 44 | return [q,p] # and only return the final state + momentum 45 | 46 | # Part 2bis : Geodesic shooting + deformation of the ambient space, for visualization =========== 47 | def _HamiltonianCarrying(q, p, g, s) : 48 | """ 49 | Similar to _HamiltonianShooting, but also conveys information about the deformation of 50 | an arbitrary point cloud 'grid' in the ambient space. 51 | """ 52 | for t in range(10) : # Let's hardcode the "dt = .1" 53 | q,p,g = [q + .1 * _dp_Hqp(q,p, s), 54 | p - .1 * _dq_Hqp(q,p, s), 55 | g + .1 * _k(g, q, s) @ p] 56 | return q,p,g # return the final state + momentum + grid 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /LDDMM_Python/lddmm_python/lib/plotly/matplotlylib/mplexporter/renderers/fake_renderer.py: -------------------------------------------------------------------------------- 1 | from .base import Renderer 2 | 3 | 4 | class FakeRenderer(Renderer): 5 | """ 6 | Fake Renderer 7 | 8 | This is a fake renderer which simply outputs a text tree representing the 9 | elements found in the plot(s). This is used in the unit tests for the 10 | package. 11 | 12 | Below are the methods your renderer must implement. You are free to do 13 | anything you wish within the renderer (i.e. build an XML or JSON 14 | representation, call an external API, etc.) Here the renderer just 15 | builds a simple string representation for testing purposes. 16 | """ 17 | def __init__(self): 18 | self.output = "" 19 | 20 | def open_figure(self, fig, props): 21 | self.output += "opening figure\n" 22 | 23 | def close_figure(self, fig): 24 | self.output += "closing figure\n" 25 | 26 | def open_axes(self, ax, props): 27 | self.output += " opening axes\n" 28 | 29 | def close_axes(self, ax): 30 | self.output += " closing axes\n" 31 | 32 | def open_legend(self, legend, props): 33 | self.output += " opening legend\n" 34 | 35 | def close_legend(self, legend): 36 | self.output += " closing legend\n" 37 | 38 | def draw_text(self, text, position, coordinates, style, 39 | text_type=None, mplobj=None): 40 | self.output += " draw text '{0}' {1}\n".format(text, text_type) 41 | 42 | def draw_path(self, data, coordinates, pathcodes, style, 43 | offset=None, offset_coordinates="data", mplobj=None): 44 | self.output += " draw path with {0} vertices\n".format(data.shape[0]) 45 | 46 | def draw_image(self, imdata, extent, coordinates, style, mplobj=None): 47 | self.output += " draw image of size {0}\n".format(len(imdata)) 48 | 49 | 50 | class FullFakeRenderer(FakeRenderer): 51 | """ 52 | Renderer with the full complement of methods. 53 | 54 | When the following are left undefined, they will be implemented via 55 | other methods in the class. They can be defined explicitly for 56 | more efficient or specialized use within the renderer implementation. 57 | """ 58 | def draw_line(self, data, coordinates, style, label, mplobj=None): 59 | self.output += " draw line with {0} points\n".format(data.shape[0]) 60 | 61 | def draw_markers(self, data, coordinates, style, label, mplobj=None): 62 | self.output += " draw {0} markers\n".format(data.shape[0]) 63 | 64 | def draw_path_collection(self, paths, path_coordinates, path_transforms, 65 | offsets, offset_coordinates, offset_order, 66 | styles, mplobj=None): 67 | self.output += (" draw path collection " 68 | "with {0} offsets\n".format(offsets.shape[0])) 69 | -------------------------------------------------------------------------------- /matlab/Bin/optim/hanso (third party)/setdefaults.m: -------------------------------------------------------------------------------- 1 | function options = setdefaults(pars,options) 2 | % call: options = setdefaults(pars,options) 3 | % check that fields of pars and options are set correctly and 4 | % set basic default values for options that are common to various 5 | % optimization methods, including bfgs and gradsamp 6 | % Send comments/bug reports to Michael Overton, overton@cs.nyu.edu, 7 | % with a subject header containing the string "hanso" or "bfgs". 8 | % Version 2.0, 2010, see GPL license info below. 9 | 10 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 11 | %% HANSO 2.0 Copyright (C) 2010 Michael Overton 12 | %% This program is free software: you can redistribute it and/or modify 13 | %% it under the terms of the GNU General Public License as published by 14 | %% the Free Software Foundation, either version 3 of the License, or 15 | %% (at your option) any later version. 16 | %% 17 | %% This program is distributed in the hope that it will be useful, 18 | %% but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | %% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | %% GNU General Public License for more details. 21 | %% 22 | %% You should have received a copy of the GNU General Public License 23 | %% along with this program. If not, see . 24 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 25 | if nargin < 2 26 | options = []; 27 | end 28 | if ~isfield(pars, 'nvar') 29 | error('setdefaults: input "pars" must have a field "nvar" (number of variables)') 30 | elseif ~isposint(pars.nvar) 31 | error('setdefaults: input "pars.nvar" (number of variables) must be a positive integer') 32 | end 33 | if ~isfield(pars, 'fgname') 34 | error('setdefaults: input "pars" must have a field "fgname" (name of m-file computing function and gradient)') 35 | end 36 | if isfield(options, 'maxit') 37 | if ~isnonnegint(options.maxit) 38 | error('setdefaults: input "options.maxit" must be a nonnegative integer') 39 | end 40 | else 41 | options.maxit = 1000; 42 | end 43 | if isfield(options, 'normtol') 44 | if ~isposreal(options.normtol) 45 | error('setdefaults: input "options.normtol" must be a positive real scalar') 46 | end 47 | else 48 | options.normtol = 1.0e-6; 49 | end 50 | if isfield(options, 'fvalquit') 51 | if ~isreal(options.fvalquit)|~isscalar(options.fvalquit) 52 | error('setdefaults: input "options.fvalquit" must be a real scalar') 53 | end 54 | else 55 | options.fvalquit = -inf; 56 | end 57 | if isfield(options, 'xnormquit') 58 | if ~isreal(options.xnormquit)|~isscalar(options.xnormquit) 59 | error('setdefaults: input "options.fvalquit" must be a real scalar') 60 | end 61 | else 62 | options.xnormquit = inf; 63 | end 64 | if ~isfield(options, 'cpumax') 65 | options.cpumax = inf; 66 | end 67 | if ~isfield(options, 'prtlevel') 68 | options.prtlevel = 1; 69 | end -------------------------------------------------------------------------------- /matlab/Script/hands/data/generate_fiber.m: -------------------------------------------------------------------------------- 1 | function Xall = generate_fiber(X0,l,curvature,n,v,noise) 2 | % generate n curves of length l from the starting points X0 3 | % with the given mean curvature and in the global direction v 4 | % (parametres code en dur : nb_gaussienne et sigma 5 | % qui influencent la nature du bruit) 6 | 7 | if 0 % script 8 | l=15; n=20; X0=zeros(3,10); v=[1;1;2]; 9 | curvature=1/l; noise=.5; 10 | Xall=generate_fiber(X0,l,curvature,n,v,noise); 11 | figure; hold on; 12 | for i=1:size(X0,2) 13 | plot3(Xall(1,:,i),Xall(2,:,i),Xall(3,:,i)); 14 | end 15 | hold off; 16 | 17 | X0=rand(3,10); % source unique juste pour visualiser 18 | Xall=generate_fiber(X0,l,curvature,n,v,noise); 19 | figure; hold on; 20 | for i=1:size(X0,2) 21 | plot3(Xall(1,:,i),Xall(2,:,i),Xall(3,:,i)); 22 | end 23 | hold off; 24 | 25 | l =0.7;noise=.2; n=50; 26 | X0=repmat([0;-.2;0],1,n)+ randn(3,n)*.01; curvature=0.5/l; v=[.1;.1;2]; 27 | Xall=generate_fiber(X0,l,curvature,n,v,noise); 28 | % Xall = Xall/10; 29 | figure(1); hold on; 30 | trisurf(t,p(:,1),p(:,2),p(:,3)) 31 | for i=1:size(X0,2) 32 | plot3(Xall(1,:,i),Xall(2,:,i),Xall(3,:,i)); 33 | end 34 | hold off; 35 | axis equal 36 | end 37 | 38 | d=size(X0,1); 39 | if d~=size(v,1) 40 | disp('Dimension of the direction vector does not match'); 41 | end 42 | 43 | r=1/(curvature+eps); 44 | theta=l/r; 45 | 46 | th=3*pi/2+linspace(0,theta,n); 47 | X=zeros(3,n); 48 | X(1,:)=r*cos(th); 49 | X(2,:)=r*sin(th)+r; 50 | 51 | % Alignment on the direction v 52 | v=v/norm(v,2); ref=zeros(d,1);ref(1)=1; 53 | R=vrrotvec2mat(vrrotvec(ref,v)); 54 | X=R*X; 55 | 56 | Xall=zeros(d,n,size(X0,2)); 57 | % Generate the variations : 58 | for i=1:size(X0,2) 59 | nb_gaussienne=ceil(n/3); % parametre code en dur ! 60 | sigma=(n/5)^2; 61 | noise_scale=max(noise,noise*max(max((dist(X0))))); 62 | fX=genereCourbe(n,noise_scale,nb_gaussienne,sigma); 63 | fY=genereCourbe(n,noise_scale,nb_gaussienne,sigma); 64 | fZ=genereCourbe(n,noise_scale,nb_gaussienne,sigma); 65 | fX=log(linspace(1,exp(1),n)).*fX; % cancel noise at X0 66 | fY=log(linspace(1,exp(1),n)).*fY; % cancel noise at X0 67 | fZ=log(linspace(1,exp(1),n)).*fZ; % cancel noise at X0 68 | Xall(:,:,i)=repmat(X0(:,i),1,n)+X+[fX;fY;fZ]; 69 | end 70 | 71 | if d==2 72 | Xall(3,:,:)=[]; 73 | end 74 | end 75 | 76 | 77 | function fX = genereCourbe(n,a,ng,sigma) 78 | % generate a curve of n points 79 | % d'amplitude a, centr�e en 0 80 | 81 | g=@(x,c,sigma)exp(-(x-c)^2/sigma); 82 | 83 | c=linspace(0,1,ng)'+(2*rand(ng,1)-.5*ones(ng,1))/ng; % centres des gaussiennes 84 | h=2*rand(ng,1)-ones(ng,1); % amplitudes et signes 85 | X=linspace(0,1,n); 86 | fX=zeros(size(X)); 87 | for i=1:ng 88 | fX=fX+arrayfun(@(x)h(i)*g(x,c(i),sigma),X); 89 | end 90 | fX=a*fX/(max(fX)-min(fX)); 91 | fX=fX-mean(fX); 92 | end 93 | -------------------------------------------------------------------------------- /LDDMM_Python/lddmm_python/modules/data_attachment/currents.py: -------------------------------------------------------------------------------- 1 | from pylab import * 2 | from scipy.spatial.distance import pdist, squareform, cdist 3 | 4 | 5 | class Current : 6 | """ 7 | Encodes a Current as a sum of weighted vector diracs. 8 | \omega(v) = \sum_i (Omega_i, v(x_i)) 9 | """ 10 | def __init__(self, points, normals) : 11 | assert (points.shape[1] == 2), "3D currents have not been implemented yet !" 12 | assert (points.shape == normals.shape), "A current is given by an array of coordinates + an array of directions" 13 | self.points = points 14 | self.normals = normals 15 | self.dimension = self.points.shape[1] 16 | 17 | class Currents : 18 | @staticmethod 19 | def kernel_matching(Q, Xt, s) : 20 | """ 21 | Implementation of the kernel data attachment term : 22 | 23 | d(Q, Xt) = .5 * sum_{i,j} (v_i, v_j) k( | Q_i - Q_j | ) 24 | - .5 * 2*sum_{i,j} (v_i, w_j) k( | Q_i - Xt_j | ) 25 | + .5 * sum_{i,j} (w_i, w_j) k( | Xt_i - Xt_j | ) 26 | where 27 | Q = sum_i (v_i, \dirac_{ Q_i}(.) ) 28 | Xt = sum_j (w_j, \dirac_{Xt_j}(.) ) 29 | and where k( d ) = exp( - d^2/(2*s^2) ) is a gaussian kernel 30 | with std = s. 31 | 32 | This can be seen as a ``linear'' matching tool between curves/surfaces : 33 | - unlike the "Measures" tool, it takes the orientation into account, 34 | - but it only does so in a linear way. 35 | Today, one may prefer to use Varifolds or Normal Cycles. 36 | """ 37 | # We use a Gaussian kernel 38 | kernel = lambda x : exp(- x / (2* s ** 2)) # kernel is given |x|^2 as input 39 | kernelp = lambda x : - exp(- x / (2* s ** 2)) / (2* s ** 2) 40 | q = Q.points 41 | xt = Xt.points 42 | v = Q.normals 43 | w = Xt.normals 44 | q_dists = squareform(pdist( q, 'sqeuclidean')) 45 | cross_dists = cdist( q, xt, 'sqeuclidean') 46 | xt_dists = squareform(pdist(xt, 'sqeuclidean')) 47 | 48 | # Matrices of scalar products between normals ('G' stands for Grassmanian) 49 | Gvv = v @ v.T 50 | Gvw = v @ w.T 51 | Gww = w @ w.T 52 | 53 | # We're gonna need those two for later calculations 54 | ker_qq = kernel(q_dists) 55 | ker_qxt = kernel(cross_dists) 56 | 57 | K_qq = Gvv * ker_qq 58 | K_qxt = Gvw * ker_qxt 59 | K_xtxt = Gww * kernel(xt_dists) 60 | # Total data attachment term : 61 | C = .5 * ( sum(K_qq) - 2*sum(K_qxt) + sum(K_xtxt) ) 62 | 63 | # Computation of the directional derivatives 64 | # with respect to the dirac positions 65 | Kp_qq = Gvv * kernelp(q_dists) 66 | Kp_qxt = Gvw * kernelp(cross_dists) 67 | dq = zeros(q.shape) 68 | for d in range(q.shape[1]) : 69 | qi_min_qj = atleast_2d(q[:,d]).T - atleast_2d( q[:,d]) 70 | qi_min_xtj = atleast_2d(q[:,d]).T - atleast_2d(xt[:,d]) 71 | dq[:,d] = ( sum( qi_min_qj * Kp_qq , 1) \ 72 | - 2* sum( qi_min_xtj * Kp_qxt, 1) ) 73 | 74 | # Computation of the directional derivatives 75 | # with respect to the normals v 76 | dv = zeros(v.shape) 77 | for d in range(v.shape[1]) : 78 | dv[:,d] = sum( v[:,d] * ker_qq , 1) \ 79 | - sum( w[:,d] * ker_qxt, 1) 80 | 81 | dOmega = Current(dq, dv) 82 | return (C, dOmega) 83 | -------------------------------------------------------------------------------- /matlab/Bin/kernels/cuda/makefile_cuda.sh~: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # This small script shows how to compile the cuda mex files. It has been tested : 4 | # on a Debian Jessie/Sid and Ubuntu 14.04 systems with Cuda 5.5 to 7.5 (packaged version) and matlab R2013b and R2014a. 5 | # If cuda was manually installed make sure that path "CUDAROOT" to cuda libs is correct and that ld knows where 6 | # libcudart.so.* is located (modify or create a LD_LIBRARY_PATH variable). Please adapt all the other values to fit your configuration. 7 | 8 | 9 | #------------------------------------# 10 | # CHECK THESE PATHS # 11 | #------------------------------------# 12 | 13 | 14 | MATLABROOT="/usr/local/MATLAB/R2014a" 15 | CUDAROOT="/usr/local/cuda-7.5/lib64" 16 | MEXC="$MATLABROOT/bin/mex" 17 | CC="/usr/bin/gcc" 18 | NVCC="/usr/local/cuda-7.5/bin/nvcc" 19 | 20 | # CHECK THESE PARAMETERS (depends on your GPU): 21 | COMPUTECAPABILITY=35 22 | USE_DOUBLE=0 23 | NVCCOPT="--use_fast_math" 24 | BLOCKSIZE=192 25 | 26 | # NVCC 27 | NVCCFLAGS="-ccbin=$CC -arch=sm_$COMPUTECAPABILITY -Xcompiler -fPIC" 28 | MEXPATH="-I$MATLABROOT/extern/include" 29 | 30 | # C 31 | COPTIMFLAG="-O3" 32 | CLIB="-L$CUDAROOT -lcudart" 33 | 34 | INSTALL_DIR="../binaries" 35 | 36 | #clean 37 | rm -f *.o; 38 | 39 | #---------------------------------------# 40 | # fshapes distances # 41 | #---------------------------------------# 42 | 43 | #clean 44 | rm -f *.o; 45 | 46 | # Wasserstein distances (compiled with double) 47 | 48 | $NVCC -c -D "USE_DOUBLE_PRECISION=1" -D "CUDA_BLOCK_SIZE=$BLOCKSIZE" ./shapes_distances/wasserstein/sinkhornGpuConv.cu $NVCCFLAGS $MEXPATH -o sinkhornGpuConv.o;echo "sinkhornGpuConv.cu successfully compiled"; 49 | $NVCC -c -D "USE_DOUBLE_PRECISION=1" -D "CUDA_BLOCK_SIZE=$BLOCKSIZE" ./shapes_distances/wasserstein/sinkhornGpuConv_unbalanced.cu $NVCCFLAGS $MEXPATH -o sinkhornGpuConv_unbalanced.o;echo "sinkhornGpuConv_unbalanced.cu successfully compiled"; 50 | $NVCC -c -D "USE_DOUBLE_PRECISION=1" -D "CUDA_BLOCK_SIZE=$BLOCKSIZE" ./shapes_distances/wasserstein/dsinkhornGpuConv.cu $NVCCFLAGS $MEXPATH -o dsinkhornGpuConv.o;echo "dsinkhornGpuConv.cu successfully compiled"; 51 | 52 | #mex complilation 53 | for i in `ls *.o`;do $MEXC GCC=$CC COPTIMFLAGS=$COPTIMFLAG $i $CLIB;done 54 | 55 | # install 56 | mkdir -p "$INSTALL_DIR/fshapes_distances/wasserstein" 57 | 58 | for i in `ls *.mexa64`;do 59 | mv $i "$INSTALL_DIR/fshapes_distances/wasserstein/"; 60 | echo "$i successfully installed" 61 | done 62 | 63 | #---------------------------------------# 64 | # Kernels # 65 | #---------------------------------------# 66 | 67 | #nvcc compilation of every .cu files 68 | for i in `ls *.cu`;do $NVCC -D "USE_DOUBLE_PRECISION=$USE_DOUBLE" -D "CUDA_BLOCK_SIZE=$BLOCKSIZE" -c $i $NVCCFLAGS $MEXPATH $NVCCOPT;echo "$i successfully compiled";done 69 | 70 | #mex complilation 71 | for i in `ls *.o`;do $MEXC GCC=$CC COPTIMFLAGS=$COPTIMFLAG $i $CLIB;done 72 | 73 | #clean 74 | rm -f *.o; 75 | 76 | # install 77 | mkdir -p "$INSTALL_DIR" 78 | 79 | for i in `ls *.mexa64`;do 80 | mv $i "$INSTALL_DIR"; 81 | echo "$i successfully installed" 82 | done 83 | 84 | -------------------------------------------------------------------------------- /matlab/Bin/kernels/cuda/makefile_cuda.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # This small script shows how to compile the cuda mex files. It has been tested : 4 | # on a Debian Jessie/Sid and Ubuntu 14.04 systems with Cuda 5.5 to 7.5 (packaged version) and matlab R2013b and R2014a. 5 | # If cuda was manually installed make sure that path "CUDAROOT" to cuda libs is correct and that ld knows where 6 | # libcudart.so.* is located (modify or create a LD_LIBRARY_PATH variable). Please adapt all the other values to fit your configuration. 7 | # Author : B. Charlier (2017) 8 | 9 | 10 | #------------------------------------# 11 | # CHECK THESE PATHS # 12 | #------------------------------------# 13 | 14 | 15 | MATLABROOT="/usr/local/MATLAB/R2014a" 16 | CUDAROOT="/usr/local/cuda-7.5/lib64" 17 | MEXC="$MATLABROOT/bin/mex" 18 | CC="/usr/bin/gcc" 19 | NVCC="nvcc" 20 | 21 | # CHECK THESE PARAMETERS (depends on your GPU): 22 | COMPUTECAPABILITY=35 23 | USE_DOUBLE=0 24 | NVCCOPT="--use_fast_math" 25 | BLOCKSIZE=192 26 | 27 | # NVCC 28 | NVCCFLAGS="-ccbin=$CC -arch=sm_$COMPUTECAPABILITY -Xcompiler -fPIC" 29 | MEXPATH="-I$MATLABROOT/extern/include" 30 | 31 | # C 32 | COPTIMFLAG="-O3" 33 | CLIB="-L$CUDAROOT -lcudart" 34 | 35 | INSTALL_DIR="../binaries" 36 | 37 | #clean 38 | rm -f *.o; 39 | 40 | #---------------------------------------# 41 | # fshapes distances # 42 | #---------------------------------------# 43 | 44 | #clean 45 | rm -f *.o; 46 | 47 | # Wasserstein distances (compiled with double) 48 | 49 | $NVCC -c -D "USE_DOUBLE_PRECISION=1" -D "CUDA_BLOCK_SIZE=$BLOCKSIZE" ./shapes_distances/wasserstein/sinkhornGpuConv.cu $NVCCFLAGS $MEXPATH -o sinkhornGpuConv.o;echo "sinkhornGpuConv.cu successfully compiled"; 50 | $NVCC -c -D "USE_DOUBLE_PRECISION=1" -D "CUDA_BLOCK_SIZE=$BLOCKSIZE" ./shapes_distances/wasserstein/sinkhornGpuConv_unbalanced.cu $NVCCFLAGS $MEXPATH -o sinkhornGpuConv_unbalanced.o;echo "sinkhornGpuConv_unbalanced.cu successfully compiled"; 51 | $NVCC -c -D "USE_DOUBLE_PRECISION=1" -D "CUDA_BLOCK_SIZE=$BLOCKSIZE" ./shapes_distances/wasserstein/dsinkhornGpuConv.cu $NVCCFLAGS $MEXPATH -o dsinkhornGpuConv.o;echo "dsinkhornGpuConv.cu successfully compiled"; 52 | 53 | #mex complilation 54 | for i in `ls *.o`;do $MEXC GCC=$CC COPTIMFLAGS=$COPTIMFLAG $i $CLIB;done 55 | 56 | # install 57 | mkdir -p "$INSTALL_DIR/fshapes_distances/wasserstein" 58 | 59 | for i in `ls *.mexa64`;do 60 | mv $i "$INSTALL_DIR/fshapes_distances/wasserstein/"; 61 | echo "$i successfully installed" 62 | done 63 | 64 | #---------------------------------------# 65 | # Kernels # 66 | #---------------------------------------# 67 | 68 | #nvcc compilation of every .cu files 69 | for i in `ls *.cu`;do $NVCC -D "USE_DOUBLE_PRECISION=$USE_DOUBLE" -D "CUDA_BLOCK_SIZE=$BLOCKSIZE" -c $i $NVCCFLAGS $MEXPATH $NVCCOPT;echo "$i successfully compiled";done 70 | 71 | #mex complilation 72 | for i in `ls *.o`;do $MEXC GCC=$CC COPTIMFLAGS=$COPTIMFLAG $i $CLIB;done 73 | 74 | #clean 75 | rm -f *.o; 76 | 77 | # install 78 | mkdir -p "$INSTALL_DIR" 79 | 80 | for i in `ls *.mexa64`;do 81 | mv $i "$INSTALL_DIR"; 82 | echo "$i successfully installed" 83 | done 84 | 85 | -------------------------------------------------------------------------------- /matlab/Bin/optim/set_optim_option.m: -------------------------------------------------------------------------------- 1 | function [noptim,mesg] = set_optim_option(optim,objfun,list_of_variables,enr) 2 | % This function check the optim structure and set default values if needed. 3 | % Author : B. Charlier (2017) 4 | 5 | 6 | noptim = optim; 7 | 8 | 9 | noptim = setoptions(noptim,'method','gradDesc',{'gradDesc','bfgs'}); 10 | noptim = setoptions(noptim,noptim.method,[]); 11 | 12 | 13 | switch lower(noptim.method) 14 | case 'graddesc' 15 | noptim.gradDesc = set_gradDesc_defaults(noptim.gradDesc,objfun,list_of_variables,enr); 16 | 17 | case 'bfgs' 18 | noptim.bfgs = set_bfgs_defaults(noptim.bfgs,list_of_variables,enr); 19 | 20 | end 21 | 22 | 23 | % save message and display 24 | mesg = [sprintf('\n----------- Optimization parameters -----------\n' ),... 25 | dispstructure(noptim)]; 26 | 27 | fprintf('%s',mesg); 28 | 29 | 30 | 31 | 32 | end 33 | 34 | function opt = set_gradDesc_defaults(opt,objfun,list_of_variables,enr_name) 35 | 36 | 37 | opt = setoptions(opt,'step_increase',1.2); 38 | opt = setoptions(opt,'step_decrease',.5); 39 | 40 | opt = setoptions(opt,'kernel_size_signal_reg',0); 41 | opt = setoptions(opt,'kernel_size_geom_reg',0); 42 | 43 | switch objfun{1}.distance 44 | case 'kernel' 45 | opt = setoptions(opt,'max_nb_iter',50 * ones(1,size(objfun{1}.kernel_distance.kernel_size_signal,2))); 46 | 47 | nb_run = length(opt.max_nb_iter); 48 | nb_match = length(objfun); 49 | 50 | if ~isequal(cell2mat(cellfun(@(x) length(x.kernel_distance.kernel_size_signal),objfun,'UniformOutput',0)),nb_run*ones(1,nb_match)) ... 51 | || ~isequal(cell2mat(cellfun(@(x) length(x.kernel_distance.kernel_size_geom),objfun,'UniformOutput',0)),nb_run*ones(1,nb_match))... 52 | || ( (strcmp(objfun{1}.kernel_distance.kernel_grass,'gaussian_oriented')|| strcmp(objfun{1}.kernel_distance.kernel_grass,'gaussian_unoriented') ) && ~isequal(cell2mat(cellfun(@(x) length(x.kernel_distance.kernel_size_grass),objfun,'UniformOutput',0)),nb_run*ones(1,nb_match))) 53 | error('All kernel sizes objfun.sigmaXX and optim.max_nb_iter must have the same length'); 54 | end 55 | 56 | case 'wasserstein' 57 | opt = setoptions(opt,'max_nb_iter',50 * ones(1,size(objfun{1}.wasserstein_distance.epsilon,2))); 58 | 59 | end 60 | 61 | opt = setoptions(opt,'save_template_evolution',0); 62 | opt = setoptions(opt,'min_step_size',1e-10); 63 | opt = setoptions(opt,'min_fun_decrease',1e-4); 64 | 65 | for i =1:length(list_of_variables) 66 | opt = setoptions(opt,['step_size_',list_of_variables{i}],'auto'); 67 | end 68 | 69 | opt = setoptions(opt,'list_of_variables',list_of_variables); 70 | opt = setoptions(opt,'enr_name',enr_name); 71 | end 72 | 73 | function opt = set_bfgs_defaults(opt,list_of_variables,enr_name) 74 | 75 | 76 | 77 | opt = setoptions(opt, 'nvec', 20); % BFGS memory 78 | opt = setoptions(opt, 'maxit', 50); 79 | opt = setoptions(opt, 'prtlevel',2); 80 | opt = setoptions(opt, 'normtol', eps); 81 | opt = setoptions(opt, 'tol',eps); 82 | opt = setoptions(opt,'list_of_variables',list_of_variables); 83 | opt = setoptions(opt,'enr_name',enr_name); 84 | 85 | 86 | end 87 | 88 | -------------------------------------------------------------------------------- /LDDMM_Python/lddmm_python/modules/models/hypertemplate_atlas.py: -------------------------------------------------------------------------------- 1 | from pylab import * 2 | 3 | from .atlas import Atlas 4 | 5 | class HypertemplateAtlas(Atlas): 6 | """ 7 | Atlas with a shooted mean Q0 and no dimensional constraint. 8 | Important note : 9 | in general, the shooting method associated to the 10 | HT -> Template geodesic (Hilbert Space V0) can be different 11 | from the one used to get models X from the template. 12 | Here, we won't bother to define an other metric, 13 | and will simply use the one given by self.M. 14 | """ 15 | def __init__(self, *args, **kwargs): 16 | Atlas.__init__(self, *args, **kwargs) 17 | self.P0 = self.M.zero_momentum() 18 | self.QHT = self.Q0 19 | def template(self) : 20 | (Q0, _, _, _, _) = self.M.shoot(self.QHT, self.P0) 21 | return Q0 22 | def update(self, dP0, dP): 23 | # Parameters update : 24 | self.update_Q0(dP0) 25 | self.update_P(dP) 26 | def after_step_Q0(self, dP0) : 27 | # template update 28 | return self.P0 + dP0 # update of the template shooting parameter... 29 | def after_step_P(self, dP) : 30 | return [ p + dp for (p,dp) in zip(self.P, dP)] # No dimensional constraint 31 | def set_state(self, new_state) : 32 | self.P0 = new_state.Q0 33 | self.Q0 = self.template() # to get a new template 34 | self.P = new_state.P 35 | def template_cost(self, prec_QHT) : 36 | return .5* self.gamma_V0 * ( self.M.norm_p(self.QHT, self.P0, prec_QHT) **2) # Quadratic cost 37 | 38 | def normalize_and_regularize_template_updates(self, dQ0p, iteration) : 39 | dQ0 = self.M.sum_position(self.Q0, dQ0p) 40 | 41 | (Q0, Qt, Pt, _, prec_Qt) = self.M.shoot(self.QHT, self.P0) 42 | (dQHT, dP0) = self.M.backward_scheme(dQ0, self.M.zero_momentum(), Qt, Pt, prec_Qt) 43 | (dQHT_reg, dP0_reg) = self.d_regularization_term_HT(self.QHT, self.P0, prec_Qt[0]) 44 | # we will actually discard dQHT_reg, as we suppose it is fixed. 45 | dP0 = self.gamma_V0 * dP0_reg + dP0 46 | 47 | norm_update = self.M.norm_p(self.QHT, dP0, prec_Qt[0]) # usual approx 48 | dP0 = self.normalize_template_updates([dP0], norm_update, iteration)[0] 49 | return dP0.ravel() 50 | def d_regularization_term_HT(self, q, p, prec_q) : 51 | """ 52 | Differential of the term associated to gamma_V0 : 53 | .5 * (p0, Kqht p0) 54 | """ 55 | dp = self.M.K(q, p, prec_q) 56 | dq = - self.M.upP(q,p, prec_q) 57 | return (dq, dp) 58 | def show_HT(self) : 59 | self.M.marker(self.QHT, marker = dict(size = 10, color='rgb(255,0,255)'), name='Hypertemplate', visible=False) 60 | (Q0, Qt, Pt, _, _) = self.M.shoot(self.QHT, self.P0) 61 | self.M.plot_traj(Qt, line = dict(width= 2, color='rgb(255,128,0)'), name='Template Shooting', visible=False) 62 | def get_frame(self, f) : 63 | # Six plotly traces per frame : 'Hypertemplate', 'Template Shooting', 'Frechet Mean', 'Shootings', 'Targets', 'Models' 64 | list1 = str([ 1 + 6*self.current_frame, 2 + 6*self.current_frame, 3 + 6*self.current_frame, 4 + 6*self.current_frame, 5 + 6*self.current_frame, 6 + 6*self.current_frame])[1:-1] 65 | self.current_frame = f 66 | list2 = str([ 1 + 6*self.current_frame, 2 + 6*self.current_frame, 3 + 6*self.current_frame, 4 + 6*self.current_frame, 5 + 6*self.current_frame, 6 + 6*self.current_frame])[1:-1] 67 | return (self.frames[f] , [list1, list2]) 68 | 69 | 70 | -------------------------------------------------------------------------------- /Pytorch/curve.py: -------------------------------------------------------------------------------- 1 | # Import the relevant tools 2 | import numpy as np # standard array library 3 | import torch 4 | 5 | # Display routines : 6 | import matplotlib.cm as cm 7 | import matplotlib.pyplot as plt 8 | import matplotlib.colors as colors 9 | from matplotlib.collections import LineCollection 10 | from pyvtk import VtkData # from '.vtk' to Curves objects 11 | 12 | from input_output import level_curves 13 | 14 | # Curve representations ========================================================================= 15 | 16 | class Curve : 17 | "Encodes a 2D curve as an array of float coordinates + a connectivity list." 18 | def __init__(self, points, connectivity) : 19 | "points should be a n-by-2 float array, connectivity an nsegments-by-2 int array." 20 | self.points = points 21 | self.connectivity = connectivity 22 | 23 | def segments(self) : 24 | "Returns the list of segments the curve is made of." 25 | return np.array( [ [self.points[l[0]], self.points[l[1]]] for l in self.connectivity ] ) 26 | 27 | def to_measure(self) : 28 | """ 29 | Outputs the sum-of-diracs measure associated to the curve. 30 | Each segment from the connectivity matrix self.c 31 | is represented as a weighted dirac located at its center, 32 | with weight equal to the segment length. 33 | """ 34 | segments = self.segments() 35 | centers = [ .5 * ( seg[0] + seg[1] ) for seg in segments ] 36 | lengths = [np.sqrt(np.sum( (seg[1] - seg[0])**2 )) for seg in segments ] 37 | return ( np.array(centers), np.array(lengths) ) 38 | 39 | @staticmethod 40 | def _vertices_to_measure( q, connec ) : 41 | """ 42 | Transforms a torch array 'q1' into a measure, assuming a connectivity matrix connec. 43 | It is the Torch equivalent of 'to_measure'. 44 | """ 45 | a = q[connec[:,0]] ; b = q[connec[:,1]] 46 | # A curve is represented as a sum of diracs, one for each segment 47 | x = .5 * (a + b) # Mean 48 | mu = torch.sqrt( ((b-a)**2).sum(1) ) # Length 49 | return (x, mu) 50 | 51 | def plot(self, ax, color = 'rainbow', linewidth = 3) : 52 | "Simple display using a per-id color scheme." 53 | segs = self.segments() 54 | 55 | if color == 'rainbow' : # rainbow color scheme to see pointwise displacements 56 | ncycles = 5 57 | cNorm = colors.Normalize(vmin=0, vmax=(len(segs)-1)/ncycles) 58 | scalarMap = cm.ScalarMappable(norm=cNorm, cmap=plt.get_cmap('hsv') ) 59 | seg_colors = [ scalarMap.to_rgba( i % ((len(segs)-1)/ncycles) ) 60 | for i in range(len(segs)) ] 61 | else : # uniform color 62 | seg_colors = [ color for i in range(len(segs)) ] 63 | 64 | line_segments = LineCollection(segs, linewidths=(linewidth,), 65 | colors=seg_colors, linestyle='solid') 66 | ax.add_collection(line_segments) 67 | 68 | @staticmethod 69 | def from_file(fname) : 70 | if fname[-4:] == '.png' : 71 | (points, connec) = level_curves(fname) 72 | return Curve(points, connec) 73 | elif fname[-4:] == '.vtk' : 74 | data = VtkData(fname) 75 | points = np.array(data.structure.points)[:,0:2] # Discard "Z" 76 | connec = np.array(data.structure.polygons) 77 | return Curve((points + 150)/300, connec) # offset for the skull dataset... 78 | 79 | 80 | -------------------------------------------------------------------------------- /matlab/Bin/io/import_fshape_vtk.m: -------------------------------------------------------------------------------- 1 | function fshape = import_fshape_vtk(filename) 2 | % IMPORT_VTK(filename) import a vtk file as a fshape structure. 3 | % 4 | %Input : 5 | % path : string path to file 6 | %Output : 7 | % fshape : struct('x',...,'G',...,'f',...) 8 | % 9 | % See also : import_fshape_ply, import_fshape_obj 10 | % Author : B. Charlier (2017) 11 | 12 | [fshape.x,fshape.G,fshape.f] = read_vtk(filename); 13 | 14 | 15 | end 16 | 17 | function [vertex,face,signal] = read_vtk(filename) 18 | 19 | % read_vtk - read data from VTK file. (Based on a work Mario Richtsfeld) 20 | % 21 | % [vertex,face] = read_vtk(filename, verbose); 22 | % 23 | % 'vertex' is a 'nb.vert x 3' array specifying the position of the vertices. 24 | % 'face' is a 'nb.face x 2' (POLYGONS) or 'nb.face x 2' (LINES) array specifying the connectivity of the mesh. 25 | 26 | 27 | 28 | fid = fopen(filename,'r'); 29 | 30 | %--------------- 31 | % read header 32 | %---------------- 33 | 34 | if( fid==-1 ) 35 | error('Can''t open the file.'); 36 | end 37 | 38 | str = fgets(fid); % -1 if eof 39 | if ~strcmp(str(3:5), 'vtk') 40 | error('The file is not a valid VTK one.'); 41 | end 42 | 43 | %jump 3 lines 44 | [~] = fgets(fid); 45 | [~] = fgets(fid); 46 | [~] = fgets(fid); 47 | 48 | %---------------- 49 | % read vertices 50 | %---------------- 51 | 52 | str = fgets(fid); 53 | info = sscanf(str,'%s %*s %*s', 6); 54 | 55 | if strcmp(info,'POINTS') 56 | nvert = sscanf(str,'%*s %d %*s', 1); 57 | [A,cnt] = fscanf(fid,'%G ', 3*nvert); 58 | if cnt~=3*nvert 59 | warning('Problem in reading vertices.'); 60 | end 61 | A = reshape(A, 3, cnt/3); 62 | vertex = A'; 63 | end 64 | 65 | %---------------- 66 | % read polygons 67 | %---------------- 68 | 69 | str = fgets(fid); 70 | info = sscanf(str,'%s %*s %*s'); 71 | 72 | if strcmp(info,'POLYGONS') || strcmp(info,'LINES') 73 | nface = sscanf(str,'%*s %d %d', 2); 74 | [A,cnt] = fscanf(fid,'%d ', nface(2)); 75 | if cnt~=nface(2) 76 | warning('Problem in reading faces.'); 77 | end 78 | A = reshape(A, nface(2)/nface(1),nface(1)); 79 | face = (A(2:end,:)+1)'; 80 | else 81 | error('Problem in reading faces.') 82 | end 83 | 84 | %------------------- 85 | % read signal 86 | %------------------- 87 | 88 | try 89 | str = fgets(fid); 90 | info = sscanf(str,'%s %*s', 10); 91 | 92 | if strcmp(info,'POINT_DATA') 93 | 94 | nvertex = sscanf(str,'%*s %d', 1); 95 | [~] = fgets(fid); 96 | [~] = fgets(fid); 97 | 98 | [signal,cnt] = fscanf(fid,'%G', nvertex); 99 | if cnt~=nvertex 100 | error('Problem in reading signal.'); 101 | end 102 | elseif strcmp(info,'CELL_DATA') 103 | nface = sscanf(str,'%*s %d', 1); 104 | [~] = fgets(fid); 105 | [~] = fgets(fid); 106 | 107 | [signal,cnt] = fscanf(fid,'%G', nface); 108 | if cnt~=nface 109 | error('Problem in reading signal.'); 110 | end 111 | else 112 | error('Problem in reading signal.'); 113 | end 114 | catch 115 | signal = zeros( [size(vertex,1) ,1] ); 116 | end 117 | 118 | 119 | fclose(fid); 120 | 121 | end 122 | -------------------------------------------------------------------------------- /LDDMM_Python/lddmm_python/modules/models/free_atlas.py: -------------------------------------------------------------------------------- 1 | from pylab import * 2 | 3 | from .atlas import Atlas 4 | from ..manifolds.curves import Curve 5 | 6 | class FreeAtlas(Atlas): 7 | "Atlas with a Free mean Q0 and no dimensional constraint." 8 | def __init__(self, *args, **kwargs): 9 | Atlas.__init__(self, *args, **kwargs) 10 | def after_step_Q0(self, dQ0) : 11 | return self.Q0 + dQ0 # Free templates 12 | def after_step_P(self, dP) : 13 | return [ p + dp for (p,dp) in zip(self.P, dP)] # No dimensional constraint 14 | def template_cost(self, *args) : 15 | return 0 # Free template 16 | def normalize_and_regularize_template_updates(self, dQ0p, iteration) : 17 | dQ0p = self.normalize_template_updates(dQ0p, self.M.displacement_norm(dQ0p), iteration) 18 | dQ0 = self.M.sum_position(self.Q0, dQ0p) 19 | 20 | # This whole Free template stuff is more or less a hack, 21 | # as it is not a well defined problem (flat prior on an unbounded space), 22 | # so it's put here without too much care. 23 | if self.reg_template_gradient is not None : 24 | if self.reg_template_gradient[0] == 'gaussian' and type(self.reg_template_gradient[1]) is float : 25 | if self.reg_template_gradient[1] > 0 : 26 | if type(dQ0) is ndarray : 27 | None 28 | elif type(dQ0) is Curve : 29 | None 30 | else : 31 | print("I don't know how to regularize this type of gradient.") 32 | raise NotImplementedError 33 | else : 34 | print('This regularization type for the free template is not implemented : ', self.reg_template_gradient) 35 | raise NotImplementedError 36 | 37 | return dQ0 38 | def regularize_template_gradient(self, grad) : 39 | "Free template gradient regularization." 40 | if self.reg_template_gradient[0] == 'gaussian' and type(self.reg_template_gradient[1]) is float : 41 | if self.reg_template_gradient[1] > 0 : 42 | K = self.M.precompute_kernels(self.Q0)[0] 43 | if type(grad) is ndarray : 44 | grad_p = grad.reshape((self.M.npoints, self.M.dimension)) 45 | return (K @ grad_p).ravel() 46 | elif type(grad) is Curve : 47 | C = self.Q0 # assume it's a curve 48 | M = C.to_measure() 49 | 50 | mutilde = zeros(C.array_shape()[0]) 51 | for (i,s) in enumerate(C.connectivity) : 52 | mutilde[s[0]] += .5 * M.weights[i] 53 | mutilde[s[1]] += .5 * M.weights[i] 54 | 55 | K = K * (atleast_2d(K.dot(mutilde)).T * mutilde) 56 | grad.points = (K @ grad.to_array()).ravel() 57 | return grad 58 | else : 59 | print("I don't know how to regularize this type of gradient.") 60 | raise NotImplementedError 61 | else : 62 | print('This regularization type for the free template is not implemented : ', self.reg_template_gradient) 63 | raise NotImplementedError 64 | 65 | def show_HT(self) : 66 | None # nothing to show... 67 | def get_frame(self, f) : 68 | # Five plotly traces per frame : 'Frechet Mean', 'Shootings', 'Targets', 'Models', 'Transports' 69 | list1 = str([ 1 + 5*self.current_frame, 2 + 5*self.current_frame, 3 + 5*self.current_frame, 4 + 5*self.current_frame, 5 + 5*self.current_frame])[1:-1] 70 | self.current_frame = f 71 | list2 = str([ 1 + 5*self.current_frame, 2 + 5*self.current_frame, 3 + 5*self.current_frame, 4 + 5*self.current_frame, 5 + 5*self.current_frame])[1:-1] 72 | return (self.frames[f] , [list1, list2]) 73 | -------------------------------------------------------------------------------- /matlab/Bin/norms/shape/wasserstein/sinkhorn_log.m: -------------------------------------------------------------------------------- 1 | function [u,v,gamma,Wprimal,Wdual,err] = sinkhorn_log(mu,nu,c,epsilon,options) 2 | % sinkhorn_log - stabilized sinkhorn over log domain with acceleration 3 | % 4 | % [u,v,Wprimal,Wdual,err] = sinkhorn_log(mu,nu,c,epsilon,options); 5 | % 6 | % mu and nu are marginals. 7 | % c is cost 8 | % epsilon is regularization 9 | % coupling is 10 | % gamma = exp( (-c+u*ones(1,N(2))+ones(N(1),1)*v')/epsilon ); 11 | % 12 | % options.niter is the number of iterations. 13 | % options.tau is an avering step. 14 | % - tau=0 is usual sinkhorn 15 | % - tau<0 produces extrapolation and can usually accelerate. 16 | % 17 | % options.rho controls the amount of mass variation. Large value of rho 18 | % impose strong constraint on mass conservation. rho=Inf (default) 19 | % corresponds to the usual OT (balanced setting). 20 | % Author : B. Charlier (2017) 21 | 22 | 23 | options.null = 0; 24 | niter = getoptions(options, 'niter', 1000); 25 | tau = getoptions(options, 'tau', -.5); 26 | rho = getoptions(options, 'rho', Inf); 27 | record_evol = getoptions(options, 'record_evol', 0); 28 | 29 | 30 | lambda = rho/(rho+epsilon); 31 | if rho==Inf 32 | lambda=1; 33 | end 34 | 35 | % Sinkhorn 36 | N = [size(mu,1) size(nu,1)]; 37 | ave = @(tau, u,u1)tau*u+(1-tau)*u1; 38 | lse = @(A)logReg(sum(exp(A),2)); 39 | M = @(u,v)(-c+ repmat(u,1,N(2)) + repmat(v',N(1), 1) )/epsilon; 40 | 41 | if record_evol %only if needed! 42 | err = zeros(niter,1); 43 | Wprimal = zeros(niter,1); 44 | Wdual = zeros(niter,1); 45 | end 46 | 47 | u = zeros(N(1),1); 48 | v = zeros(N(2),1); 49 | 50 | 51 | for i=1:niter 52 | 53 | u1 = u; 54 | u = ave(tau, u, ... 55 | lambda*epsilon*log(mu) - lambda*epsilon*lse( M(u,v) ) + lambda*u ); 56 | 57 | v = ave(tau, v, ... 58 | lambda*epsilon*log(nu) - lambda*epsilon*lse( M(u,v)' ) + lambda*v ); 59 | 60 | if record_evol %only if needed! 61 | % coupling 62 | gamma = exp(M(u,v)); 63 | [Wprimal(i),Wdual(i),err(i)]= objfunction(u,u1,v,nu,mu,c,gamma,rho,epsilon); 64 | end 65 | 66 | end 67 | 68 | % prepare output 69 | 70 | if ~record_evol 71 | % coupling 72 | gamma = exp(M(u,v)); 73 | [Wprimal,Wdual,err]= objfunction(u,u1,v,nu,mu,c,gamma,rho,epsilon); 74 | 75 | end 76 | 77 | end 78 | 79 | 80 | 81 | function [Wprimal,Wdual,err]= objfunction(u,u1,v,nu,mu,c,gamma,rho,epsilon) 82 | 83 | % kullback divergence 84 | H = @(p)-sum( p(:).*(logReg(p(:))-1) ); 85 | KL = @(h,p)sum( h(:).*log( h(:)./p(:) ) - h(:)+p(:) ); 86 | KLd = @(u,p)sum( p(:).*(exp(-u(:))-1) ); 87 | dotp = @(x,y)sum(x(:).*y(:)); 88 | 89 | 90 | if rho==Inf % marginal violation 91 | 92 | Wprimal = dotp(c,gamma) - epsilon*H(gamma); 93 | Wdual = dotp(u,mu) + dotp(v,nu) ... 94 | - epsilon*sum( gamma(:) ); 95 | err = norm( sum(gamma,2)-mu ); 96 | 97 | else % difference with previous iterate 98 | 99 | Wprimal = dotp(c,gamma) - epsilon*H(gamma) ... 100 | + rho*KL(sum(gamma,2),mu) ... 101 | + rho*KL(sum(gamma,1),nu); 102 | Wdual = -rho*KLd(u/rho,mu) - rho*KLd(v/rho,nu) ... 103 | - epsilon*sum( gamma(:) ); 104 | err = norm(u(:)-u1(:), 1); 105 | 106 | end 107 | 108 | end 109 | 110 | function r = logReg(x) 111 | r = log(x+eps); 112 | end 113 | -------------------------------------------------------------------------------- /matlab/Bin/models/matching/geom/jnfmatch_geom.m: -------------------------------------------------------------------------------- 1 | function [momentums,summary]=jnfmatch_geom(source,momentumsInit,defo,objfun,optim) 2 | % Jackknife Match shape. It computes a matching between shapes using a bfgs 3 | % optimization scheme. 4 | % 5 | % Inputs: 6 | % templateInit: is a cell array of fshapes containing the initial mean template. 7 | % momentumsInit : a cell array with momentums 8 | % funresInit : a cell array with functional residuals. 9 | % defo: is a structure containing the parameters of the deformations. 10 | % objfun: is a structure containing the parameters of attachment term. 11 | % optim: is a structure containing the parameters of the optimization procedure (here gradient descent with adaptative step) 12 | % 13 | % Outputs: 14 | % meantemplate : a cell array of fshapes containing the mean template 15 | % momentums: a cell array with momentums 16 | % funres: a cell array with functional residuals. 17 | % summary: is a structure containing various informations about the 18 | % gradient descent. 19 | % 20 | % See also : enr_tan_free, denr_tan_free, fsatlas_tan_free 21 | % Author : B. Charlier (2017) 22 | 23 | 24 | global data templateG objfunc defoc deflag templatexc templatefc 25 | 26 | 27 | %------% 28 | % Init % 29 | %------% 30 | 31 | % check data 32 | if isempty(data) 33 | error('Check that data is global variable.') 34 | end 35 | nb_obs = size(data,1); %number of observations 36 | nb_match = size(data,2); % number of shape in each observation 37 | 38 | % check template 39 | if ~iscell(source) 40 | source={source}; 41 | end 42 | n = sum(cellfun(@(y) size(y.x,1),source)); %total number of points 43 | deflag = [0,cumsum(cellfun(@(y) size(y.x,1),source))]; 44 | d = size(source{1}.x,2); % dimension of the ambient space 45 | 46 | 47 | templateG = cellfun(@(y) y.G,source,'uniformOutput',0); 48 | templatexc = cellfun(@(y) y.x,source,'uniformOutput',0); 49 | templatefc = cellfun(@(y) y.f,source,'uniformOutput',0); 50 | 51 | % print some informations 52 | disp_info_dimension(data,source); 53 | 54 | 55 | % check momentums 56 | if isempty(momentumsInit) 57 | momentums = zeros(d*n,1); 58 | end 59 | 60 | %-----------% 61 | % options % 62 | %-----------% 63 | 64 | list_of_variables = {'p'}; 65 | 66 | 67 | % check functional residuals 68 | if ~iscell(objfun) 69 | objfun ={objfun}; 70 | objfun = objfun(ones(1,size(data,2))); 71 | end 72 | objfun = set_objfun_option(objfun,source,data,list_of_variables); 73 | % compute normalization coefficients 74 | objfun = compute_coefficents_normalization(objfun,source,data); 75 | 76 | defoc = set_defo_option(defo,list_of_variables); 77 | 78 | optim = set_optim_option(optim,objfun,list_of_variables,'enr_geom'); 79 | 80 | %-----------% 81 | % Call bfgs % 82 | %-----------% 83 | 84 | objfunc = objfun; 85 | 86 | tstart = tic; 87 | 88 | [momentums,summary] = perform_bfgs(optim.bfgs.enr_name,momentums,optim.bfgs); 89 | 90 | momentums = reshape(momentums,n,d); 91 | 92 | % disp informations 93 | telapsed = toc(tstart); 94 | fprintf('\nTotal number of iterations : %d in %g sec (%g sec per it)\n\n',summary.bfgs.nb_of_iterations,telapsed,telapsed/summary.bfgs.nb_of_iterations); 95 | 96 | 97 | % Summary information : save real parameters 98 | summary.parameters.defo = defoc; 99 | summary.parameters.objfun = objfun; 100 | summary.parameters.optim = optim; 101 | 102 | end 103 | 104 | -------------------------------------------------------------------------------- /matlab/Bin/deformations/tangential/shoot_and_flow_tan.m: -------------------------------------------------------------------------------- 1 | function [points_evol,obj_evol,mom_evol] = shoot_and_flow_tan(points,mom,defo,obj) 2 | % [points_evol,obj_evol,mom_evol] = SHOOT_AND_FLOW(points_init,mom_init,defo,obj) computes the evolution of 3 | % obj under the deformation generated by the couple points/momentums via the Hamiltonian dynamics. 4 | % 5 | % Input : 6 | % points_init : initial coordinates of the points (position) in a (n x d) matrix. 7 | % mom_init : initial momentums in a (n x d) matrix. 8 | % defo : structure containing the parameters of deformations (kernel_size_mom,method,nstep,...) 9 | % obj : initial coordinate of the object to be flown (if not set, assume obj = x) 10 | % 11 | % Output 12 | % points_evol : a cell list containing evolution path of positions ( points_evol{i} is a n x d matrix and i ranges from 1 to defo_options.nstep+1) 13 | % obj_evol : a cell list containing evolution path of object ( obj_evol{i} is a n x d matrix and i ranges from 1 to defo_options.nstep+1) 14 | % mom_evol : a cell list containing evolution path of momentums ( p_evol{i} is a n x d matrix and i ranges from 1 to defo_options.nstep+1) 15 | % Author : B. Charlier (2017) 16 | 17 | 18 | [points_evol,mom_evol] = forward_tan(points,mom,defo); 19 | 20 | if nargin==4 21 | obj_evol = flow(obj,points_evol,mom_evol,defo); 22 | else 23 | obj_evol =points_evol; 24 | end 25 | 26 | end 27 | 28 | 29 | function [obj_evol] = flow(obj,x,p,defo) 30 | % computes the evolution of the obj under the flow generated by x/p. 31 | 32 | h = 1 ./ defo.nb_euler_steps; 33 | 34 | switch defo.method 35 | case 'cuda' 36 | eulerStep = @euler_cuda; 37 | case 'matlab' 38 | eulerStep = @euler_mat; 39 | case 'grid' 40 | eulerStep = @euler_grid; 41 | end 42 | 43 | obj_evol= cell(1,defo.nb_euler_steps +1); 44 | obj_evol{1} = obj; 45 | 46 | for i = 1:defo.nb_euler_steps 47 | % Midpoint method 48 | obj1 = eulerStep(x{i},p{i},obj_evol{i},defo,h/2); 49 | obj2 = eulerStep((x{i}+x{i+1})/2,(p{i} + p{i+1})/2,obj1,defo,h); 50 | 51 | obj_evol{i+1} = obj2 - obj1 + obj_evol{i}; 52 | end 53 | 54 | end 55 | 56 | function [nobj] = euler_cuda(x,p,obj,defo,h) 57 | % This function implements an elementary Euler Step in cuda 58 | nobj = obj; 59 | for lam = defo.kernel_size_mom 60 | nobj = nobj + h * GaussGpuConv(obj',x',p',lam)'; 61 | end 62 | 63 | end 64 | 65 | function [nobj] = euler_mat(x,p,obj,defo,h) 66 | % This function implements an elementary Euler Step in cuda 67 | 68 | [nx,d]=size(x); 69 | [ny,~]=size(obj); 70 | 71 | % Calcul de A=exp(-|x_i -x_j|^2/(lam^2)) 72 | S=zeros(ny,nx); 73 | for l=1:d 74 | S=S+(repmat(obj(:,l),1,nx)-repmat(x(:,l)',ny,1)).^2; 75 | end 76 | A = rho(S,0,defo.kernel_size_mom); 77 | 78 | nobj = obj + h * A*p; 79 | 80 | end 81 | 82 | function [nobj] = euler_grid(x,p,obj,defo,h) 83 | % This function implements an elementary Euler Step in cuda 84 | 85 | %generate grid 86 | bbox.min = min([x;obj],[],1)';bbox.max= max([x;obj],[],1)'; 87 | do_grad=0;do_gradgrad=0; 88 | if ~isfield(defo,'sourcegrid') 89 | newGrid =1; 90 | else 91 | newGrid = changegrid(bbox.min,bbox.max,defo.kernel_size_mom,defo.gridratio,defo.sourcegrid); 92 | end 93 | 94 | if newGrid 95 | sourcegrid = setgrid(bbox,defo.kernel_size_mom,defo.gridratio,do_grad,do_gradgrad); 96 | else 97 | sourcegrid =defo.sourcegrid; 98 | end 99 | 100 | nobj = obj; 101 | for t = 1:size(sourcegrid.pas,2) 102 | nobj = nobj + h* gridOptimNew(x',p',obj',sourcegrid.long(:,t)',sourcegrid.pas(:,t),sourcegrid.origine(:,t),sourcegrid.fft3k_d{t},0)'; 103 | end 104 | 105 | end 106 | -------------------------------------------------------------------------------- /Simple_script/pytorch_memory_overflow.py: -------------------------------------------------------------------------------- 1 | NPOINTS = 10000 2 | 3 | # Variable definitions, etc. for this minimal working example. ---------------------------------- 4 | # You don't need to read this to understand the bottlneck. 5 | # Import the relevant tools 6 | import numpy as np # standard array library 7 | import torch 8 | from torch.autograd import Variable 9 | 10 | use_cuda = torch.cuda.is_available() 11 | dtype = torch.cuda.FloatTensor if use_cuda else torch.FloatTensor 12 | 13 | # Computation of the Kernel Matrix : 14 | def _squared_distances(x, y) : 15 | "Returns the matrix of |x_i-y_j|^2." 16 | x_col = x.unsqueeze(1) ; y_lin = y.unsqueeze(0) 17 | return torch.sum( (x_col - y_lin)**2 , 2 ) 18 | def _k(x, y, s) : 19 | "Returns the matrix of k(x_i,y_j)." 20 | sq = _squared_distances(x, y) / (s**2) 21 | return torch.exp( -sq ) 22 | 23 | 24 | t = np.linspace(0, 2*np.pi, NPOINTS) 25 | weights = np.ones( (NPOINTS,) ) /NPOINTS 26 | 27 | X = Variable(torch.from_numpy( np.vstack([np.cos(t), np.sin(t)]).T ).type(dtype), requires_grad=True ) 28 | Y = Variable(torch.from_numpy( np.vstack([np.cos(t)+1, np.sin(t)]).T ).type(dtype), requires_grad=True ) 29 | P = Variable(torch.from_numpy( weights ).type(dtype), requires_grad=False) 30 | Q = Variable(torch.from_numpy( weights ).type(dtype), requires_grad=False) 31 | 32 | # The meaningful part of the program, aka "The Sinkhorn Algorithm" ------------------------------ 33 | # Iterating this simple "for" loop is an efficient way of finding the optimal scaling 34 | # factors A and B such that Gamma = diag(A)*K*diag(B) has : 35 | # - row-wise sums equal to P 36 | # - column-wise sums equal to Q 37 | # Since the publication of the milestone paper : 38 | # "Sinkhorn Distances: Lightspeed Computation of Optimal Transport", Marco Cuturi (2013), 39 | # who proposed to use this scheme to compute Optimal Transport plans (Monge-Kantorovitch theory), 40 | # this algorithm has generated a considerable interest in some applied maths and 41 | # image registration communities. 42 | # 43 | # This algorithm showcases the typical features of state-of-the-art methods in the field 44 | # of medical image registration (major conference on the topic : MICCAI) : 45 | # 46 | # - "small" datasets, but each image has a large memory footprint 47 | # (say, 256x256x256 images, or >50,000 triangles for a segmented brain surface). 48 | # 49 | # - "diffeomorphic" (that is, tearing-free) registration algorithms, which iterate a simple 50 | # linear algebra operation on the data. 51 | # Here, we iterate a matrix-vector product + pointwise division, 52 | # but other pipelines will flow a vector field through time [t, t+dt] using an ODE step 53 | # such as Euler (simplistic) or Runge-Kutta, etc. 54 | # 55 | # - output is a matching score, whose gradient shall be used to update the registration. 56 | # 57 | 58 | K = _k( X, Y, .5) # Gaussian Kernel matrix (Npoints-by-Npoints), regularization parameter = .5 59 | A = Variable(torch.ones( NPOINTS ).type(dtype), requires_grad = False) 60 | B = Variable(torch.ones( NPOINTS ).type(dtype), requires_grad = False) 61 | 62 | for it in range(1000) : 63 | A = P / (K @ B) 64 | B = Q / (K.t() @ A) 65 | 66 | Gamma = (A.unsqueeze(1) @ B.unsqueeze(0)) * K # Gamma_ij = a_i * b_j * k( x_i , y_j ) 67 | Cost = torch.sum( Gamma * _squared_distances(X,Y) ) 68 | # The above cost can be used as a distance measure between the unlabeled points clouds X and Y. 69 | print(Cost) 70 | 71 | # In practice, target Y is fixed and we're looking for the X-gradient of the Cost. 72 | dX = torch.autograd.grad( Cost , X ) 73 | print(dX) 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /matlab/Bin/models/matching/tan/jnfmatch_tan.m: -------------------------------------------------------------------------------- 1 | function [momentums,summary]=jnfmatch_tan(templateInit,momentumsInit,funresInit,defo,objfun,optim) 2 | % Jackknife Mean fshape estimation in the 'tangential' and 'free' framework. 3 | % This is a gradient descent for cost function computed in enr_tan_free. 4 | % 5 | % Inputs: 6 | % templateInit: is a cell array of fshapes containing the initial mean template. 7 | % momentumsInit : a cell array with momentums 8 | % funresInit : a cell array with functional residuals. 9 | % defo: is a structure containing the parameters of the deformations. 10 | % objfun: is a structure containing the parameters of attachment term. 11 | % optim: is a structure containing the parameters of the optimization procedure (here gradient descent with adaptative step) 12 | % 13 | % Outputs: 14 | % meantemplate : a cell array of fshapes containing the mean template 15 | % momentums: a cell array with momentums 16 | % funres: a cell array with functional residuals. 17 | % summary: is a structure containing various informations about the 18 | % gradient descent. 19 | % 20 | % See also : enr_tan_free, denr_tan_free, fsatlas_tan_free 21 | % Author : B. Charlier (2017) 22 | 23 | 24 | global data templateG objfunc defoc deflag templatexc templatefc 25 | 26 | %------% 27 | % Init % 28 | %------% 29 | 30 | % check data 31 | if isempty(data) 32 | error('Check that data is global variable.') 33 | end 34 | nb_obs = size(data,1); %number of observations 35 | nb_match = size(data,2); % number of shape in each observation 36 | 37 | % check template 38 | if ~iscell(templateInit) 39 | templateInit={templateInit}; 40 | end 41 | 42 | deflag = [0,cumsum(cellfun(@(y) size(y.x,1),templateInit))]; 43 | n = deflag(end); 44 | d = size(templateInit{1}.x,2); % dimension of the ambient space 45 | 46 | templateG = cellfun(@(y) y.G,templateInit,'uniformOutput',0); 47 | templatexc = cellfun(@(y) y.x,templateInit,'uniformOutput',0); 48 | templatefc = cellfun(@(y) y.f,templateInit,'uniformOutput',0); 49 | 50 | 51 | % print some informations 52 | disp_info_dimension(data,templateInit); 53 | 54 | % check momentums 55 | if isempty(momentumsInit) 56 | momentums = zeros(d*n,1); 57 | else 58 | momentums = momentumsInit; 59 | end 60 | 61 | 62 | %-----------% 63 | % options % 64 | %-----------% 65 | 66 | list_of_variables = {'p','fr'}; 67 | 68 | if ~iscell(objfun) 69 | objfun ={objfun}; 70 | objfun = objfun(ones(1,size(data,2))); 71 | end 72 | objfun = set_objfun_option(objfun,templateInit,data,list_of_variables); 73 | % compute normalization coefficients 74 | objfun = compute_coefficents_normalization(objfun,templateInit,data); 75 | 76 | defoc = set_defo_option(defo,list_of_variables); 77 | 78 | optim = set_optim_option(optim,objfun,list_of_variables,'enr_match_tan'); 79 | 80 | 81 | %------------------% 82 | % BFGS % 83 | %------------------% 84 | 85 | tstart = tic; 86 | objfunc = objfun; 87 | 88 | [mom,summary] = perform_bfgs(optim.bfgs.enr_name,momentums,optim.bfgs); 89 | 90 | momentums = reshape(mom(1:n*d),n,d); 91 | 92 | 93 | % disp informations 94 | telapsed = toc(tstart); 95 | fprintf('\nTotal number of iterations : %d in %g sec (%g sec per it)\n\n',summary.bfgs.nb_of_iterations,telapsed,telapsed/summary.bfgs.nb_of_iterations); 96 | 97 | 98 | % Prepare Output 99 | meantemplate = cell(1,nb_match); 100 | for l=1:nb_match 101 | meantemplate{1,l} = struct('x',templatexc{l},'f',templatefc{l},'G',templateG{l}); 102 | end 103 | 104 | % Summary information : save real parameters 105 | summary.parameters.defo = defoc; 106 | summary.parameters.objfun = objfun; 107 | summary.parameters.optim = optim; 108 | 109 | end 110 | 111 | -------------------------------------------------------------------------------- /matlab/Bin/optim/hanso (third party)/setdefaultshanso.m: -------------------------------------------------------------------------------- 1 | function options = setdefaultshanso(pars, options) 2 | % set HANSO defaults that are not set by setdefaults 3 | % called only by hanso 4 | % 5 | % Send comments/bug reports to Michael Overton, overton@cs.nyu.edu, 6 | % with a subject header containing the string "hanso". 7 | % Version 2.2, 2016, see GPL license info below. 8 | 9 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 10 | %% HANSO 2.2 Copyright (C) 2010 Michael Overton 11 | %% This program is free software: you can redistribute it and/or modify 12 | %% it under the terms of the GNU General Public License as published by 13 | %% the Free Software Foundation, either version 3 of the License, or 14 | %% (at your option) any later version. 15 | %% 16 | %% This program is distributed in the hope that it will be useful, 17 | %% but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | %% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | %% GNU General Public License for more details. 20 | %% 21 | %% You should have received a copy of the GNU General Public License 22 | %% along with this program. If not, see . 23 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 24 | 25 | % this is also in setdefaults, but setdefaults_hanso is called first 26 | % so we need it here too, as pars.nvar is referenced below 27 | if ~isfield(pars, 'nvar') 28 | error('hanso: input "pars" must have a field "nvar" (number of variables)') 29 | elseif ~isposint(pars.nvar) 30 | error('hanso: input "pars.nvar" (number of variables) must be a positive integer') 31 | end 32 | nvar = pars.nvar; 33 | % the following isn't needed since it's in setdefaults, but may as well 34 | % include it so error message says "hanso" 35 | if ~isfield(pars, 'fgname') 36 | error('hanso: input "pars" must have a field "fgname" (name of m-file computing function and gradient)') 37 | end 38 | if ~isfield(options, 'normtol') 39 | options.normtol = 1e-4; 40 | elseif ~isposreal(options.normtol) 41 | error('hanso: input "options.normtol" must be a positive scalar') 42 | end 43 | if ~isfield(options, 'evaldist') 44 | options.evaldist = 1e-4; 45 | elseif ~isposreal(options.evaldist) 46 | error('hanso: input "options.evaldist" must be a positive scalar') 47 | end 48 | if ~isfield(options, 'samprad') 49 | % default is NO gradient sampling as of HANSO 2.2: too expensive 50 | options.samprad = []; % no gradient sampling 51 | else 52 | % check sampling radii are positive and decreasing 53 | if any(sort(options.samprad,'descend') ~= options.samprad) || any(options.samprad <= 0) 54 | error('options.samprad must have decreasing positive entries') 55 | end 56 | end 57 | % the following are from HANSO 1.0, 1.01 58 | % for backwards compatibility: 59 | if isfield(options, 'phasemaxit') 60 | if ~isfield(options, 'prtlevel') | options.prtlevel > 0 61 | fprintf('hanso: "options.phasemaxit" is no longer used in HANSO 2.0\n') 62 | fprintf(' setting "options.maxit" to "options.phasemaxit(1)"\n\n') 63 | end 64 | options.maxit = options.phasemaxit(1); % for BFGS (ignore the others) 65 | end 66 | if isfield(options, 'phasenum') 67 | if ~isfield(options, 'prtlevel') | options.prtlevel > 0 68 | fprintf('hanso: "options.phasenum" is no longer used in HANSO 2.0\n') 69 | fprintf(' number of BFGS starting points is either 10 or number of columns in "options.x0"\n') 70 | fprintf(' number of gradient sampling phases is 3, or 0 if pars.nvar > 100, or number of entries in options.gradsamp\n\n') 71 | end 72 | % ignore the number of phases specified and use defaults 73 | end -------------------------------------------------------------------------------- /matlab/Bin/models/atlas/tan_free/denr_tan_free.m: -------------------------------------------------------------------------------- 1 | function [dx,dp] = denr_tan_free(templatex,momentum) 2 | %[dx,df,dp,dfunres] = DENR_TAN_FREE(templatex,momentums) computes the gradient 3 | % of the energy functional coded in enr_tan_free. 4 | % 5 | % Input : 6 | % templatex : cell with the points position 7 | % momentums : cell with the momentums attached to each point 8 | % 9 | % Output : 10 | % dx : gradient wrt x 11 | % dp : gradient wrt momentums 12 | % Author : B. Charlier (2017) 13 | 14 | global data objfunc defoc deflag templateG 15 | 16 | [nb_obs,nb_match] = size(data); 17 | nlist = diff(deflag); % number of point in each shape 18 | 19 | dx = cell(1,nb_match); 20 | dp = cell(nb_obs,1); 21 | 22 | templatextotal = cell2mat(templatex'); [n,d] = size(templatextotal); 23 | 24 | %---------------------------% 25 | % gradient of penalization % 26 | %---------------------------% 27 | 28 | for l= 1:nb_match 29 | dx{l} = zeros(size(templatex{1,l})); 30 | end 31 | 32 | 33 | dX = cell(nb_obs,1); 34 | 35 | for sh_ind=1:nb_obs %parallel computations 36 | 37 | %sliced variable in parfor 38 | datac = data(sh_ind,:); 39 | momentumc = momentum{sh_ind}; 40 | 41 | %---------------------% 42 | % gradient dmatchterm % 43 | %---------------------% 44 | 45 | [shootingx,shootingmom]=forward_tan(templatextotal,momentum{sh_ind},defoc); 46 | 47 | dxfinalg= cell(1,nb_match); 48 | dfg= cell(1,nb_match); 49 | for l = 1:nb_match 50 | %load the shooted fshape (== final position) 51 | templatefinal= struct('x',shootingx{end}(deflag(l)+1:deflag(l+1),:),'f',zeros(size(shootingx{end}(deflag(l)+1:deflag(l+1),:),1),1),'G',templateG{l}); 52 | %load current target 53 | targetc = struct('x',datac{l}.x,'G',datac{l}.G); 54 | % gradient of the data attachment term wrt the final position 55 | [dxfinalg{l}]=dmatchterm(templatefinal,targetc,objfunc{l}); 56 | dxfinalg{l} = dxfinalg{l} .*objfunc{l}.weight_coef_dist ; 57 | 58 | %save template final 59 | export_fshape_vtk(templatefinal,['./',num2str(l),'-results_iter_c.vtk']); 60 | end 61 | 62 | %at the final position the derivative wrt the moment is 0 63 | dpfinalg=zeros(n,d); 64 | % integrate backward the adjoint system to get the gradient at init 65 | [dxg,dpg]=backward_tan(cell2mat(dxfinalg'),dpfinalg,struct('x',{shootingx},'mom',{shootingmom}),defoc); 66 | 67 | %----------------------------% 68 | % gradient of the prior part % 69 | %----------------------------% 70 | 71 | [dxu,dpu] = dnormRkhsV(templatextotal,momentumc,defoc); 72 | 73 | dXt = cell(1,nb_match); 74 | 75 | for l = 1:nb_match 76 | 77 | % Normalization in order to get a gradient scale invariant 78 | dxg(deflag(l)+1:deflag(l+1),:)=dxg(deflag(l)+1:deflag(l+1),:).*objfunc{l}.dgxC; 79 | dpg(deflag(l)+1:deflag(l+1),:)=dpg(deflag(l)+1:deflag(l+1),:).*objfunc{l}.dgxC; 80 | dfg{l}=dfg{l}.*objfunc{l}.dgfC; 81 | 82 | %-----------------------------------% 83 | % gradient of penalization (funres) % 84 | %-----------------------------------% 85 | dXt{l} = objfunc{1}.weight_coef_pen_p * dxu(deflag(l)+1:deflag(l+1),:) + dxg(deflag(l)+1:deflag(l+1),:); 86 | 87 | end 88 | 89 | dp{sh_ind} = objfunc{1}.weight_coef_pen_p *dpu +dpg; 90 | dX{sh_ind} = dXt; 91 | 92 | end 93 | 94 | for i= 1:nb_obs 95 | 96 | dx = cellfun(@(y,z) y+z,dx,dX{i},'uniformoutput',0); 97 | 98 | end 99 | 100 | 101 | 102 | for l=1:nb_match 103 | 104 | % Normalization of the gradient 105 | dx{l}=dx{l}*nlist(l); 106 | 107 | 108 | end 109 | 110 | dp= cellfun(@(y) y/n,dp,'UniformOutput',0); 111 | 112 | end 113 | -------------------------------------------------------------------------------- /matlab/Bin/deformations/tangential/ddHrtP_tan.m: -------------------------------------------------------------------------------- 1 | function [dPx,dPp] = ddHrtP_tan(x,p,Px,Pp,defo) 2 | % [dPx,dPp] = DDhRTP(x,p,Px,Pp,defo) computes the adjoints Hamiltonian 3 | % system usingthe methods given in defo.method. 4 | % 5 | % Inputs : 6 | % x: is a (n x d) matrix containing the points. 7 | % p: is a (n x d) matrix containing the momentums. 8 | % Px : is a (n x d) matrix (adjoint variable of x). 9 | % Pp : is a (n x d) matrix (adjoint variable of p ). 10 | % defo : structure containing the deformations parameters 11 | % 12 | % Outputs 13 | % dPx : (n x d) matrix containing the update of Px. 14 | % dPp :(n x d) matrix containing the update of Pp. 15 | % 16 | % See also : forward_tan, backward_tan, dHr_tan 17 | % Author : B. Charlier (2017) 18 | 19 | switch defo.method 20 | case 'cuda' 21 | DFTP = @dftP_cuda; 22 | otherwise 23 | DFTP = @dftP_mat; 24 | end 25 | 26 | [dPx,dPp] = DFTP(x,p,Px,Pp,defo); 27 | 28 | end 29 | 30 | 31 | 32 | function [dPx,dPp]=dftP_cuda(x,p,Px,Pp,defo) 33 | % Basic Euler step for the tangential Hamiltonian flow \deltaX_H using cuda mex file. 34 | % 35 | % Inputs : 36 | % x: is a (n x d) matrix containing the points. 37 | % p: is a (n x d) matrix containing the momentums. 38 | % Px : is a (n x d) matrix (adjoint variable x). 39 | % Pp : is a (n x d) matrix (adjoint variable momentums ). 40 | % defo : structure containing the deformations parameters 41 | % 42 | % Outputs 43 | % dPx : (n x d) matrix containing the update of Px. 44 | % dPp :(n x d) matrix containing the update of Pp. 45 | 46 | dPp = zeros(size(Pp)); 47 | dPx = zeros(size(Px)); 48 | 49 | for lam = defo.kernel_size_mom 50 | 51 | dPx = dPx - GaussGpuGradConv(p',x',Px',lam)'+ dxxHrP2(Pp',x',p',lam)'; 52 | dPp = dPp - GaussGpuConv(x',x',Px',lam)'+ dpxHrP2(Pp',x',p',lam)'; 53 | 54 | end 55 | 56 | end 57 | 58 | 59 | function [dPx,dPp]=dftP_mat(x,p,Px,Pp,defo) 60 | %Compute the [dPx;dPp] = dft([x;p]) * [Px;Pp] exactly with matlab. 61 | % 62 | % Inputs : 63 | % x: is a (n x d) matrix containing the points. 64 | % p: is a (n x d) matrix containing the momentums. 65 | % Px : is a (n x d) matrix (adjoint variable x). 66 | % Pp : is a (n x d) matrix (adjoint variable momentums ). 67 | % defo : structure containing the deformations parameters 68 | % 69 | % Outputs 70 | % dPx : (n x d) matrix containing the update of Px. 71 | % dPp :(n x d) matrix containing the update of Pp. 72 | 73 | 74 | lam=defo.kernel_size_mom; 75 | [n,d]=size(x); 76 | 77 | dPp = zeros(size(Pp)); 78 | dPx = zeros(size(Px)); 79 | 80 | % Calcul de A=exp(-|x_i -x_j|^2/(lam^2)) 81 | S=zeros(n); 82 | for l=1:d 83 | S=S+(repmat(x(:,l),1,n)-repmat(x(:,l)',n,1)).^2; 84 | end 85 | A=rho(S,0,lam); 86 | B=rho(S,1,lam); 87 | C=rho(S,2,lam); 88 | 89 | for r=1:d 90 | dPxr=zeros(n,1); 91 | dPpr=-A*Px(:,r); % [\partial_{p_i}\partial_{p_j} H_r ] * Px 92 | % Computation of Br 93 | Br=2*(repmat(x(:,r),1,n)-repmat(x(:,r)',n,1)).*B; 94 | 95 | for s=1:d 96 | Bs=2*(repmat(x(:,s),1,n)-repmat(x(:,s)',n,1)).*B; 97 | dPpr=dPpr+(Bs*p(:,r)).*Pp(:,s)-Bs*(p(:,r).*Pp(:,s));% ([Diag(\partial_{x_i}\partial_{p_i} H_r)] + [\partial_{x_i} \partial_{p_j}  H_r])* Pp 98 | 99 | dPxr=dPxr-(p(:,s).*(Br*Px(:,s))+Px(:,s).*(Br*p(:,s))); 100 | 101 | Crs=4*(repmat(x(:,r),1,n)-repmat(x(:,r)',n,1))... 102 | .*(repmat(x(:,s),1,n)-repmat(x(:,s)',n,1)).*C; 103 | if s==r 104 | Crs=Crs+2*B; 105 | end 106 | 107 | for l=1:d 108 | dPxr=dPxr+p(:,l).*... 109 | ((Crs*p(:,l)).*Pp(:,s)-Crs*(p(:,l).*Pp(:,s))); 110 | end 111 | end 112 | dPx(:,r)=dPxr; 113 | dPp(:,r)=dPpr; 114 | end 115 | 116 | 117 | end 118 | 119 | 120 | 121 | 122 | -------------------------------------------------------------------------------- /matlab/Bin/norms/shape/wasserstein/dfshape_wasserstein_distance.m: -------------------------------------------------------------------------------- 1 | function [dxg]= dfshape_wasserstein_distance(fs1,fs2,objfun) 2 | % DFSHAPE_KERNEL_DISTANCE(templatefinal,target,objfun) computes the derivatives of the kernel based 3 | % distances between fshapes. 4 | % 5 | % \sum_i\sum_j K_signal(f_i-g_j)^2) K_geom(-norm(x_i-y_j)^2) K_tan(angle(V_i,W_j)) 6 | % 7 | % Possible method are 'cuda' or 'matlab'. 8 | % 9 | % Inputs: 10 | % templatefinal : "fshape structure" containing the shooted template 11 | % target : "fshape structure" containing the target. 12 | % objfun : is a structure containing the data attachment term parameters (mandatory fields are : 'kernel_geom', 'kernel_signal' and 'kernel_grass' and the associated bandwidth) 13 | % Output 14 | % dxg : a matrix of the size of templatefinal.x. 15 | % dfg : a matrix of the size of templatefinal.f. 16 | % Author : B. Charlier (2017) 17 | 18 | 19 | 20 | %------------------------% 21 | % Start the chain's rule % 22 | %------------------------% 23 | 24 | d_ambient_space=size(fs1.x,2); 25 | m=size(fs1.G,2)-1; 26 | 27 | % discretize the fshapes 28 | [center_faceX,normalsX]=fcatoms(fs1.x,fs1.G); 29 | [center_faceY,normalsY]=fcatoms(fs2.x,fs2.G); 30 | 31 | options = objfun.wasserstein_distance; 32 | 33 | 34 | if min(m, d_ambient_space-m) ==0 % for points clouds or simplexes dim or codim == 0 : some simplifications occurs 35 | 36 | x=center_faceX'; 37 | y=center_faceY'; 38 | 39 | mu = fs1.G; 40 | nu = fs2.G; 41 | 42 | %only needed for matlab version. See built-in function for cuda version. 43 | nablaC = @(x,y)repmat(x,[1 1 size(y,2)]) - ... 44 | repmat(reshape(y,[size(y,1) 1 size(y,2)]),[1 size(x,2)]); 45 | C = @(x,y)squeeze( sum(nablaC(x,y).^2)/2 );% C(x,y)=1/2*|x-y|^2 46 | 47 | elseif min(m,d_ambient_space-m) ==1 % for curves or surface dim or codim ==1; 48 | 49 | x=[center_faceX';normalsX']; 50 | y=[center_faceY';normalsY']; 51 | 52 | mu = area(fs1.x,fs1.G); 53 | nu = area(fs2.x,fs2.G); 54 | 55 | %only needed for matlab version. See built-in function for cuda version. 56 | C = @(X,Y) cost_varifold(X,Y,options.weight_cost_varifold); 57 | nablaC = @(X,Y) dcost_varifold(X,Y,options.weight_cost_varifold); 58 | 59 | end 60 | 61 | 62 | switch options.method 63 | case 'matlab' 64 | 65 | [u,~,gamma,~,~,~] = sinkhorn_log(mu,nu,C(x,y),options.epsilon,options); 66 | 67 | % gradient with respect to positions 68 | DXg = sum( nablaC(x,y) .*... 69 | repmat(reshape(gamma, [1,size(mu,1),size(nu,1)]), [size(x,1),1,1]), ... 70 | 3 ); 71 | case 'cuda' 72 | 73 | [u,DXg] = dsinkhorn_log_cuda(mu,nu,x,y,options.epsilon,options,d_ambient_space); 74 | DXg = DXg'; 75 | 76 | end 77 | 78 | % gradient with respect to the weights 79 | if options.rho==Inf% balanced 80 | Dmug = u; 81 | else% unbalanced 82 | Dmug = -options.rho*(exp(-u/options.rho)-1); 83 | end 84 | 85 | % gradient with respect to the normal and centerFace 86 | if min(m,d_ambient_space-m) == 0 87 | 88 | Dcenter_faceXg = DXg(1:d_ambient_space,:)'; 89 | DnormalsXg = zeros(size(normalsX)); 90 | 91 | 92 | elseif min(m,d_ambient_space-m) ==1 93 | 94 | norm_normalsX = sqrt(sum(normalsX .^2,2)); 95 | unit_normalsX = normalsX ./ repmat(norm_normalsX,1,d_ambient_space); 96 | 97 | Dcenter_faceXg = DXg(1:d_ambient_space,:)'; 98 | DnormalsXg = repmat(Dmug,1,d_ambient_space) .*unit_normalsX+ DXg(d_ambient_space+1:2*d_ambient_space,:)'/2; 99 | 100 | 101 | end 102 | 103 | 104 | %-------------------------% 105 | % End of the chain's rule % 106 | %-------------------------% 107 | 108 | [dxg]= chain_rule(fs1.x,fs1.G,Dcenter_faceXg,DnormalsXg); 109 | 110 | 111 | end 112 | -------------------------------------------------------------------------------- /LDDMM_Python/lddmm_python/modules/io/anim3D.py: -------------------------------------------------------------------------------- 1 | # We use a slightly hacked version of the plot.ly js/python library 2 | lddmm_python = __import__(__name__.split('.')[0]) 3 | print(lddmm_python) 4 | import lddmm_python.lib.plotly as plotly 5 | 6 | import re 7 | from pylab import * 8 | from IPython.html.widgets import interact 9 | from IPython.display import HTML, display 10 | from pprint import pprint 11 | import json 12 | 13 | from plotly.tools import FigureFactory as FF 14 | from plotly import utils, graph_objs 15 | 16 | from .my_iplot import my_iplot 17 | from .read_vtk import ReadVTK 18 | 19 | 20 | class Anim3d : 21 | def __init__(self, filenames): 22 | self.frames = list(ReadVTK(f) for f in filenames) 23 | self.current_frame = list(range(len(self.frames))) 24 | print(self.current_frame) 25 | def get_frame(self, w) : 26 | points = array(self.frames[w][0]) 27 | """update = dict( 28 | x = [points[:,2]], 29 | y = [points[:,0]], 30 | z = [points[:,1]] 31 | )""" 32 | update1 = dict( 33 | visible = False 34 | ) 35 | update2 = dict( 36 | visible = True 37 | ) 38 | list1 = str(self.current_frame) 39 | self.current_frame = [w] 40 | list2 = str(self.current_frame) 41 | return ([update1, update2], [list1, list2]) 42 | def show(self, title): 43 | figs = [] 44 | for ind_f in range(len(self.frames)) : 45 | (points, triangles, signals) = self.frames[ind_f] 46 | points = array(points) 47 | triangles = array(triangles) 48 | signals = array(signals) 49 | signals_per_triangle = list( (signals[triangles[i,0]] + signals[triangles[i,1]] + signals[triangles[i,2]]) / 3 50 | for i in range(triangles.shape[0]) ) 51 | signals_per_triangle[0] += 0.001 52 | # Validate colormap 53 | my_colormap = FF._validate_colors("Portland", 'tuple') 54 | newdata = FF._trisurf(x=points[:,2], y=points[:,0], z=points[:,1], 55 | colormap=my_colormap, 56 | simplices=triangles, 57 | color_func = signals_per_triangle, 58 | plot_edges=False, 59 | edges_color = 'rgb(50, 50, 50)', 60 | show_colorbar = False, 61 | data_list = True) 62 | figs += newdata 63 | axis = dict( 64 | showbackground=True, 65 | backgroundcolor='rgb(230, 230, 230)', 66 | gridcolor='rgb(255, 255, 255)', 67 | zerolinecolor='rgb(255, 255, 255)' 68 | ) 69 | xaxis = axis.copy() 70 | xaxis['range'] = [-0.08,0.09] 71 | yaxis = axis.copy() 72 | yaxis['range'] = [-0.11,0.05] 73 | zaxis = axis.copy() 74 | zaxis['range'] = [0.02,0.18] 75 | aspectratio=dict(x=1, y=1, z=1) 76 | layout = graph_objs.Layout( 77 | title=title, 78 | width='100%', 79 | height= 800, 80 | scene=graph_objs.Scene( 81 | xaxis=graph_objs.XAxis(xaxis), 82 | yaxis=graph_objs.YAxis(yaxis), 83 | zaxis=graph_objs.ZAxis(zaxis), 84 | aspectratio=dict( 85 | x=aspectratio['x'], 86 | y=aspectratio['y'], 87 | z=aspectratio['z']), 88 | ) 89 | ) 90 | 91 | return my_iplot(graph_objs.Figure( data = figs, layout=layout)) 92 | def slider(self, div_id) : 93 | #div_id = self.show(*args, **kwargs) 94 | 95 | def change_frame(w) : 96 | (updates, indices) = self.get_frame(w-1) 97 | script = '' 98 | for i in range(len(updates)) : 99 | jupdate = json.dumps(updates[i], cls=utils.PlotlyJSONEncoder) 100 | #pprint(jupdate) 101 | script = script \ 102 | + 'Plotly.restyle("{id}", {update}, [{index}]);'.format( 103 | id=div_id, 104 | update=jupdate, index = indices[i][1:-1]) 105 | #print(script) 106 | update_str = ( 107 | '' 108 | '' 113 | '').format(script=script) 114 | display(HTML(update_str)) 115 | interact((lambda frame : change_frame(frame)), frame=(1,len(self.frames))) 116 | 117 | 118 | -------------------------------------------------------------------------------- /matlab/Bin/norms/shape/chain_rule.m: -------------------------------------------------------------------------------- 1 | function [dxg2]=chain_rule(x,tri,DXg,DXig) 2 | % 3 | % Computation of the gradient with respect to x by distributing the previous gradients 4 | % on points of the initial shape. (Chain's rule). There is two versions of the same 5 | % code somewhat equivalent : one using matlab for loop (that is not so bad 6 | % due to JIT precompilation process) and one using built in matlab function 7 | % accumarray. 8 | % 9 | % Input: 10 | % x: list of vertices (n x d matrix) 11 | % G: list of edges (T x M matrix) 12 | % DXg: derivative wrt X (center of the cells: T x d matrix) 13 | % DXig: derivative wrt Xi (p-vectors: T x d matrix) 14 | % Dtfg: derivative wrt tf (signal at center of the cells: T x1 colunm vector) 15 | % 16 | % Output: 17 | % dxg: derivative wrt x (n x d matrix) 18 | % dfg: derivative wrt f (n x 1 colunm vector) 19 | % Author : B. Charlier (2017) 20 | 21 | 22 | 23 | [nx,d]=size(x); 24 | [~,M] = size(tri); 25 | 26 | if M==1 % point cloud case chain's rule stops here 27 | 28 | dxg2 = DXg; 29 | return 30 | end 31 | 32 | 33 | 34 | if (d==2) 35 | U2 = [accumarray(tri(:),repmat(DXg(:,1),M,1),[nx,1],[],0),... 36 | accumarray(tri(:),repmat(DXg(:,2),M,1),[nx,1],[],0)] / M; 37 | elseif (d==3) 38 | U2 = [accumarray(tri(:),repmat(DXg(:,1),M,1),[nx,1],[],0),... 39 | accumarray(tri(:),repmat(DXg(:,2),M,1),[nx,1],[],0),... 40 | accumarray(tri(:),repmat(DXg(:,3),M,1),[nx,1],[],0)] / M; 41 | end 42 | 43 | 44 | if (M==2) % curve case 45 | if (d==2) 46 | dxg2 = U2 + [accumarray(tri(:),[-DXig(:,1);DXig(:,1)] ,[nx,1],[],0),... 47 | accumarray(tri(:),[-DXig(:,2);DXig(:,2)] ,[nx,1],[],0) ]; 48 | elseif (d==3) 49 | dxg2 = U2 + [accumarray(tri(:),[-DXig(:,1);DXig(:,1)] ,[nx,1],[],0),... 50 | accumarray(tri(:),[-DXig(:,2);DXig(:,2)] ,[nx,1],[],0),... 51 | accumarray(tri(:),[-DXig(:,3);DXig(:,3)] ,[nx,1],[],0) ]; 52 | end 53 | 54 | elseif (M==3) && (d==3) % surface case 55 | 56 | Xa=x(tri(:,1),:); 57 | Xb=x(tri(:,2),:); 58 | Xc=x(tri(:,3),:); 59 | 60 | 61 | [dU1,dU2,dU3,dV1,dV2,dV3] = dcross((Xb-Xa),(Xc-Xa),DXig/2); 62 | 63 | dxg2 = U2 + [accumarray(tri(:),[-dU1-dV1;+dU1 ;+dV1 ],[nx,1],[],0),... 64 | accumarray(tri(:),[-dU2-dV2;+dU2 ;+dV2 ],[nx,1],[],0),... 65 | accumarray(tri(:),[-dU3-dV3;+dU3 ;+dV3 ],[nx,1],[],0)]; 66 | 67 | elseif (M==4) && (d==3) % simplexes case 68 | 69 | Xa=x(tri(:,1),:); 70 | Xb=x(tri(:,2),:); 71 | Xc=x(tri(:,3),:); 72 | Xd=x(tri(:,4),:); 73 | 74 | u=(Xb-Xa);v=(Xc-Xa);w=(Xd-Xa); 75 | 76 | %[dU1,dU2,dU3,dV1,dV2,dV3,dW1,dW2,dW3] = dcrosss(u,v,w,H); 77 | H = DXig/6; 78 | 79 | dU1 = ( v(:,2) .* w(:,3) - v(:,3) .* w(:,2) ).* H; 80 | dU2 = ( v(:,3) .* w(:,1) - v(:,1) .* w(:,3) ).* H; 81 | dU3 = ( v(:,1) .* w(:,2) - v(:,2) .* w(:,1) ).* H; 82 | 83 | dV1 = ( w(:,2) .* u(:,3) - w(:,3) .* u(:,2) ).* H; 84 | dV2 = ( w(:,3) .* u(:,1) - w(:,1) .* u(:,3) ).* H; 85 | dV3 = ( w(:,1) .* u(:,2) - w(:,2) .* u(:,1) ).* H; 86 | 87 | dW1 = ( u(:,2) .* v(:,3) - u(:,3) .* v(:,2) ).* H; 88 | dW2 = ( u(:,3) .* v(:,1) - u(:,1) .* v(:,3) ).* H; 89 | dW3 = ( u(:,1) .* v(:,2) - u(:,2) .* v(:,1) ).* H; 90 | 91 | 92 | 93 | dxg2 = U2 + [accumarray(tri(:),[-dU1-dV1-dW1 ;+dU1 ;+dV1 ; dW1],[nx,1],[],0),... 94 | accumarray(tri(:),[-dU2-dV2-dW2 ;+dU2 ;+dV2 ; dW2],[nx,1],[],0),... 95 | accumarray(tri(:),[-dU3-dV3-dW3 ;+dU3 ;+dV3 ; dW3],[nx,1],[],0)]; 96 | 97 | 98 | 99 | elseif (M==3) && (d==2) % simplexes case 100 | 101 | Xa=x(tri(:,1),:); 102 | Xb=x(tri(:,2),:); 103 | Xc=x(tri(:,3),:); 104 | 105 | U=(Xb-Xa);V=(Xc-Xa); 106 | 107 | H = DXig/2; 108 | 109 | dU1 = V(:,2) .* H; 110 | dU2 = -V(:,1) .* H; 111 | 112 | dV1 = -U(:,2) .* H ; 113 | dV2 = U(:,1) .* H; 114 | 115 | dxg2 = U2 + [accumarray(tri(:),[-dU1-dV1;+dU1 ;+dV1 ],[nx,1],[],0)... 116 | accumarray(tri(:),[-dU2-dV2;+dU2 ;+dV2 ],[nx,1],[],0)]; 117 | 118 | end 119 | 120 | end 121 | -------------------------------------------------------------------------------- /Pytorch/data_attachment.py: -------------------------------------------------------------------------------- 1 | # Import the relevant tools 2 | import time # to measure performance 3 | import numpy as np # standard array library 4 | import torch 5 | from torch.autograd import Variable 6 | import torch.optim as optim 7 | 8 | # No need for a ~/.theanorc file anymore ! 9 | use_cuda = torch.cuda.is_available() 10 | dtype = torch.cuda.FloatTensor if use_cuda else torch.FloatTensor 11 | dtypeint = torch.cuda.LongTensor if use_cuda else torch.LongTensor 12 | 13 | from kernel import _k, _cross_kernels, _squared_distances 14 | 15 | # Part 3 : Data attachment ====================================================================== 16 | 17 | def _kernel_matching(q1_x, q1_mu, xt_x, xt_mu, radius) : 18 | """ 19 | Given two measures q1 and xt represented by locations/weights arrays, 20 | outputs a kernel-fidelity term and an empty 'info' array. 21 | """ 22 | K_qq, K_qx, K_xx = _cross_kernels(q1_x, xt_x, radius) 23 | cost = .5 * ( torch.sum(K_qq * torch.ger(q1_mu,q1_mu)) \ 24 | + torch.sum(K_xx * torch.ger(xt_mu,xt_mu)) \ 25 | -2*torch.sum(K_qx * torch.ger(q1_mu,xt_mu)) ) 26 | 27 | # Info = the 2D graph of the blurred distance function 28 | # Increase res if you want to get nice smooth pictures... 29 | res = 10 ; ticks = np.linspace( 0, 1, res + 1)[:-1] + 1/(2*res) 30 | X,Y = np.meshgrid( ticks, ticks ) 31 | points = Variable(torch.from_numpy(np.vstack( (X.ravel(), Y.ravel()) ).T).type(dtype), requires_grad=False) 32 | 33 | info = _k( points, q1_x , radius ) @ q1_mu \ 34 | - _k( points, xt_x , radius ) @ xt_mu 35 | return [cost , info.view( (res,res) ) ] 36 | 37 | def _ot_matching(q1_x, q1_mu, xt_x, xt_mu, radius) : 38 | """ 39 | Given two measures q1 and xt represented by locations/weights arrays, 40 | outputs an optimal transport fidelity term and the transport plan. 41 | """ 42 | # The Sinkhorn algorithm takes as input three Theano variables : 43 | c = _squared_distances(q1_x, xt_x) # Wasserstein cost function 44 | mu = q1_mu ; nu = xt_mu 45 | 46 | # Parameters of the Sinkhorn algorithm. 47 | epsilon = (.02)**2 # regularization parameter 48 | rho = (.5) **2 # unbalanced transport (See PhD Th. of Lenaic Chizat) 49 | niter = 10000 # max niter in the sinkhorn loop 50 | tau = -.8 # nesterov-like acceleration 51 | 52 | lam = rho / (rho + epsilon) # Update exponent 53 | 54 | # Elementary operations ..................................................................... 55 | def ave(u,u1) : 56 | "Barycenter subroutine, used by kinetic acceleration through extrapolation." 57 | return tau * u + (1-tau) * u1 58 | def M(u,v) : 59 | "$M_{ij} = (-c_{ij} + u_i + v_j) / \epsilon$" 60 | return (-c + u.unsqueeze(1) + v.unsqueeze(0)) / epsilon 61 | lse = lambda A : torch.log(torch.exp(A).sum( 1 ) + 1e-6) # slight modif to prevent NaN 62 | 63 | # Actual Sinkhorn loop ...................................................................... 64 | u,v,err = 0.*mu, 0.*nu, 0. 65 | actual_nits = 0 66 | 67 | for i in range(niter) : 68 | u1= u # useful to check the update 69 | u = ave( u, lam * ( epsilon * ( torch.log(mu) - lse(M(u,v)) ) + u ) ) 70 | v = ave( v, lam * ( epsilon * ( torch.log(nu) - lse(M(u,v).t()) ) + v ) ) 71 | err = (u - u1).abs().sum() 72 | 73 | actual_nits += 1 74 | if (err < 1e-4).data.cpu().numpy() : 75 | break 76 | U, V = u, v 77 | Gamma = torch.exp( M(U,V) ) # Eventual transport plan g = diag(a)*K*diag(b) 78 | cost = torch.sum( Gamma * c ) # Simplistic cost, chosen for readability in this tutorial 79 | 80 | print('Sinkhorn error after ' + str(actual_nits) + ' iterations : ' + str(err.data.cpu().numpy())) 81 | return [cost, Gamma] 82 | 83 | 84 | def _data_attachment(q1_measure, xt_measure, radius) : 85 | "Given two measures and a radius, returns a cost - as a Theano symbolic variable." 86 | if radius == 0 : # Convenient way to allow the choice of a method 87 | return _ot_matching(q1_measure[0], q1_measure[1], 88 | xt_measure[0], xt_measure[1], 89 | radius) 90 | else : 91 | return _kernel_matching(q1_measure[0], q1_measure[1], 92 | xt_measure[0], xt_measure[1], 93 | radius) 94 | -------------------------------------------------------------------------------- /LDDMM_Python/lddmm_python/modules/io/read_vtk.py: -------------------------------------------------------------------------------- 1 | import re 2 | from pylab import * 3 | 4 | def ReadVTK(filename, points = True, polygons = True, signals = True, thicknesses = True): 5 | """ Specification of VTK-files: 6 | http://www.vtk.org/VTK/img/file-formats.pdf - page 4 """ 7 | f = open(filename) 8 | lines = f.readlines() 9 | f.close() 10 | 11 | verticeList = [] 12 | polygonsList = [] 13 | signalsList = [] 14 | 15 | lineNr = 0 16 | #pattern_points = re.compile('([-+]?\d*\.\d+|\d+) ([-+]?\d*\.\d+|\d+) ([-+]?\d*\.\d+|\d+)') 17 | pattern_points_3perline = re.compile('([-+Ee\d\.]+) ([-+Ee\d\.]+) ([-+Ee\d\.]+) ([-+Ee\d\.]+) ([-+Ee\d\.]+) ([-+Ee\d\.]+) ([-+Ee\d\.]+) ([-+Ee\d\.]+) ([-+Ee\d\.]+)') 18 | pattern_points_2perline = re.compile('([-+Ee\d\.]+) ([-+Ee\d\.]+) ([-+Ee\d\.]+) ([-+Ee\d\.]+) ([-+Ee\d\.]+) ([-+Ee\d\.]+)') 19 | pattern_points = re.compile('([-+Ee\d\.]+) ([-+Ee\d\.]+) ([-+Ee\d\.]+)') 20 | pattern_polygons_3 = re.compile('([\d]+) ([\d]+) ([\d]+) ([\d]+)') 21 | pattern_polygons_2 = re.compile('([\d]+) ([\d]+) ([\d]+)') 22 | pattern_signal = re.compile('([-+E\d\.]+)') 23 | 24 | def handle_points(l) : 25 | m = pattern_points_3perline.match(l) 26 | if m != None: 27 | x1 = float(m.group(1)) 28 | y1 = float(m.group(2)) 29 | z1 = float(m.group(3)) 30 | x2 = float(m.group(4)) 31 | y2 = float(m.group(5)) 32 | z2 = float(m.group(6)) 33 | x3 = float(m.group(7)) 34 | y3 = float(m.group(8)) 35 | z3 = float(m.group(9)) 36 | verticeList.append([x1,y1,z1]) 37 | verticeList.append([x2,y2,z2]) 38 | verticeList.append([x3,y3,z3]) 39 | else : 40 | m = pattern_points_2perline.match(l) 41 | if m != None: 42 | x1 = float(m.group(1)) 43 | y1 = float(m.group(2)) 44 | z1 = float(m.group(3)) 45 | x2 = float(m.group(4)) 46 | y2 = float(m.group(5)) 47 | z2 = float(m.group(6)) 48 | verticeList.append([x1,y1,z1]) 49 | verticeList.append([x2,y2,z2]) 50 | else : 51 | m = pattern_points.match(l) 52 | if m != None: 53 | x = float(m.group(1)) 54 | y = float(m.group(2)) 55 | z = float(m.group(3)) 56 | verticeList.append([x,y,z]) 57 | 58 | def handle_polygons(l) : 59 | m = pattern_polygons_3.match(l) 60 | if m != None : 61 | nrOfPoints = m.group(1) 62 | vertice1 = int(m.group(2)) 63 | vertice2 = int(m.group(3)) 64 | vertice3 = int(m.group(4)) 65 | polygonsList.append([vertice1, vertice2, vertice3]) 66 | else : 67 | m = pattern_polygons_2.match(l) 68 | if m != None : 69 | nrOfPoints = m.group(1) 70 | vertice1 = int(m.group(2)) 71 | vertice2 = int(m.group(3)) 72 | polygonsList.append([vertice1, vertice2]) 73 | 74 | def handle_signal(l) : 75 | m = pattern_signal.match(l) 76 | if m != None : 77 | signal = float(m.group(1)) 78 | signalsList.append(signal) 79 | 80 | def handle_nothing(l) : 81 | None 82 | 83 | current_treatment = handle_nothing 84 | for line in lines : 85 | if "POINTS" in line : 86 | current_treatment = handle_points 87 | elif "POLYGONS" in line : 88 | current_treatment = handle_polygons 89 | elif "LINES" in line : 90 | current_treatment = handle_polygons 91 | elif "LOOKUP_TABLE" in line : 92 | current_treatment = handle_signal 93 | else : 94 | current_treatment(line) 95 | 96 | """ 97 | while "POINTS" not in lines[lineNr]: 98 | lineNr += 1 99 | while "POLYGONS" not in lines[lineNr]: 100 | lineNr += 1 101 | m = pattern_points.match(lines[lineNr]) 102 | if m != None: 103 | x = float(m.group(1)) 104 | y = float(m.group(2)) 105 | z = float(m.group(3)) 106 | verticeList.append([x,y,z]) 107 | while "LOOKUP_TABLE" not in lines[lineNr]: 108 | lineNr += 1 109 | m = pattern_polygons.match(lines[lineNr]) 110 | if m != None : 111 | nrOfPoints = m.group(1) 112 | vertice1 = int(m.group(2)) 113 | vertice2 = int(m.group(3)) 114 | vertice3 = int(m.group(4)) 115 | gewicht = 1.0 116 | polygonsList.append([vertice1, vertice2, vertice3]) 117 | while lineNr < len(lines)-1: 118 | lineNr += 1 119 | m = pattern_signal.match(lines[lineNr]) 120 | if m != None : 121 | signal = float(m.group(1)) 122 | signalsList.append(signal) 123 | """ 124 | return (verticeList, polygonsList, signalsList) 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | -------------------------------------------------------------------------------- /matlab/Script/hands/script_hands_matching_tan_bundle_ot.m: -------------------------------------------------------------------------------- 1 | % Matching of multi-shapes : hands and fibres bundle (http://visionair.ge.imati.cnr.it/ontologies/shapes/) 2 | % Author : B. Charlier (2017) 3 | 4 | PathToFshapesTk = '../..' 5 | addpath(genpath([PathToFshapesTk,'/Bin'])) 6 | addpath(genpath([PathToFshapesTk,'/Script'])) 7 | 8 | 9 | %------------------% 10 | % oliver's hand % 11 | %------------------% 12 | 13 | [p,t] = read_off('./data/764-Olivier_hand_-_Simplified_to_10kF/764_closed.off'); 14 | 15 | p=p';t=t'; 16 | 17 | l =0.7;noise=.2; n=50;nb_point_bundle=8; 18 | X0=repmat([0;-.2;0],1,n)+ randn(3,n)*.01; curvature=0.5/l; v=[1;.1;2]; 19 | Xall=generate_fiber(X0,l,curvature,nb_point_bundle,v,noise); 20 | 21 | oliver_hand{1,1} = struct('x',p,'G',t,'f',zeros(size(p,1),1)); 22 | curvex = []; 23 | curveG = []; 24 | pointx = []; 25 | for i = 1:size(Xall,3) 26 | curvex =[curvex ; Xall(:,:,i)'] ; 27 | n = size(Xall,2); 28 | nstart = ((i-1)*n); 29 | curveG = [curveG;[nstart+1:(nstart+n-1);(nstart+2):(nstart+n)]']; 30 | pointx =[pointx ; Xall(:,end,i)']; 31 | end 32 | 33 | oliver_hand{1,2} = struct('x',curvex,'G',curveG,'f',zeros(numel(Xall)/3,1) ); 34 | 35 | %-----------------------% 36 | % Pierre's hand % 37 | %-----------------------% 38 | 39 | 40 | [pp,tp] = read_off('./data/736-Pierre_s_hand__decimated_version/736.off'); 41 | 42 | pp=pp'; 43 | pp(:,1) = - pp(:,1); 44 | tp=tp'; 45 | 46 | 47 | l =0.5;noise=.1; n=53;nb_point_bundle=9; 48 | X0=repmat([0;-.2;0],1,n)+ randn(3,n)*.01; curvature=0.5/l; v=[-.1;.2;1]; 49 | Xall=generate_fiber(X0,l,curvature,nb_point_bundle,v,noise); 50 | 51 | pierre_hand{1,1} = struct('x',pp,'G',tp,'f',zeros(size(pp,1),1)); 52 | curvex = []; 53 | curveG = []; 54 | pointx = []; 55 | for i = 1:size(Xall,3) 56 | curvex =[curvex ; Xall(:,:,i)'] ; 57 | n = size(Xall,2); 58 | nstart = ((i-1)*n); 59 | curveG = [curveG;[nstart+1:(nstart+n-1);(nstart+2):(nstart+n)]']; 60 | pointx =[pointx ; Xall(:,end,i)']; 61 | end 62 | 63 | pierre_hand{1,2} = struct('x',curvex,'G',curveG,'f',zeros(numel(Xall)/3,1) ); 64 | 65 | %------------------------------% 66 | % parameters % 67 | %------------------------------% 68 | 69 | comp_method = 'cuda';% possible values are 'cuda' or 'matlab' 70 | 71 | % Parameters for the deformations 72 | defo.kernel_size_mom = [.5, .2,.1]; % the kernel used to generate the deformations is a sum of 2 kernels 73 | defo.nb_euler_steps =15; % nbr of steps in the (for||back)ward integration 74 | defo.method =comp_method; % possible values are 'cuda' or 'matlab' 75 | 76 | % Parameters for the matchterm 77 | objfun{1}.normalize_objfun=1; 78 | % First part of the shape : hand's shape surface 79 | objfun{1}.weight_coef_dist = 6000; % weighting coeff in front of the data attachment term 80 | objfun{1}.distance = 'wasserstein'; 81 | objfun{1}.wasserstein_distance.epsilon = .5*(.05)^2; 82 | objfun{1}.wasserstein_distance.niter = 200; 83 | objfun{1}.wasserstein_distance.tau = 0; % basic sinkhorn, no extrapolation 84 | objfun{1}.wasserstein_distance.rho = 10; % balanced case 85 | objfun{1}.wasserstein_distance.weight_cost_varifold = [6,1]; % weight on spatial and orientation distances 86 | objfun{1}.wasserstein_distance.method=comp_method; % possible values are 'cuda' or 'matlab' 87 | 88 | % second part of the shape : the fibres bundles 89 | objfun{2}.normalize_objfun=1; 90 | objfun{2}.weight_coef_dist = 10; % weighting coeff in front of the data attachment term 91 | objfun{2}.distance = 'wasserstein'; 92 | objfun{2}.wasserstein_distance.epsilon = .5*(.05)^2; 93 | objfun{2}.wasserstein_distance.niter = 200; 94 | objfun{2}.wasserstein_distance.tau = 0; % basic sinkhorn, no extrapolation 95 | objfun{2}.wasserstein_distance.rho = 10; % balanced case 96 | objfun{2}.wasserstein_distance.weight_cost_varifold = [6,1]; % weight on spatial and orientation distances 97 | objfun{2}.wasserstein_distance.method=comp_method; % possible values are 'cuda' or 'matlab' 98 | 99 | 100 | optim.method = 'bfgs'; 101 | optim.bfgs.maxit = 300; 102 | 103 | %----------% 104 | % output % 105 | %----------% 106 | 107 | [momentums,summary]=fsmatch_tan(pierre_hand,oliver_hand,defo,objfun,optim); 108 | 109 | % export in vtk files 110 | saveDir ='./results/matching_hands_and_bundles_ot/'; 111 | export_matching_tan(pierre_hand,momentums,{zeros(size(pierre_hand{1}.f)), zeros(size(pierre_hand{2}.f))},oliver_hand,summary,saveDir) 112 | 113 | 114 | 115 | -------------------------------------------------------------------------------- /LDDMM_Python/lddmm_python/modules/models/free_1D_atlas.py: -------------------------------------------------------------------------------- 1 | from pylab import * 2 | 3 | from .free_atlas import FreeAtlas 4 | 5 | class Free1DAtlas(FreeAtlas) : 6 | """Atlas with a free mean Q0 and rank-1 constraint on P0""" 7 | def __init__(self, *args, **kwargs) : 8 | FreeAtlas.__init__(self, *args, **kwargs) 9 | 10 | # the direction, a single momentum; we choose to constrain its norm 11 | self.E = self.M.unit_p(self.Q0, array([1,0])) # arbitrary choice. 12 | self.L = zeros((self.nobs,1)) # coefficients, 1xnobs real-valued matrix 13 | self.P = self.L @ atleast_2d(self.E) # it is more pythonic to work with the "transposes" 14 | 15 | # true (default) if we use the kernel matrix K 16 | # at the template to compute the scalar 17 | # products between momentums; this is the 18 | # natural choice, but it can be costly in 19 | # practice for shape manifolds. 20 | # 21 | # False to use a simple L2 metric. 22 | self.intrinsic_scalar_product = False 23 | 24 | """Updates""" 25 | def update_P(self, dP) : 26 | # models update 27 | self.normalize_basis() # just in case the user is toying with the scalar product 28 | (scals, residuals) = self.decompose(dP) 29 | assert(self.L.shape == scals.shape) 30 | assert(self.E.shape == (residuals.shape[1],)) 31 | self.L = self.L + scals 32 | 33 | # scals = scals ./ (abs(scals) + eps) 34 | # residuals = self.M.unit_p(self.Q0, residuals) 35 | self.E = self.E + mean(residuals, 0) # !!! 36 | 37 | self.normalize_basis() # Don't forget to stay in the Stiefel manifold ! 38 | self.P = self.L @ atleast_2d(self.E) 39 | 40 | def normalize_basis(self) : 41 | # This is the simplest way to do it; in practice, 42 | # we may use more accurate methods : 43 | if self.intrinsic_scalar_product : 44 | self.E = self.M.unit_p(self.Q0, self.E) 45 | else : 46 | self.E = self.E / sqrt(self.E @ self.E) # just in case the user is toying with the scalar product 47 | 48 | def decompose(self, dP) : 49 | """ 50 | Decomposes the update dP in a : 51 | - longitudinal part along self.E, given by the coeff. update 'scals' 52 | - orthogonal part, given by 'residuals' 53 | self.E is assumed to be an orthonormal family 54 | """ 55 | if self.intrinsic_scalar_product : 56 | scals = self.M.K( self.Q0, dP ) @ self.E 57 | else : 58 | scals = dP @ self.E 59 | scals = atleast_2d(scals).T 60 | residuals = dP - scals @ atleast_2d(self.E) # normal component 61 | # rescaling depending on the distance from model to the template : 62 | residuals = residuals * (self.weights()) 63 | # scals = scals ./ max(.2, abs(scals)); 64 | # scals = .01 * scals ./ abs(scals); 65 | residuals = atleast_2d(residuals) 66 | return (scals, residuals) 67 | 68 | def weights(self) : 69 | """ 70 | Returns the weight associated to each point in the steering of 71 | the direction self.E. Just like with Frechet means, the choice 72 | of this function will change the behaviour of our model, from 73 | 'angular median' to 'angular mean'. 74 | Note that the correct quadratic gradient-based formula is '1 / L'. 75 | """ 76 | return sign(self.L) #1/(self.L + 0.00001) 77 | """ 78 | def show_inner_model(self, Xt, ax) : 79 | [points, Q, C, dQ] = show_inner_model@HypertemplateAtlas(Mod, Xt, ax); 80 | [dQ0p, dP] = self.training_step(Xt, 1, true); % simulation = true : there won't be any update ! 81 | [scals, residuals] = self.decompose(dP); 82 | 83 | longitudinals = self.E * scals; 84 | % For ease of explanation as a steering process : 85 | normals = residuals.* sign(repmat(self.L, [size(residuals, 1), 1])); 86 | if self.intrinsic_scalar_product 87 | dP = self.M.L2_repr_p(self.Q0, dP); 88 | longitudinals = self.M.L2_repr_p(self.Q0, longitudinals); 89 | normals = self.M.L2_repr_p(self.Q0, residuals); 90 | end 91 | 92 | basis = self.M.L2_repr_p(self.Q0, self.E); 93 | hold(ax, 'on'); 94 | %plot(ax, self.L, self.L, '-x'); 95 | quiver(ax, 0, 0, basis(2,:), basis(1, :), 0); 96 | quiver(ax, points(2,:), points(1,:), longitudinals(2,:), longitudinals(1,:), 1, 'y'); 97 | quiver(ax, points(2,:), points(1,:), normals(2,:), normals(1,:), 1, 'g'); 98 | %quiver(ax, points(2,:), points(1,:), dQ0p(2,:), dQ0p(1,:), 1, 'r'); 99 | quiver(ax, points(2,:), points(1,:), dP(2,:), dP(1,:), 1, 'r'); 100 | quiver(ax, 0, 0, mean(dQ0p(2,:)), mean(dQ0p(1,:)), 1, 'Color', [0,0,.5], 'Linewidth', 2); 101 | hold(ax, 'off'); 102 | 103 | """ 104 | 105 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | **N.B.:** This repository is out of date. A reference implementation of Optimal Transport divergences for shape registration is now available on the [geomloss](https://github.com/jeanfeydy/geomloss) repository: [website](https://www.kernel-operations.io/geomloss), [pip package](https://pypi.org/project/geomloss/). 2 | 3 | 4 | # lddmm-ot 5 | MICCAI 2017 Paper - Optimal Transport for Diffeomorphic Registration 6 | 7 | Authors : 8 | Jean Feydy, Benjamin Charlier, F.-X. Vialard, Gabriel Peyré 9 | 10 | This repositery contains three independent implementations of the Optimal Transport 11 | data attachment term introduced in the paper : 12 | 13 | - A simplistic "one-script" theano+python implementation, located in the 14 | 'Simple_script/' folder. It implements curves matching with a simplistic 15 | 'curve length' measure embedding. 16 | 17 | - A fully-fledged theano+python toolbox, located in the "LDDMM_Python" folder. 18 | It implements embeddings in the varifold space for curves and surfaces, 19 | and was used for Figure 1 (Protozoa). 20 | 21 | - A fully-fledged Matlab toolbox, placed in the 'matlab/' directory. 22 | 23 | It also hosts a mini implementation in Pytorch, that we will strive to make as 24 | memory-efficient as possible. Hopefully, we can find a way to relieve the major 25 | bottleneck of autodiffs libraries, as of 2017. 26 | 27 | -------------------------------------------------------------------------------- 28 | Instructions for the python implementations 29 | -------------------------------------------------------------------------------- 30 | You will need to install the autodiff library Theano on top of Jupyter/IPython. 31 | N.B. : To use your Nvidia GPU, don't forget to put the appropriate settings in 32 | your .theanorc (http://www.deeplearning.net/software/theano/tutorial/using_gpu.html). 33 | For our experiments, it was simply : 34 | 35 | ```markdown 36 | [nvcc] 37 | flags=-D_FORCE_INLINES 38 | 39 | 40 | [global] 41 | device=cuda 42 | floatX=float32 43 | exception_verbosity=high 44 | ``` 45 | 46 | (With an Nvidia GeForce GTX 960M) 47 | 48 | We advise the interested reader to get introduced to our implementations with 49 | the 'Simple_script/' toy demo. 50 | 51 | Then, to recompute the Figure 1, please : 52 | - go into the 'LDDMM_Python/' folder. 53 | - there, open a terminal and launch the 'jupyter notebook' command - provided by 54 | a fresh Anaconda install for instance. 55 | - Your web browser should open itself. Through the web interface, go into 56 | 'demo/Notebooks/Feb2017_paper/'. 57 | - Click on 'curves_matching.ipynb' to open the IPython/Jupyter Notebook. 58 | - Simply make a 'Cell/Run all'. 59 | - Once the computation is over, you can run the 'pvpython render.py' 60 | (provided by the software Paraview) to convert the .vtk into the appropriate 61 | .png images. 62 | 63 | The runs made to compute the presented images have been saved in 64 | 'run_1.html' and 'run_2.html' (the first one had crashed due to a garbage 65 | collection problem combined to the super-greedy theano scan, we discarded 66 | the error message to preserve anonymity). 67 | You may check energy descent and computation time here. 68 | 69 | N.B. : you may change the source and target by editing the 70 | 'demo/Notebooks/Feb2017_paper/data/source.png' and 'target.png' images. 71 | 72 | As of today, theano's implementation of the 'scan' or 'for loop' operation, 73 | is extremely memory-greedy : we can't use autodiff with 74 | ~1000 sinkhorn iterations with more than 200 points without a memory overflow. 75 | A future version of the toolbox will use the 'scan_checkpoints' routine 76 | (which allows one to set the speed/memory tradeoff), and eventualy allow us 77 | to test our method on Eulerian image registration. 78 | 79 | 80 | -------------------------------------------------------------------------------- 81 | Instructions for the matlab toolbox 82 | -------------------------------------------------------------------------------- 83 | ----------- 84 | Quick start 85 | ----------- 86 | 87 | A) Use with pure matlab code 88 | 1) simplyrun the various examples in ./Script/ 89 | 90 | B) Use with cuda mex files (mandatory with surfaces) 91 | 1) compile the mex files in ./Bin/kernels/ with the makefile.sh 92 | 2) run the various examples in ./Script/ 93 | 94 | You will be able to read the .vtk files with Paraview. 95 | 96 | 97 | 98 | Best regards, 99 | 100 | The authors. 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | -------------------------------------------------------------------------------- /LDDMM_Python/lddmm_python/modules/manifolds/theano_shapescarrier.py: -------------------------------------------------------------------------------- 1 | # Import of the relevant tools 2 | import time 3 | import numpy as np 4 | import theano 5 | import theano.tensor as T 6 | from theano import pp, config 7 | 8 | 9 | from plotly.tools import FigureFactory as FF 10 | import plotly.graph_objs as go 11 | 12 | from ..io.read_vtk import ReadVTK 13 | from ..data_attachment.measures import Measures 14 | from ..data_attachment.varifolds import Varifolds 15 | from ..math_utils.kernels import _squared_distances, _gaussian_kernel 16 | 17 | 18 | from .theano_hamiltoniancarrier import TheanoHamiltonianCarrier 19 | from .shapes_manifold import ShapesManifold 20 | 21 | 22 | 23 | class TheanoShapesCarrier(ShapesManifold, TheanoHamiltonianCarrier) : 24 | """ 25 | Combines the control points framework with the data attachment + io methods 26 | of the ShapesManifold class. 27 | """ 28 | 29 | def __init__(self, S0, 30 | kernel = ('gaussian', 1), 31 | data_attachment = ('measure-kernel', ('gaussian', 1)), 32 | weights = (0.01, 1), # gamma_V, gamma_W 33 | dt = 0.1, 34 | compatibility_compile = False, 35 | plot_interactive = False, 36 | plot_file = True, 37 | foldername = 'results/' 38 | ) : 39 | """ 40 | Creates a TheanoCurves/Surfaces manifold. 41 | Compilation takes place here. 42 | """ 43 | 44 | TheanoHamiltonianCarrier.__init__(self, kernel = kernel, 45 | weights = weights, 46 | dt = dt, 47 | plot_interactive = plot_interactive, 48 | plot_file = plot_file, 49 | foldername = foldername) 50 | ShapesManifold.__init__(self, S0, 51 | data_attachment) 52 | 53 | 54 | #=============================================================== 55 | # Before compiling, we assign types to the teano variables 56 | q0 = T.matrix('q0') 57 | p0 = T.matrix('p0') 58 | s0 = T.matrix('s0') 59 | xt_x = T.matrix('xt_x') 60 | xt_mu = T.vector('xt_mu') 61 | xt_n = T.matrix('xt_n') 62 | 63 | # Compilation. Depending on settings specified in the ~/.theanorc file or explicitely given 64 | # at execution time, this will produce CPU or GPU code. 65 | 66 | if not compatibility_compile : # With theano, it's better to let the compilator handle the whole forward-backward pipeline 67 | print('Compiling the shooting_cost routine...') 68 | time1 = time.time() 69 | 70 | if self.embedding_type == 'measure' : 71 | self.opt_shooting_cost = theano.function([q0, p0, s0, xt_x, xt_mu], # input 72 | self._opt_shooting_cost(q0, p0, s0, xt_x, xt_mu), # output 73 | allow_input_downcast=True) # GPU = float32 only, whereas numpy uses 74 | # float64 : we allow silent conversion 75 | elif self.embedding_type == 'varifold' : 76 | self.opt_shooting_cost = theano.function([q0, p0, s0, xt_x, xt_mu, xt_n], # input 77 | self._opt_shooting_cost(q0, p0, s0, xt_x, xt_mu, xt_n), # output 78 | allow_input_downcast=True) # GPU = float32 only, whereas numpy uses 79 | # float64 : we allow silent conversion 80 | 81 | 82 | time2 = time.time() 83 | print('Compiled in : ', '{0:.2f}'.format(time2 - time1), 's') 84 | 85 | # The hamiltonian_trajectory routine, that shall be used in the visualization 86 | print('Compiling the hamiltonian_trajectory visualization routine...') 87 | time1 = time.time() 88 | self.hamiltonian_trajectory = theano.function([q0,p0,s0], # input 89 | self._HamiltonianTrajectoryCarrying(q0, p0, s0), # output 90 | allow_input_downcast=True) # GPU = float32 only, whereas numpy uses 91 | # float64 : we allow silent conversion 92 | time2 = time.time() 93 | print('Compiled in : ', '{0:.2f}'.format(time2 - time1), 's') 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | -------------------------------------------------------------------------------- /matlab/Bin/optim/hanso (third party)/gradsampfixed.m: -------------------------------------------------------------------------------- 1 | function [x, f, g, dnorm, X, G, w, quitall] = ... 2 | gradsampfixed(x0, f0, g0, samprad, pars, options) 3 | % gradient sampling minimization with fixed sampling radius 4 | % intended to be called by gradsamp1run only 5 | % 6 | % Send comments/bug reports to Michael Overton, overton@cs.nyu.edu, 7 | % with a subject header containing the string "hanso" or "gradsamp". 8 | % Version 2.0, 2010, see GPL license info below. 9 | 10 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 11 | %% HANSO 2.0 Copyright (C) 2010 Michael Overton 12 | %% This program is free software: you can redistribute it and/or modify 13 | %% it under the terms of the GNU General Public License as published by 14 | %% the Free Software Foundation, either version 3 of the License, or 15 | %% (at your option) any later version. 16 | %% 17 | %% This program is distributed in the hope that it will be useful, 18 | %% but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | %% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | %% GNU General Public License for more details. 21 | %% 22 | %% You should have received a copy of the GNU General Public License 23 | %% along with this program. If not, see . 24 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 25 | 26 | fgname = pars.fgname; 27 | prtlevel = options.prtlevel; 28 | if prtlevel > 0 29 | fprintf('gradsamp: sampling radius = %7.1e,',samprad); 30 | end 31 | if prtlevel > 1 32 | fprintf('\n') 33 | end 34 | x = x0; 35 | f = f0; 36 | g = g0; 37 | X = x; 38 | G = g; 39 | w = 1; 40 | quitall = 0; 41 | maxit = options.maxit; 42 | normtol = options.normtol; 43 | ngrad = options.ngrad; 44 | fvalquit = options.fvalquit; 45 | cpufinish = cputime + options.cpumax; 46 | dnorm = inf; 47 | for iter = 1:maxit 48 | % evaluate gradients at randomly generated points near x 49 | % first column of Xnew and Gnew are respectively x and g 50 | [Xnew, Gnew] = getbundle(x, g, samprad, ngrad, pars); 51 | % solve QP subproblem 52 | [wnew,dnew] = qpspecial(Gnew); % Anders Skajaa specialized QP solver 53 | dnew = -dnew; % this is a descent direction 54 | gtdnew = g'*dnew; % gradient value at current point 55 | dnormnew = norm(dnew); 56 | if dnormnew < dnorm % for returning, may not be the final one 57 | dnorm = dnormnew; 58 | X = Xnew; 59 | G = Gnew; 60 | w = wnew; 61 | end 62 | if dnormnew < normtol 63 | % since dnormnew is first to satisfy tolerance, it must equal dnorm 64 | if prtlevel > 0 65 | fprintf(' tolerance met at iter %d, f = %g, dnorm = %5.1e\n', ... 66 | iter, f, dnorm); 67 | end 68 | return 69 | elseif gtdnew >= 0 | isnan(gtdnew) 70 | if prtlevel > 0 % dnorm, not dnormnew, which may be bigger 71 | fprintf(' not descent direction, quit at iter %d, f = %g, dnorm = %5.1e\n', ... 72 | iter, f, dnorm); 73 | end 74 | return 75 | end 76 | % note that dnew is NOT normalized, but we set second Wolfe 77 | % parameter to 0 so that sign of derivative must change 78 | % and this is accomplished by expansion steps when necessary, 79 | % so it does not seem necessary to normalize d 80 | wolfe1 = 0; 81 | wolfe2 = 0; 82 | [alpha, x, f, g, fail] = ... 83 | linesch_ww(x, f, g, dnew, pars, wolfe1, wolfe2, fvalquit, prtlevel); 84 | if prtlevel > 1 % since this is printed every iteration we print dnormnew here 85 | fprintf(' iter %d: step = %5.1e, f = %g, dnorm = %5.1e\n',... 86 | iter, alpha, f, dnormnew) 87 | end 88 | if f < fvalquit 89 | if prtlevel > 0 90 | fprintf(' reached target objective, quit at iter %d \n', iter) 91 | end 92 | quitall = 1; 93 | return 94 | end 95 | % if fail == 1 % Wolfe conditions not both satisfied, DO NOT quit, 96 | % because this typically means gradient set not rich enough and we 97 | % should continue sampling 98 | if fail == -1 % function apparently unbounded below 99 | if prtlevel > 0 100 | fprintf(' f may be unbounded below, quit at iter %d, f = %g\n',... 101 | iter, f) 102 | end 103 | quitall = 1; 104 | return 105 | end 106 | if cputime > cpufinish 107 | if prtlevel > 0 108 | fprintf(' cpu time limit exceeded, quit at iter %d\n', iter) 109 | end 110 | quitall = 1; 111 | return 112 | end 113 | end 114 | if prtlevel > 0 115 | fprintf(' %d iters reached, f = %g, dnorm = %5.1e\n', maxit, f, dnorm); 116 | end --------------------------------------------------------------------------------