From dc533c1690fe191b2f3a85fafb2b20d0cded38bc Mon Sep 17 00:00:00 2001 From: Markus Stoll Date: Thu, 18 Dec 2014 22:42:27 +0100 Subject: [PATCH 1/2] #197 CPack & GET_PREREQUISITES --- operators/CMakeLists.txt | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/operators/CMakeLists.txt b/operators/CMakeLists.txt index ebc6977a..8254b7b0 100755 --- a/operators/CMakeLists.txt +++ b/operators/CMakeLists.txt @@ -192,6 +192,17 @@ MACRO(MSML_LIBRARY) IF(WIN32 AND NOT CYGWIN) ADD_LIBRARY(${ML_NAME} SHARED ${ML_SOURCES} "${CMAKE_SOURCE_DIR}/common/log.cpp") set_target_properties (_${ML_NAME}Python PROPERTIES COMPILE_DEFINITIONS "PYTHONLOGGING") #experimental + + string(TOUPPER "${CMAKE_BUILD_TYPE}" CONFIG) + GET_TARGET_PROPERTY(MY_BINARY_LOCATION ${ML_NAME} LOCATION_${CONFIG} ) + INCLUDE(GetPrerequisites) + message(${MY_BINARY_LOCATION} " looking for DEPENDENCIES... ") + GET_PREREQUISITES(${MY_BINARY_LOCATION} DEPENDENCIES 1 1 "" "") + foreach(DEPENDENCY_FILE ${DEPENDENCIES}) + gp_resolve_item("${MY_BINARY_LOCATION}" "${DEPENDENCY_FILE}" "" "" resolved_file) + message("resolved_file='${resolved_file}'") + endforeach() + ELSE() set_target_properties (_${ML_NAME}Python PROPERTIES COMPILE_DEFINITIONS "PYTHONLOGGING") ADD_LIBRARY(${ML_NAME} SHARED ${ML_SOURCES} "${CMAKE_SOURCE_DIR}/common/log.cpp") @@ -214,3 +225,4 @@ ADD_SUBDIRECTORY(CLI) ADD_SUBDIRECTORY(ACVDOperators) +INCLUDE(CPack) From 063e478592469d6849dfa9b5beec540ef33030e3 Mon Sep 17 00:00:00 2001 From: Alexander Weigl Date: Tue, 23 Dec 2014 04:47:24 +0100 Subject: [PATCH 2/2] add proper install targets * fix some cmake errors on my machine --- operators/CMakeLists.txt | 244 +++++++++++++++++--------- src/msml/exporter/hiflow3/__init__.py | 43 +++-- src/msml/exporter/hiflow3/findrot.py | 75 ++++++++ src/msml/ext/msmlvtk.py | 55 ++++-- src/msml/model/__init__.py | 2 +- src/msmltest/findrot_test.py | 46 +++++ 6 files changed, 352 insertions(+), 113 deletions(-) create mode 100644 src/msml/exporter/hiflow3/findrot.py create mode 100644 src/msmltest/findrot_test.py diff --git a/operators/CMakeLists.txt b/operators/CMakeLists.txt index 8254b7b0..f77ea8e9 100755 --- a/operators/CMakeLists.txt +++ b/operators/CMakeLists.txt @@ -1,47 +1,126 @@ +PROJECT(MSML) CMAKE_MINIMUM_REQUIRED(VERSION 2.6.2) SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/CMake") -######################### +######################################################################################################################## +# Prepare Installation +######################################################################################################################## + +INCLUDE(InstallRequiredSystemLibraries) + +SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Medical Simulation Markup Language") +SET(CPACK_PACKAGE_VENDOR "http://CognitionGuidedSurgery.de see Authors.txt for details") +SET(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/../README.md") +SET(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/../LICENSE") + +SET(CPACK_PACKAGE_VERSION_MAJOR "0") +SET(CPACK_PACKAGE_VERSION_MINOR "8") +SET(CPACK_PACKAGE_VERSION_PATCH "2") + +SET(CPACK_PACKAGE_INSTALL_DIRECTORY "msml-${CMake_VERSION_MAJOR}.${CMake_VERSION_MINOR}") + +IF(WIN32 AND NOT UNIX) + # There is a bug in NSI that does not handle full unix paths properly. Make + # sure there is at least one set of four (4) backlasshes. + SET(CPACK_PACKAGE_ICON "${CMake_SOURCE_DIR}/Utilities/Release\\\\InstallIcon.bmp") + SET(CPACK_NSIS_INSTALLED_ICON_NAME "bin\\\\MyExecutable.exe") + SET(CPACK_NSIS_DISPLAY_NAME "${CPACK_PACKAGE_INSTALL_DIRECTORY} My Famous Project") + SET(CPACK_NSIS_HELP_LINK "http:\\\\\\\\www.my-project-home-page.org") + SET(CPACK_NSIS_URL_INFO_ABOUT "http:\\\\\\\\www.my-personal-home-page.com") + SET(CPACK_NSIS_CONTACT "me@my-personal-home-page.com") + SET(CPACK_NSIS_MODIFY_PATH ON) +ELSE(WIN32 AND NOT UNIX) + + #SET(CPACK_STRIP_FILES "bin/MyExecutable") + #SET(CPACK_SOURCE_STRIP_FILES "") + +ENDIF(WIN32 AND NOT UNIX) +#SET(CPACK_PACKAGE_EXECUTABLES "MyExecutable" "My Executable") + + + +## DEBIAN +SET(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6 (>= 2.3.1-6), libgcc1 (>= 1:3.4.2-12)") +SET(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "amd64") +SET(CPACK_DEBIAN_PACKAGE_MAINTAINER "Alexander Weigl ") +INCLUDE(CPack) + +######################################################################################################################## # Set default Build Type to Debug -######################### +######################################################################################################################## + +SET(CMAKE_BUILD_TYPE Debug CACHE STRING + "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel.") -IF (NOT CMAKE_BUILD_TYPE) - SET(CMAKE_BUILD_TYPE Release CACHE STRING - "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel." - FORCE) -ENDIF (NOT CMAKE_BUILD_TYPE) +######################################################################################################################## +# Compiler Flags (CMAKE_CXX_FLAGS) +######################################################################################################################## -if(MSVC) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP") +IF(MSVC) + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP" CACHE STRING) ELSE() - # set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") + ## Activating c++0x for gcc + ## currently supported by VTK6.X (bug) + # set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x" CACHE STRING) ENDIF(MSVC) -MESSAGE(" #############################") -MESSAGE(" # CMAKE BUILD TYPE = ${CMAKE_BUILD_TYPE}") -MESSAGE(" #############################") +MESSAGE(STATUS "BUILD TYPE = ${CMAKE_BUILD_TYPE}") - -## Activating c++0x for gcc -## currently supported by VTK6.X (bug) -#SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") - -# for deactivating the rpath within shared object (runtime path defines places -# for loading libraries as abspaths) +# for deactivating the rpath within shared object (runtime path defines places for loading libraries as abspaths) #message("CMAKE does not set RPATH, please adapt your LD_LIBRARY_PATH") #set(CMAKE_SKIP_RPATH true) -# Find VTK +######################################################################################################################## +# Global Dependencies +######################################################################################################################## + + +######################################################################################################################## +# VTK + FIND_PACKAGE(VTK REQUIRED) INCLUDE(${VTK_USE_FILE}) +IF(NOT VTK_FOUND) + message("VTK is required to build MSML") + message("for ubuntu14.10: sudo apt-get install python-vtk6 libvtk6 libvtk6-dev") + message("for ubuntu14.04: sudo apt-get install libvtk5.8 libvtk5-dev") + message("for fedora: yum install vtk-devel.x86_64 vtk-python.x86_64") + message("if you have a own-compiled version please set VTK_DIR") +ENDIF() + +######################################################################################################################## # SWIG FIND_PACKAGE(SWIG REQUIRED) INCLUDE(${SWIG_USE_FILE}) + +IF(NOT SWIG_FOUND) + message("SWIG is required to build MSML") + message("for ubuntu: sudo apt-get install swig") + message("for fedora: yum install swig") + message("if you have a own-compiled version please set the environment PATH variable") +ENDIF() + +SET(SWIG_LANG "python") +FIND_PACKAGE(PythonLibs REQUIRED) + +IF(NOT PYTHON_DEBUG_LIBRARIES) + # linux workaround: + SET(PYTHON_DEBUG_LIBRARIES ${PYTHON_LIBRARIES}) +ENDIF(NOT PYTHON_DEBUG_LIBRARIES) + +SET(WRAPPER_LIBRARIES_RELEASE ${PYTHON_LIBRARIES}) +SET(WRAPPER_LIBRARIES_DEBUG ${PYTHON_DEBUG_LIBRARIES}) +SET(WRAPPER_INCLUDES ${PYTHON_INCLUDE_DIRS}) + +INCLUDE_DIRECTORIES(${WRAPPER_INCLUDES}) + + + IF(WIN32 AND NOT CYGWIN) IF(CMAKE_BUILD_TYPE MATCHES Release) SET(CMAKE_SWIG_OUTDIR ${CMAKE_CURRENT_BINARY_DIR}/bin/release) @@ -52,43 +131,44 @@ ELSE() SET(CMAKE_SWIG_OUTDIR ${CMAKE_CURRENT_BINARY_DIR}/bin) ENDIF() - -#MESSAGE("Include dirs of Python: " ${PYTHON_INCLUDE_DIRS} ) -#message("Libs of Python: " ${PYTHON_LIBRARIES} ) - - +######################################################################################################################## # Find Boost FIND_PACKAGE(Boost COMPONENTS program_options unit_test_framework filesystem iostreams regex - system + system iostreams REQUIRED) INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIR}) -set(Boost_USE_STATIC_LIBS OFF) -add_definitions( -DBOOST_ALL_DYN_LINK ) +SET(Boost_USE_STATIC_LIBS OFF) +ADD_DEFINITIONS(-DBOOST_ALL_DYN_LINK) LINK_DIRECTORIES(${Boost_LIBRARY_DIR}) +IF(NOT SWIG_FOUND) + message("Boost>=1.48 is required to build MSML") + message("Please make following components available: program_options unit_test_framework filesystem iostreams regex system iostreams") + message("for ubuntu: sudo apt-get install libboost …") + message("for fedora: yum install libboost …") +ENDIF() + + #message("Include dirs of Boost : " ${Boost_INCLUDE_DIR} ) #message("cmake module path: " ${CMAKE_MODULE_PATH} ) #message("Booth2 python library: " ${Boost_PYTHON_LIBRARY} ) #MESSAGE("Boost Libraries = " ${Boost_LIBRARIES}) -######################### +######################################################################################################################## # Testing -######################### +######################################################################################################################## INCLUDE(CTest) ENABLE_TESTING() -######################### +######################################################################################################################## # Misc Options -######################### - -SET(PYTHON_SITE_PACKAGE "" - CACHE PATH "Path to python site-package directory") +######################################################################################################################## #SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) # deprecated @@ -104,65 +184,54 @@ SET(CMAKE_OPERATOR_DIRECTORY ${CMAKE_BINARY_DIR}/bin SET(CMAKE_TESTDATA_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../share/testdata CACHE PATH "Choose the test data path.") -add_definitions( -DTESTDATA_PATH="${CMAKE_TESTDATA_PATH}" ) +ADD_DEFINITIONS( -DTESTDATA_PATH="${CMAKE_TESTDATA_PATH}" ) #SET(CMAKE_PYTHON_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/../MSML_Python # CACHE PATH "Choose the test data path.") -FIND_FILE(SOFA_EXECUTABLE "sofaBatch" NAMES "sofaBatch.exe" "sofaBatchExtended" +FIND_FILE(SOFA_EXECUTABLE "sofaBatch" NAMES "runSofa" "runSofa.exe" "sofaBatch.exe" "sofaBatchExtended" DOC "") -FIND_FILE(HIFLOW_EXECUTABLE "hiflow3" NAMES "hiflow3" - DOC "") +FIND_FILE(HIFLOW_EXECUTABLE "hiflow3" NAMES "elasticity" DOC "PATH to elasticity executable") -FIND_FILE(ABAQUS_EXECUTABLE "abaqus" NAMES "abaqus" "abaqus" - DOC "") +FIND_FILE(ABAQUS_EXECUTABLE "abaqus" NAMES "abaqus" "abaqus" DOC "Path to abaqus executable") +IF(NOT SOFA_EXECUTABLE) + message(WARNING "Sofa not find on your system, looked for sofaBatch or runSofa executable. Sofa simulation will not work") +ENDIF() -CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/CMake/Config.xml.in - ${CMAKE_CURRENT_SOURCE_DIR}/../share/Config.xml) -CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/CMake/envconfig.py - ${CMAKE_CURRENT_SOURCE_DIR}/../src/msml/envconfig.py) +IF(NOT ABAQUS_EXECUTABLE) + message(WARNING "Abaqus not find on your system, looked for abaqus executable. Abaqus simulation will not work") +ENDIF() -SET(CMAKE_ECLIPSE_MAKE_ARGUMENTS "-j${x}" CACHE STRING "" FORCE ) -SET(SWIG_LANG "python") -#SET(SWIG_LANG "java") - - -IF( "${SWIG_LANG}" STREQUAL "python") - # Find Python - FIND_PACKAGE(PythonLibs REQUIRED) - if(NOT PYTHON_DEBUG_LIBRARIES) - # linux workaround: - set(PYTHON_DEBUG_LIBRARIES ${PYTHON_LIBRARIES}) - endif(NOT PYTHON_DEBUG_LIBRARIES) - SET(WRAPPER_LIBRARIES_RELEASE ${PYTHON_LIBRARIES}) - SET(WRAPPER_LIBRARIES_DEBUG ${PYTHON_DEBUG_LIBRARIES}) - SET(WRAPPER_INCLUDES ${PYTHON_INCLUDE_DIRS}) -#ELSEIF( "${SWIG_LANG}" EQUAL "java") -ELSE() - FIND_PACKAGE(JNI) - SET(WRAPPER_LIBRARIES_RELEASE ${JNI_LIBRARIES}) - SET(WRAPPER_LIBRARIES_DEBUG ${JNI_LIBRARIES}) - SET(WRAPPER_INCLUDES ${JNI_INCLUDE_DIRS}) - - # this does not work - #message(${JNI_FOUND}) - #IF(NOT ${JNI_FOUND}) - # message("Java Wrapper selected but no JNI found. JAVA_HOME set?") - # RETURN() - #ENDIF() +IF(NOT HIFLOW_EXECUTABLE) + message(WARNING "Hiflow not find on your system, looked for elasticity. Hiflow simulation will not work") ENDIF() +SET(CMAKE_ECLIPSE_MAKE_ARGUMENTS "-j${x}" CACHE STRING "" FORCE ) -#message(${SWIG_LANG}) -#message(${JNI_LIBRARIES}) +## FIND site-package dir from the default Python instance +IF(NOT PYTHON_SITE_PACKAGES) + EXECUTE_PROCESS( COMMAND python -c "from distutils.sysconfig import get_python_lib; print get_python_lib(True)" OUTPUT_VARIABLE PYTHON_SITE_PACKAGES OUTPUT_STRIP_TRAILING_WHITESPACE) +ENDIF() +SET(PYTHON_INSTALL_PACKAGES "${CMAKE_INSTALL_PREFIX}${PYTHON_SITE_PACKAGES}" + CACHE STRING "Python site-package folder") + +message(STATUS "Python Install dir: " ${PYTHON_INSTALL_PACKAGES}) +######################################################################################################################## +# Configure Files +######################################################################################################################## + +CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/CMake/Config.xml.in + ${CMAKE_CURRENT_SOURCE_DIR}/../share/Config.xml) + +CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/CMake/envconfig.py + ${CMAKE_CURRENT_SOURCE_DIR}/../src/msml/envconfig.py) -INCLUDE_DIRECTORIES(${WRAPPER_INCLUDES}) ################################################################################ ## Macro @@ -209,9 +278,25 @@ MACRO(MSML_LIBRARY) ENDIF() TARGET_LINK_LIBRARIES(${ML_NAME} ${ML_LIBRARIES}) - install (TARGETS _${ML_NAME}Python DESTINATION bin) + + ## install of shared object into library + INSTALL(TARGETS ${ML_NAME} LIBRARY DESTINATION lib) + + ## install python extension into site-package folder + INSTALL(TARGETS _${ML_NAME}Python LIBRARY DESTINATION "${PYTHON_INSTALL_PACKAGES}/") + INSTALL(FILES ${CMAKE_SWIG_OUTDIR}/${ML_NAME}Python.py DESTINATION "${PYTHON_INSTALL_PACKAGES}/") + ENDMACRO() +################################################################################ +INSTALL(DIRECTORY "${CMAKE_SOURCE_DIR}/../src/msml" + DESTINATION "${PYTHON_INSTALL_PACKAGES}" + FILES_MATCHING + PATTERN "*.py" + PATTERN "*.xsd" + PATTERN "*.xml" + PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ + GROUP_EXECUTE GROUP_READ) ################################################################################ ## Modules @@ -223,6 +308,3 @@ ADD_SUBDIRECTORY(MiscMeshOperators) ADD_SUBDIRECTORY(CGALOperators) ADD_SUBDIRECTORY(CLI) ADD_SUBDIRECTORY(ACVDOperators) - - -INCLUDE(CPack) diff --git a/src/msml/exporter/hiflow3/__init__.py b/src/msml/exporter/hiflow3/__init__.py index 51e4623b..cb055b5f 100644 --- a/src/msml/exporter/hiflow3/__init__.py +++ b/src/msml/exporter/hiflow3/__init__.py @@ -30,8 +30,6 @@ __authors__ = 'Nicolai Schoch, Alexander Weigl ' __license__ = 'GPLv3' -import os - import jinja2 from msml.model import * @@ -41,12 +39,16 @@ class MSMLHiFlow3ExporterWarning(MSMLWarning): pass + from .. import log from path import path from collections import namedtuple from ..base import Exporter +from .findrot import find_rotation, convert4x4 +from msml.sorts import get_sort, conversion + jinja_env = jinja2.Environment(loader=jinja2.FileSystemLoader(path(__file__).dirname())) SCENE_TEMPLATE = jinja_env.get_template("hiflow_scene.tpl.xml") @@ -155,6 +157,7 @@ def vectors(self): 'sets_surface_supported', 'environment_simulation_steps_supported', 'object_element_fixedConstraint_supported', 'env_timeintegration_dynamicImplicitEuler_supported']) + class HiFlow3Exporter(Exporter): """Exporter for `hiflow3 `_ @@ -195,17 +198,18 @@ def execute(self): """Execute `runHiFlow3` """ - import msml.envconfig - import os + import msml.envconfig + import os - try: - os.makedirs("SimResults") - except: pass + try: + os.makedirs("SimResults") + except: + pass - for scenefile in self.scenes: - cmd = "%s %s" % (msml.envconfig.HIFLOW_EXECUTABLE, scenefile) - log.info("Executing HiFlow3: %s" % cmd) - os.system(cmd) + for scenefile in self.scenes: + cmd = "%s %s" % (msml.envconfig.HIFLOW_EXECUTABLE, scenefile) + log.info("Executing HiFlow3: %s" % cmd) + os.system(cmd) def create_scenes(self): @@ -217,6 +221,13 @@ def create_scenes(self): """ self.scenes = list() + from msml.ext.msmlvtk import transform + + gravity = conversion(str, get_sort('vector.float'))(self._msml_file.env.simulation[0].gravity) + rotmatrix = convert4x4( find_rotation(gravity, (0,0,-1)) ) + + + for msmlObject in self._msml_file.scene: assert isinstance(msmlObject, SceneObject) meshFilename = self.get_value_from_memory(msmlObject.mesh) @@ -268,7 +279,7 @@ def __init__(self): else: SolveInstationary = 0 - #print os.path.abspath(hf3_filename), "!!!!!!" + # print os.path.abspath(hf3_filename), "!!!!!!" with open(hf3_filename, 'w') as fp: content = SCENE_TEMPLATE.render( @@ -297,13 +308,14 @@ def create_bcdata_files(self, obj): :type obj: msml.model.base.SceneObject :return: """ + def create(): for step in self._msml_file.env.simulation: filename = '%s_%s_%s.bc.xml' % (self._msml_file.filename.namebase, obj.id, step.name) data = self.create_bcdata(obj, step.name) - content = BCDATA_TEMPLATE.render(data = data) + content = BCDATA_TEMPLATE.render(data=data) with open(filename, 'w') as h: - h.write(content) + h.write(content) yield filename return list(create()) @@ -328,7 +340,7 @@ def create_bcdata(self, obj, step): else: cs = None - if cs is None: # nothing to do here + if cs is None: # nothing to do here log.warn("No constraint region found for step %s" % step) return bcdata @@ -351,6 +363,7 @@ def create_bcdata(self, obj, step): return bcdata + def count_vector(vec, count): assert len(vec) == 3 vec = map(lambda x: "%0.15f" % float(x), vec) diff --git a/src/msml/exporter/hiflow3/findrot.py b/src/msml/exporter/hiflow3/findrot.py new file mode 100644 index 00000000..9c0da7bc --- /dev/null +++ b/src/msml/exporter/hiflow3/findrot.py @@ -0,0 +1,75 @@ +# -*- encoding: utf-8 -*- +# region gplv3preamble +# The Medical Simulation Markup Language (MSML) - Simplifying the biomechanical modeling workflow +# +# MSML has been developed in the framework of 'SFB TRR 125 Cognition-Guided Surgery' +# +# If you use this software in academic work, please cite the paper: +# S. Suwelack, M. Stoll, S. Schalck, N.Schoch, R. Dillmann, R. Bendl, V. Heuveline and S. Speidel, +# The Medical Simulation Markup Language (MSML) - Simplifying the biomechanical modeling workflow, +# Medicine Meets Virtual Reality (MMVR) 2014 +# +# Copyright (C) 2013-2014 see Authors.txt +# +# If you have any questions please feel free to contact us at suwelack@kit.edu +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# endregionvm + +"""find rotation. + + +http://math.stackexchange.com/questions/180418/calculate-rotation-matrix-to-align-vector-a-to-vector-b-in-3d + +""" +__authors__ = 'Alexander Weigl ' +__license__ = 'GPLv3' + +from numpy import array, matrix, cross, eye, inner, zeros +from numpy.linalg import norm + +__all__ = ['find_rotation', 'conv' + ''] + +def convert4x4(mat): + m = matrix(zeros((4,4))) + m[0:3,0:3] = mat + m[-1,-1] = 1 + return list(m) + +def find_rotation(a, b): + """find the rotation matrix between vector `a` and `b`. + + :param a: + :param b: + :return: + """ + + assert len(a) == 3 + assert len(b) == len(a) + + a = array(a, dtype=float) + b = array(b, dtype=float) + + v = cross(a, b) + s = norm(v) + c = inner(a, b) + + R = eye(3) + skew(v) + skew(v) ** 2 * (1 - c) / s ** 2 + return R + + +def skew(v): + v1, v2, v3 = v + return matrix([[0, -v3, v2], [v3, 0, -v1], [-v2, v1, 0]]) \ No newline at end of file diff --git a/src/msml/ext/msmlvtk.py b/src/msml/ext/msmlvtk.py index ee5eeac9..e8679b38 100644 --- a/src/msml/ext/msmlvtk.py +++ b/src/msml/ext/msmlvtk.py @@ -4,7 +4,7 @@ # MSML has been developed in the framework of 'SFB TRR 125 Cognition-Guided Surgery' # # If you use this software in academic work, please cite the paper: -# S. Suwelack, M. Stoll, S. Schalck, N.Schoch, R. Dillmann, R. Bendl, V. Heuveline and S. Speidel, +# S. Suwelack, M. Stoll, S. Schalck, N.Schoch, R. Dillmann, R. Bendl, V. Heuveline and S. Speidel, # The Medical Simulation Markup Language (MSML) - Simplifying the biomechanical modeling workflow, # Medicine Meets Virtual Reality (MMVR) 2014 # @@ -30,7 +30,7 @@ __author__ = 'Alexander Weigl ' __date__ = '2014-04-14' -from msml.exceptions import MSMLWarning, warn +from msml.exceptions import MSMLWarning import math from itertools import starmap from ..log import logger @@ -39,11 +39,13 @@ class MSMLVTKImportWarning(MSMLWarning): pass + try: import vtk except: logger.warn("Could not import vtk python module. Did you install python-vtk?") + def read_ugrid(filename): if filename.endswith(".pvtu"): reader = vtk.vtkXMLPUnstructuredGridReader() @@ -59,6 +61,7 @@ def read_ugrid(filename): return reader.GetOutput() + def write_surface(ugrid, filename): surface_filter = vtk.vtkDataSetSurfaceFilter() surface_filter.SetInputData(ugrid) @@ -71,6 +74,7 @@ def write_surface(ugrid, filename): writer.SetInputConnection(triangle_filter.GetOutputPort()) writer.Write() + def write_stl(ugrid, filename): surface_filter = vtk.vtkDataSetSurfaceFilter() surface_filter.SetInputConnection(ugrid) @@ -83,7 +87,8 @@ def write_stl(ugrid, filename): writer.SetInputConnection(triangle_filter.GetOutputPort()) writer.Write() -def write_vtu(ugrid, filename, mode = 'ascii'): + +def write_vtu(ugrid, filename, mode='ascii'): writer = vtk.vtkXMLUnstructuredGridWriter() if mode == 'ascii': writer.SetDataModeToAscii() @@ -96,13 +101,15 @@ def write_vtu(ugrid, filename, mode = 'ascii'): writer.SetInputData(ugrid) writer.Write() + def write_vtk(ugrid, filename): writer = vtk.vtkUnstructuredGridWriter() writer.SetFileName(filename) writer.SetInputData(ugrid) writer.Write() -def closest_point(mesh, vector, radius = None): + +def closest_point(mesh, vector, radius=None): locator = vtk.vtkPointLocator() ugrid = read_ugrid(mesh) locator.SetDataSet(ugrid) @@ -117,19 +124,18 @@ def closest_point(mesh, vector, radius = None): index = locator.FindClosestPointWithinRadius(radius, vector, a) point = ugrid.GetPoint(index) - distance = math.sqrt(sum(starmap(lambda a, b: (b-a)**2, zip(vector, point)))) + distance = math.sqrt(sum(starmap(lambda a, b: (b - a) ** 2, zip(vector, point)))) return {'index': index, 'point': point, 'dist': distance} -def get_impact(ugrid, start, direction, factor = 1000): +def get_impact(ugrid, start, direction, factor=1000): cl = vtk.vtkCellLocator() ugrid = read_ugrid(ugrid) cl.SetDataSet(ugrid) - mult = lambda f, x: map(lambda a: f*a, x) + mult = lambda f, x: map(lambda a: f * a, x) end = mult(1000, direction) - points = vtk.vtkPoints() cells = vtk.vtkIdList() @@ -138,10 +144,6 @@ def get_impact(ugrid, start, direction, factor = 1000): ugrid.GetCell(cells.getId(0)) - - - - def view_stl(filename): """ http://www.vtk.org/Wiki/VTK/Examples/Python/STLReader @@ -176,7 +178,7 @@ def view_stl(filename): iren.Start() -def vtp_reader(filename): +def vtp_reader(filename): reader = vtk.vtkXMLPolyDataReader() reader.SetFileName(filename) reader.Update() @@ -187,17 +189,18 @@ def vtp_reader(filename): actor = vtk.vtkActor() actor.SetMapper(mapper) + def unstructered_grid_reader(filename): # Read the source file. reader = vtk.vtkUnstructuredGridReader() reader.SetFileName(filename) - reader.Update() # Needed because of GetScalarRange + reader.Update() # Needed because of GetScalarRange output = reader.GetOutput() scalar_range = output.GetScalarRange() # Create the mapper that corresponds the objects of the vtk file # into graphics elements - mapper =vtk.vtkDataSetMapper() + mapper = vtk.vtkDataSetMapper() mapper.SetInputData(output) mapper.SetScalarRange(scalar_range) @@ -208,7 +211,7 @@ def unstructered_grid_reader(filename): # Create the Renderer renderer = vtk.vtkRenderer() renderer.AddActor(actor) - renderer.SetBackground(1, 1, 1) # Set background to white + renderer.SetBackground(1, 1, 1) # Set background to white # Create the RendererWindow renderer_window = vtk.vtkRenderWindow() @@ -219,3 +222,23 @@ def unstructered_grid_reader(filename): interactor.SetRenderWindow(renderer_window) interactor.Initialize() interactor.Start() + + +def rotate(inputfile, outputfile, alpha, beta, gamma): + pass + + +def transform(inputfile, outputfile, coeffs): + ugrid = read_ugrid(inputfile) + + + matrix = vtk.vtkMatrix4x4() + matrix.DeepCopy(coeffs) + adapter = vtk.vtkMatrixToLinearTransform() + adapter.SetInput(matrix) + tfilter = vtk.vtkTransformFilter() + tfilter.SetInputData(ugrid) + tfilter.SetTransform(adapter) + vgrid = tfilter.GetOutput() + write_vtu(vgrid, outputfile) + return outputfile diff --git a/src/msml/model/__init__.py b/src/msml/model/__init__.py index bed9ff4a..76bf66a7 100644 --- a/src/msml/model/__init__.py +++ b/src/msml/model/__init__.py @@ -43,7 +43,7 @@ from .alphabet import * from .base import * -from .writer import * +#from .writer import * from .dag import * diff --git a/src/msmltest/findrot_test.py b/src/msmltest/findrot_test.py new file mode 100644 index 00000000..5b9762ab --- /dev/null +++ b/src/msmltest/findrot_test.py @@ -0,0 +1,46 @@ +import numpy +import unittest + +__author__ = 'weigl' + +from msml.exporter.hiflow3.findrot import find_rotation, convert4x4 + + +class FindRotTest(unittest.TestCase): + def test_findrot1(self): + a = (0, 0, 1) + b = (0, 1, 0) + + R = find_rotation(a, b) + self.assertEqualDirection(b, R.dot(a)) + + def test_findrot2(self): + a = (10, 2, 6) + b = (0, 0, -9.81) + R = find_rotation(a, b) + + self.assertEqualDirection(b, R.dot(a)) + + + def assertEqualDirection(self, expected, got): + e = numpy.array(expected, dtype=float) + g = numpy.array(got, dtype=float) + + e = 1 / numpy.linalg.norm(e) * e + g = 1 / numpy.linalg.norm(g) * g + + self.assertTrue( + numpy.linalg.norm(e - g) < 1e-14, + "got %s , expected %s" % (g, e) + ) + + + def test_convert4x4(self): + mat = numpy.matrix([1, 2, 3, 4, 5, 6, 7, 8, 9]).reshape((3, 3)) + + ref = numpy.matrix([[1, 2, 3, 0], [4, 5, 6, 0], [7, 8, 9, 0], [0, 0, 0, 1]], dtype=float) + n = convert4x4(mat) + + for i in range(4): + for j in range(4): + self.assertEquals(ref[i,j] == n[i,j])