diff --git a/Doxyfile b/Doxyfile new file mode 100644 index 0000000..260780a --- /dev/null +++ b/Doxyfile @@ -0,0 +1,1287 @@ +# Doxyfile 1.5.3 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project +# +# All text after a hash (#) is considered a comment and will be ignored +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" ") + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file that +# follow. The default is UTF-8 which is also the encoding used for all text before +# the first occurrence of this tag. Doxygen uses libiconv (or the iconv built into +# libc) for the transcoding. See http://www.gnu.org/software/libiconv for the list of +# possible encodings. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded +# by quotes) that should identify the project. + +PROJECT_NAME = BTS + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = 0.1 + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = doc + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create +# 4096 sub-directories (in 2 levels) under the output directory of each output +# format and will distribute the generated files over these directories. +# Enabling this option can be useful when feeding doxygen a huge amount of +# source files, where putting all generated files in the same directory would +# otherwise cause performance problems for the file system. + +CREATE_SUBDIRS = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, +# Croatian, Czech, Danish, Dutch, Finnish, French, German, Greek, Hungarian, +# Italian, Japanese, Japanese-en (Japanese with English messages), Korean, +# Korean-en, Lithuanian, Norwegian, Polish, Portuguese, Romanian, Russian, +# Serbian, Slovak, Slovene, Spanish, Swedish, and Ukrainian. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is +# used as the annotated text. Otherwise, the brief description is used as-is. +# If left blank, the following values are used ("$name" is automatically +# replaced with the name of the entity): "The $name class" "The $name widget" +# "The $name file" "is" "provides" "specifies" "contains" +# "represents" "a" "an" "the" + +ABBREVIATE_BRIEF = "The $name class " "The $name widget " "The $name file " is provides specifies contains represents a an the + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = YES + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the +# path to strip. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of +# the path mentioned in the documentation of a class, which tells +# the reader which header file to include in order to use a class. +# If left blank only the name of the header file containing the class +# definition is used. Otherwise one should specify the include paths that +# are normally passed to the compiler using the -I flag. + +STRIP_FROM_INC_PATH = lib src cmd + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful is your file systems +# doesn't support long names like on DOS, Mac, or CD-ROM. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like regular Qt-style comments +# (thus requiring an explicit @brief command for a brief description.) + +JAVADOC_AUTOBRIEF = NO + +# If the QT_AUTOBRIEF tag is set to YES then Doxygen will +# interpret the first line (until the first dot) of a Qt-style +# comment as the brief description. If set to NO, the comments +# will behave just like regular Qt-style comments (thus requiring +# an explicit \brief command for a brief description.) + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# re-implements. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce +# a new page for each member. If set to NO, the documentation of a member will +# be part of the file/class/namespace that contains it. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 8 + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C +# sources only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. + +OPTIMIZE_OUTPUT_FOR_C = NO + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java +# sources only. Doxygen will then generate output that is more tailored for Java. +# For instance, namespaces will be presented as packages, qualified scopes +# will look different, etc. + +OPTIMIZE_OUTPUT_JAVA = NO + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want to +# include (a tag file for) the STL sources as input, then you should +# set this tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. +# func(std::string) {}). This also make the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. + +CPP_CLI_SUPPORT = NO + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. + +SUBGROUPING = YES + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = YES + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = NO + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + +EXTRACT_LOCAL_CLASSES = NO + +# This flag is only useful for Objective-C code. When set to YES local +# methods, which are defined in the implementation section but not in +# the interface are included in the documentation. +# If set to NO (the default) only methods in the interface are included. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be extracted +# and appear in the documentation as a namespace called 'anonymous_namespace{file}', +# where file will be replaced with the base name of the file that contains the anonymous +# namespace. By default anonymous namespace are hidden. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. + +CASE_SENSE_NAMES = NO + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = YES + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = YES + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the +# brief documentation of file, namespace and class members alphabetically +# by member name. If set to NO (the default) the members will appear in +# declaration order. + +SORT_BRIEF_DOCS = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be +# sorted by fully-qualified names, including namespaces. If set to +# NO (the default), the class list will be sorted only by class name, +# not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the +# alphabetical list. + +SORT_BY_SCOPE_NAME = YES + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. + +GENERATE_DEPRECATEDLIST = YES + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or define consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and defines in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + +SHOW_USED_FILES = YES + +# If the sources in your project are distributed over multiple directories +# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy +# in the documentation. The default is NO. + +SHOW_DIRECTORIES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from the +# version control system). Doxygen will invoke the program by executing (via +# popen()) the command , where is the value of +# the FILE_VERSION_FILTER tag, and is the name of an input file +# provided by doxygen. Whatever the program writes to standard output +# is used as the file version. See the manual for examples. + +FILE_VERSION_FILTER = + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = YES + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = NO + +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that +# don't exist or using markup commands wrongly. + +WARN_IF_DOC_ERROR = YES + +# This WARN_NO_PARAMDOC option can be abled to get warnings for +# functions that are documented, but have no documentation for their parameters +# or return value. If set to NO (the default) doxygen will only warn about +# wrong or incomplete parameter documentation, but not about the absence of +# documentation. + +WARN_NO_PARAMDOC = NO + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. Optionally the format may contain +# $version, which will be replaced by the version of the file (if it could +# be obtained via FILE_VERSION_FILTER) + +WARN_FORMAT = "$file:$line: $text " + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = src cmd + +# This tag can be used to specify the character encoding of the source files that +# doxygen parses. Internally doxygen uses the UTF-8 encoding, which is also the default +# input encoding. Doxygen uses libiconv (or the iconv built into libc) for the transcoding. +# See http://www.gnu.org/software/libiconv for the list of possible encodings. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx +# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py + +FILE_PATTERNS = *.h + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = YES + +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. + +EXCLUDE = lib/file/nifti1.h + +# The EXCLUDE_SYMLINKS tag can be used select whether or not files or +# directories that are symbolic links (a Unix filesystem feature) are excluded +# from the input. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. Note that the wildcards are matched +# against the file with absolute path, so to exclude all test directories +# for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the output. +# The symbol name can be a fully qualified name, a word, or if the wildcard * is used, +# a substring. Examples: ANamespace, AClass, AClass::ANamespace, ANamespace::*Test + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = * + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command , where +# is the value of the INPUT_FILTER tag, and is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. If FILTER_PATTERNS is specified, this tag will be +# ignored. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: +# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further +# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER +# is applied to all files. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). + +FILTER_SOURCE_FILES = NO + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also +# VERBATIM_HEADERS is set to NO. If you have enabled CALL_GRAPH or CALLER_GRAPH +# then you must also enable this option. If you don't then doxygen will produce +# a warning and turn it on anyway + +SOURCE_BROWSER = YES + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES (the default) +# then for each documented function all documented +# functions referencing it will be listed. + +REFERENCED_BY_RELATION = NO + +# If the REFERENCES_RELATION tag is set to YES (the default) +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION = NO + +# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) +# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from +# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will +# link to the source code. Otherwise they will link to the documentstion. + +REFERENCES_LINK_SOURCE = YES + +# If the USE_HTAGS tag is set to YES then the references to source code +# will point to the HTML generated by the htags(1) tool instead of doxygen +# built-in source browser. The htags tool is part of GNU's global source +# tagging system (see http://www.gnu.org/software/global/global.html). You +# will need version 4.8.6 or higher. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = YES + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet. Note that doxygen will try to copy +# the style sheet file to the HTML output directory, so don't put your own +# stylesheet in the HTML output directory as well, or it will be erased! + +HTML_STYLESHEET = + +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to +# NO a bullet list will be used. + +HTML_ALIGN_MEMBERS = YES + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compressed HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. For this to work a browser that supports +# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox +# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). + +HTML_DYNAMIC_SECTIONS = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output directory. + +CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. + +HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + +GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. + +TOC_EXPAND = NO + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index at +# top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. + +DISABLE_INDEX = NO + +# This tag can be used to set the number of enum values (range [1..20]) +# that doxygen will group on one line in the generated HTML documentation. + +ENUM_VALUES_PER_LINE = 4 + +# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be +# generated containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, +# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are +# probably better off using the HTML help feature. + +GENERATE_TREEVIEW = YES + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = NO + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, a4wide, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = a4wide + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = NO + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = NO + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. + +LATEX_HIDE_INDICES = NO + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. + +GENERATE_XML = NO + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `xml' will be used as the default path. + +XML_OUTPUT = xml + +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_SCHEMA = + +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_DTD = + +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will +# dump the program listings (including syntax highlighting +# and cross-referencing information) to the XML output. Note that +# enabling this will significantly increase the size of the XML output. + +XML_PROGRAMLISTING = YES + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# to generate PDF and DVI output from the Perl module output. + +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. This is useful +# if you want to understand what is going on. On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = YES + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_DEFINED tags. + +EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# in the INCLUDE_PATH (see below) will be search if a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. To prevent a macro definition from being +# undefined via #undef or recursively expanded use the := operator +# instead of the = operator. + +PREDEFINED = + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all function-like macros that are alone +# on a line, have an all uppercase name, and do not end with a semicolon. Such +# function macros are typically used for boiler-plate code, and will confuse +# the parser if not removed. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES option can be used to specify one or more tagfiles. +# Optionally an initial location of the external documentation +# can be added for each tagfile. The format of a tag file without +# this location is as follows: +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths or +# URLs. If a location is present for each tag, the installdox tool +# does not have to be run to correct the links. +# Note that each tag file must have a unique name +# (where the name does NOT include the path) +# If a tag file is not located in the directory in which doxygen +# is run, you must also specify the path to the tagfile here. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. + +EXTERNAL_GROUPS = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base +# or super classes. Setting the tag to NO turns the diagrams off. Note that +# this option is superseded by the HAVE_DOT option below. This is only a +# fallback. It is recommended to install and use dot, since it yields more +# powerful graphs. + +CLASS_DIAGRAMS = NO + +# You can define message sequence charts within doxygen comments using the \msc +# command. Doxygen will then run the mscgen tool (see http://www.mcternan.me.uk/mscgen/) to +# produce the chart and insert it in the documentation. The MSCGEN_PATH tag allows you to +# specify the directory where the mscgen tool resides. If left empty the tool is assumed to +# be found in the default search path. + +MSCGEN_PATH = + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + +HIDE_UNDOC_RELATIONS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = NO + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# the CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = YES + +# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for groups, showing the direct groups dependencies + +GROUP_GRAPHS = YES + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. + +UML_LOOK = NO + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + +TEMPLATE_RELATIONS = NO + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + +INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + +INCLUDED_BY_GRAPH = YES + +# If the CALL_GRAPH, SOURCE_BROWSER and HAVE_DOT tags are set to YES then doxygen will +# generate a call dependency graph for every global function or class method. +# Note that enabling this option will significantly increase the time of a run. +# So in most cases it will be better to enable call graphs for selected +# functions only using the \callgraph command. + +CALL_GRAPH = NO + +# If the CALLER_GRAPH, SOURCE_BROWSER and HAVE_DOT tags are set to YES then doxygen will +# generate a caller dependency graph for every global function or class method. +# Note that enabling this option will significantly increase the time of a run. +# So in most cases it will be better to enable caller graphs for selected +# functions only using the \callergraph command. + +CALLER_GRAPH = NO + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = YES + +# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES +# then doxygen will show the dependencies a directory has on other directories +# in a graphical way. The dependency relations are determined by the #include +# relations between the files in the directories. + +DIRECTORY_GRAPH = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are png, jpg, or gif +# If left blank png will be used. + +DOT_IMAGE_FORMAT = png + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found in the path. + +DOT_PATH = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS = + +# The MAX_DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of +# nodes that will be shown in the graph. If the number of nodes in a graph +# becomes larger than this value, doxygen will truncate the graph, which is +# visualized by representing a node as a red box. Note that doxygen if the number +# of direct children of the root node in a graph is already larger than +# MAX_DOT_GRAPH_NOTES then the graph will not be shown at all. Also note +# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. + +DOT_GRAPH_MAX_NODES = 50 + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the +# graphs generated by dot. A depth value of 3 means that only nodes reachable +# from the root by following a path via at most 3 edges will be shown. Nodes +# that lay further from the root node will be omitted. Note that setting this +# option to 1 or 2 may greatly reduce the computation time needed for large +# code bases. Also note that the size of a graph can be further restricted by +# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. + +MAX_DOT_GRAPH_DEPTH = 1000 + +# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent +# background. This is disabled by default, which results in a white background. +# Warning: Depending on the platform used, enabling this option may lead to +# badly anti-aliased labels on the edges of a graph (i.e. they become hard to +# read). + +DOT_TRANSPARENT = NO + +# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output +# files in one run (i.e. multiple -o and -T options on the command line). This +# makes dot run faster, but since only newer versions of dot (>1.8.10) +# support this, this feature is disabled by default. + +DOT_MULTI_TARGETS = NO + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate +# the various graphs. + +DOT_CLEANUP = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to the search engine +#--------------------------------------------------------------------------- + +# The SEARCHENGINE tag specifies whether or not a search engine should be +# used. If set to NO the values of all tags below this one will be ignored. + +SEARCHENGINE = NO diff --git a/algorithm_outline.txt b/algorithm_outline.txt new file mode 100644 index 0000000..1a0d37c --- /dev/null +++ b/algorithm_outline.txt @@ -0,0 +1,32 @@ +MR::Math::Matrix(points, point_conv, strand.matrix()) +MR::Math::Matrix(tang, tang_conv, strand.matrix()) + +(VoxelSize, ResponseFunction, parameters to Image class) + +BTS::Image::Neighbourhood::reserve() --set initially to some reasonable number +BTS::Image::Neighbourhood::add_section(points.row(x), tang.row(x), *strand, point_conv.row(x), tang_conv.row(x)) (maybe include pointers to intermediately generated structures as well) + +BTS::Image::Neighbourhood::calculate_intensities() + internally store points in a Nx3 matrix and tangents in a Nx3 matrices + have the list of voxel centres as Lx3 matrix and dw orientations as a 3xQ matrix + Then should have a LxNx3 distance array, Nx1 length vector, and a NxQ angle matrix. + + response_functions as a NxQ matrix (will need to to column-wise multiplication and collecting on angle matrix) to produce another NxQ response matrix. + + columnwise multiplication of length_vector and angle matrix produces another NxQ matrix (probably could be incorporated into response function step I think) + + interpolation function operates on LxNx3 to produce LxN interpolation intensities + + matrix multiplication produces LxQ intensity matrix. + +BTS::Image::collate_neighbourhoods(Neighbourhood) + + takes LxQ matrices from neighbourhoods and collates them into L'xQ image data matrix. + +BTS::Image::Neighbourood::calculate_gradients_hessians + Then take collated intensities and put them back into the calculate the gradient + Hessian + reusing the precalculated interpolation and response matrices. + + + BTS::Image::collate_gradients_hessians(Neighbourhood) + this is done per neighbourhood calculation to prevent large memory allocation problems diff --git a/bash/add_base_intensity b/bash/add_base_intensity new file mode 100755 index 0000000..17ea959 --- /dev/null +++ b/bash/add_base_intensity @@ -0,0 +1,25 @@ +#!/bin/bash + +DIR=$1 + +if [ "${#DIR}" = 0 ]; then + DIR='.' +fi + +for f in `ls $DIR/*.tck`; do + + if [ -h $f ]; then + file=`readlink $f` + else + file=$f + fi + + file_strip=${file##*/} + + select_fibres $file /tmp/$file_strip.txt + + sed -i 's/base_intensity: 0/base_intensity: 1/g' /tmp/$file_strip.txt + + select_fibres /tmp/$file_strip.txt $file + +done diff --git a/bash/add_density b/bash/add_density new file mode 100755 index 0000000..ac118d2 --- /dev/null +++ b/bash/add_density @@ -0,0 +1,25 @@ +#!/bin/bash + +DIR=$1 + +if [ "${#DIR}" = 0 ]; then + DIR='.' +fi + +for f in `ls $DIR/*.tckx`; do + + if [ -h $f ]; then + file=`readlink $f` + else + file=$f + fi + + if [ `grep -c "density" $file` = 0 ]; then + + sed -i 's/^/1\t/g' $file + + sed -i 's/1\t%%% Extended Properties File %%% - keys: /%%% Extended Properties File %%% - keys: density\t/g' $file + + fi + +done diff --git a/bash/create_fibres b/bash/create_fibres new file mode 100755 index 0000000..39c8f62 --- /dev/null +++ b/bash/create_fibres @@ -0,0 +1,30 @@ +#!/bin/bash + +#if [ $# -le 1 ]; then +# echo "At least 1 argument need to be supplied to $0 ($# supplied)." +# exit -1 +#fi + +if [ ${1##*.} == 'txt' ]; then + + new_fibres $1 ${@:2} + + vi $1 + +else + + TEMP_TXT_FILE=/tmp/${1##*/}.txt + + #Export fibres file to a temporary text equivalent. + new_fibres $TEMP_TXT_FILE ${@:2} + + #Edit with vi + vi $TEMP_TXT_FILE + + #Import fibres back to output location + select_fibres $TEMP_TXT_FILE $1 + + #Cleanup temporary file + rm $TEMP_TXT_FILE + +fi diff --git a/bash/edit_fibres b/bash/edit_fibres new file mode 100755 index 0000000..041426b --- /dev/null +++ b/bash/edit_fibres @@ -0,0 +1,28 @@ +#!/bin/bash + +if [ $# == 0 ]; then + echo "No arguments supplied to $0 (at least 1 required)." + exit -1 +elif [ $# == 1 ]; then + OUTPUT_LOCATION=$1 +elif [ $# == 2 ]; then + OUTPUT_LOCATION=$2 +else + echo "Too many arguments ($#) supplied to $0 (max 2, input and output locations)." + exit -1 +fi + + +TEMP_TXT_FILE=/tmp/${1##*/}.txt + +#Export fibres file to a temporary text equivalent. +select_fibres $1 $TEMP_TXT_FILE + +#Edit with vi +vi $TEMP_TXT_FILE + +#Import fibres back to output location +select_fibres $TEMP_TXT_FILE $OUTPUT_LOCATION + +#Cleanup temporary file +rm $TEMP_TXT_FILE diff --git a/bash/metropolis b/bash/metropolis new file mode 120000 index 0000000..baa5aae --- /dev/null +++ b/bash/metropolis @@ -0,0 +1 @@ +../metropolis_release/tractography \ No newline at end of file diff --git a/bash/process_collections b/bash/process_collections new file mode 100755 index 0000000..779d952 --- /dev/null +++ b/bash/process_collections @@ -0,0 +1,43 @@ +#!/bin/bash + +export neigh_count=0 + +neigh_size=3 +vox_size=0.15 +extent=3 +neigh_bounds=0.61 +cube_size=1.05 + +input_dir=/data/home/tclose/Data/Fifty_phantoms/ +output_dir=/data/home/tclose/Data/Tractography/chunked + +for collection_path in `ls $input_dir`; do + + extension=${collection_path##*.} + + if [ $extension = "tck" ]; then + coll_name=${collection_path##*/} + coll_name=${coll_name%.*} + + echo "--$coll_name--" + +# rm -r $output_dir/${coll_name}/vox_${vox_size} +# mkdir $output_dir/${coll_name}/vox_${vox_size} + +# chunk_strands $input_dir/$collection_path $output_dir/${coll_name}/vox_${vox_size}/cube_${cube_size}.tck -extent $extent -voxel_size $vox_size -map_to_origin -save_separate -half_offset -neigh_bounds $neigh_bounds + +# rm -r $output_dir/${coll_name}/vox_${vox_size}/ball_combined +# mkdir $output_dir/${coll_name}/vox_${vox_size}/ball_combined + + process_neighbourhoods $output_dir/${coll_name}/vox_${vox_size}/cube_${cube_size} $output_dir/${coll_name}/vox_${vox_size} + +# ls $output_dir/${coll_name}/vox_${vox_size}/prepared_strands $output_dir/prepared_strands/${coll_name}.frr + + #combine_strands $output_dir/${coll_name}/vox_${vox_size}/ball_combined $output_dir/ball_combined/${coll_name}.frr + + fi + +done + + +#combine_strands $output_dir/ball_combined/ $output_dir/ball_combined.frr diff --git a/bash/process_neighbourhoods b/bash/process_neighbourhoods new file mode 100755 index 0000000..bf8f6c3 --- /dev/null +++ b/bash/process_neighbourhoods @@ -0,0 +1,79 @@ +#!/bin/bash + +new_sphere_r=0.34 +length_reject_threshold=0.005 +inclusion_radius=0.13 +perturb=0.0075 +degree=3 +ref_image_degree=20 +neigh_size=3 +vox_size=0.15 + +new_sphere_d=0.78 +inclusion_diameter=0.26 + + +neigh_pattern=${1##*/} +base_path=${1%/$neigh_pattern} +output_path=$2 + +for neigh_path in `ls $1*`; do + + neigh_file=${neigh_path##*/} + + neigh=${neigh_file:$(( ${#neigh_pattern} + 1 )):$(( ${#neigh_file} - 5 - ${#neigh_pattern} ))} + echo $neigh + + + +# rm -r $base_path/$neigh + +# mkdir $base_path/$neigh +# mkdir $base_path/$neigh/images +# mkdir $base_path/$neigh/metropolis_hastings +# mkdir $base_path/$neigh/strands + + +# mkdir $base_path/$neigh/metropolis_hastings/A + + +# cp $base_path/$neigh_file $base_path/$neigh/strands/cube.tck + + +# trim_tcks $base_path/$neigh/strands/cube.tck $base_path/$neigh/strands/ball.tck -new_sphere_r ${new_sphere_r} -length_reject_threshold ${length_reject_threshold} + +# peel_tcks $base_path/$neigh/strands/ball.tck $base_path/$neigh/strands/peeled.tck -inclusion_radius $inclusion_radius + +# tck2fourier $base_path/$neigh/strands/peeled.tck $base_path/$neigh/strands/peeled.frr -degree ${degree} + +# perturb_fouriers $base_path/$neigh/strands/peeled.frr $base_path/$neigh/metropolis_hastings/A/initial.frr -perturb $perturb + +# rm $base_path/$neigh/images/tophat.mif + +# tck2fourier $base_path/$neigh/strands/$neigh_pattern.tck $base_path/$neigh/strands/cube_for_ref.frr -degree $ref_image_degree + +# expected_image $base_path/$neigh/strands/cube_for_ref.frr /data/home/tclose/Data/Gradient_directions/encoding_60.b $base_path/$neigh/images/tophat.mif -vox_size ${vox_size} -num_voxels 3 -points 100 + +# tck2fourier $base_path/$neigh/strands/sphere_0.78.tck $base_path/$neigh/strands/ball.frr -degree 3 + +# cp $base_path/$neigh/strands/ball.frr $output_path/ball_combined/$neigh.frr + +#echo $neigh_count + +#mv $base_path/$neigh/strands/cube_1.05.tck $base_path/$neigh/strands/cube.tck + +#mv $base_path/$neigh/strands/sphere_0.78.tck $base_path/$neigh/strands/ball.tck + +#rm $base_path/$neigh/strands/cube_1.05-frr_20.frr + +#rm $base_path/$neigh/strands/sphere_0.78* + +#tcks2fouriers $base_path/$neigh/strands/ball.tck $base_path/$neigh/strands/ball.frr -degree 3 + +ln -s $base_path/$neigh/strands /data/home/tclose/Data/Tractography/chunked/vox_0.15/strands/$neigh_count + +#ls $base_path/$neigh/strands + +#neigh_count=$(( $neigh_count + 1 )) + +done diff --git a/bash/rename_frr b/bash/rename_frr new file mode 100755 index 0000000..fe3ac97 --- /dev/null +++ b/bash/rename_frr @@ -0,0 +1,24 @@ +#!/bin/bash + +directory_name=$1 + +for file in `ls $directory_name/*.frr`; do + + svn move $file ${file/%.frr/.str}; + +done + +for file in `ls $directory_name/*.frrx`; do + + svn move $file ${file/%.frrx/.strx}; + +done + +for file in `ls $directory_name/*.frrxx`; do + + svn move $file ${file/%.frrxx/.strxx}; + +done + + +svn commit -m "renaming '.frr' to '.str' in directory $directory_name" \ No newline at end of file diff --git a/bash/test_bed b/bash/test_bed new file mode 120000 index 0000000..4d6ecd0 --- /dev/null +++ b/bash/test_bed @@ -0,0 +1 @@ +../test_bed/tractography \ No newline at end of file diff --git a/build b/build new file mode 100755 index 0000000..d65b38c --- /dev/null +++ b/build @@ -0,0 +1,16 @@ +#!/bin/bash + +#TARGET='src/bts/fibre/base.o' +#TARGET='bin/stress_tester' + +if [ ${#TARGET} -gt 0 ]; then + + echo + echo "WARNING!! Only building for target $TARGET" + echo + + +fi + +/home/tclose/Code/MRtrix/build $TARGET $@ + diff --git a/build_debug b/build_debug new file mode 100755 index 0000000..315d0f7 --- /dev/null +++ b/build_debug @@ -0,0 +1,26 @@ +#!/bin/bash + +#CMD_TARGET='dummy' +#OBJ_TARGET='fibre/tractlet/set/walker' + +if [ ${#CMD_TARGET} -gt 0 ]; then + + echo + echo "WARNING!! Only building for target $CMD_TARGET" + echo + + TARGET=bin/${CMD_TARGET}__debug + +elif [ ${#OBJ_TARGET} -gt 0 ]; then + + echo + echo "WARNING!! Only building for target $OBJ_TARGET" + echo + + TARGET=src/bts/${OBJ_TARGET}__debug.o + +fi + +echo $TARGET + +/home/tclose/Code/MRtrix/build debug $TARGET $@ diff --git a/cmd/add_encodings.cpp b/cmd/add_encodings.cpp new file mode 100644 index 0000000..9b0b3f5 --- /dev/null +++ b/cmd/add_encodings.cpp @@ -0,0 +1,88 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + + +extern "C" { +#include +#include +} + + +#include "bts/cmd.h" +#include "progressbar.h" + +#include "bts/common.h" +#include "bts/image/expected/buffer.h" +#include "bts/image/observed/buffer.h" + +#include "bts/image/noise.h" +#include "bts/image/noise/gaussian.h" + + + +#include "bts/inline_functions.h" + +using namespace BTS; + +SET_VERSION_DEFAULT; +SET_AUTHOR ("Thomas G. Close"); +SET_COPYRIGHT (NULL); + +DESCRIPTION = { + "Adds encoding to an image.", + "", + NULL +}; + +ARGUMENTS = { + Argument ("image", "The image.").type_file(), + + Argument ("encodings", "The gradient encodings to be added to the image").type_file (), + + Argument() +}; + + +OPTIONS = { + +Option() + +}; + + + +EXECUTE { + + + std::string image_location = argument[0]; + std::string encodings_location = argument[1]; + + Image::Observed::Buffer image(image_location, Diffusion::Encoding::Set(encodings_location)); + + MR::ProgressBar progress_bar ("Adding gradient encodings to image file..."); + + image.save(image_location); + + +} + + diff --git a/cmd/average_fibres.cpp b/cmd/average_fibres.cpp new file mode 100644 index 0000000..e6dc50e --- /dev/null +++ b/cmd/average_fibres.cpp @@ -0,0 +1,245 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Written by Thomas G. Close, 04/03/2009. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + +#include "bts/cmd.h" +#include "point.h" +#include "progressbar.h" + +#include "bts/common.h" +#include "bts/file.h" + +#include "bts/fibre/strand/set.h" +#include "bts/fibre/track/set.h" +#include "bts/fibre/tractlet/set.h" +#include "bts/fibre/properties/extended.h" + +#include "bts/fibre/base/writer.h" + + + +#include "bts/image/expected/buffer.h" + + +#include "bts/inline_functions.h" + + +using namespace BTS; + + +const double MIN_ACS_DEFAULT = 0.001; + +template void average_fibres(const std::string& input_location, const std::string& output_location, + const std::vector& include, double min_acs); + +template double acs(const T& fibre); + +SET_VERSION_DEFAULT; +SET_AUTHOR ("Thomas G. Close"); +SET_COPYRIGHT (NULL); + +DESCRIPTION = { + "Average a set of fibres sets, inluding the option to remove thin tractlets.", + "", + NULL +}; + +ARGUMENTS = { + Argument ("input", "The fibres to be selected from.").type_file (), + Argument ("output", "The selected fibres.").type_file (), + Argument() +}; + + +OPTIONS = { + + Option ("include","The indices of the strands to include") + + Argument ("include",""), + + Option ("min_acs","Minimum area of tractlet to include") + + Argument ("include","").type_float (0,LARGE_FLOAT, MIN_ACS_DEFAULT), + + +Option() }; + + +EXECUTE { + + std::string input_location = argument[0]; + std::string output_location = argument[1]; + + std::vector include; + double min_acs; + + Options opt = get_options("include"); + if (opt.size()) + include = parse_sequence (opt[0][0]); + + + if (File::has_extension(input_location)) { + + if (get_options("min_acs").size()) + throw Exception("Cannot use min_acs option when averaging strand sets (because they have none)."); + + min_acs = -1; + + } else if (File::has_extension(input_location)) { + + opt = get_options("min_acs"); + if (opt.size()) + min_acs = opt[0][0]; + else + min_acs = MIN_ACS_DEFAULT; + + } else + throw Exception ("Unsupported extension of file '" + input_location + "'."); + + + + if (File::has_extension(input_location)) { + + average_fibres(input_location, output_location, include, min_acs); + + } else if (File::has_extension(input_location)) { + + average_fibres(input_location, output_location, include, min_acs); + + } else + throw Exception ("Unsupported extension of file '" + input_location + "'."); + + + } + + + + +template void average_fibres(const std::string& input_location, const std::string& output_location, + const std::vector& include, double min_acs) { + + + if (!File::has_extension(output_location)) + throw Exception ("Mismatching extension of output location '" + output_location + "' for input '" + input_location + "'."); + + + typename T::Set fibres, avg_fibres; + + typename T::Set::Reader reader(input_location); + + size_t set_count = to(reader.get_extend_props()["count"]); + + //Read first tractlets set from input file, save to avg_fibres to set correct size then rewind the reader back to the start. + if (!reader.next(avg_fibres)) + throw Exception ("No sets loaded from input location '" + input_location + "'."); + + avg_fibres.zero(); + reader.rewind(); + + std::vector avg_acss(avg_fibres.size()); + + //Variables to loop through tract sets with. + size_t set_i = 0; + std::vector includes_not_found = include; + + MR::ProgressBar avg_progress_bar("Generating average set...", set_count); + + while (reader.next(fibres)) { + + //Check to see if current set is listed in included list. + std::vector::iterator include_it = find(includes_not_found.begin(), includes_not_found.end(), set_i); + + bool include_set = true; + + if (include.size()) { + if (include_it == includes_not_found.end()) + include_set = false; + else + //Remove matched include from list. + includes_not_found.erase(include_it); + } + + if (include_set) { + + if (fibres.size() != avg_fibres.size()) + throw Exception ("Size of set " + str(set_i) + " (" + str(fibres.size()) + ") does not match that of initial set (" + str(avg_fibres.size()) + ")."); + + avg_fibres += fibres; + + for (size_t elem_i = 0; elem_i < fibres.size(); ++elem_i) + avg_acss[elem_i] += acs(fibres[elem_i]); + + } + + ++set_i; + ++avg_progress_bar; + + } + + if (includes_not_found.size() != 0) + throw Exception ("Indices, " + str(includes_not_found) + ", were outside the range of the number of loaded sets."); + + size_t num_included_sets; + + if (include.size()) + num_included_sets = include.size(); + else + num_included_sets = set_i; + + + avg_fibres /= (double)num_included_sets; + + typename T::Set output_set(std::vector(), reader.elem_prop_keys()); + + MR::ProgressBar min_vol_progress_bar ("Excluding fibres that are thinner than average acs...", avg_fibres.size()); + + for (size_t elem_i = 0; elem_i < avg_fibres.size(); ++elem_i) { + + avg_acss[elem_i] /= (double)num_included_sets; + + if (avg_acss[elem_i] >= min_acs) { + + output_set.push_back(avg_fibres[elem_i]); + + } + + + ++min_vol_progress_bar; + } + + + output_set.save(output_location); + +} + + +template <> double acs(const Fibre::Strand& fibre) { + + return 0.0; + +} + + +template <> double acs(const Fibre::Tractlet& fibre) { + + return fibre.acs(); + +} + + diff --git a/cmd/cluster_strands.cpp b/cmd/cluster_strands.cpp new file mode 100644 index 0000000..e36b67d --- /dev/null +++ b/cmd/cluster_strands.cpp @@ -0,0 +1,369 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Written by Thomas G. Close, 04/03/2009. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + +*/ + +#include + +#include "bts/cmd.h" + +#include "progressbar.h" + +#include "bts/common.h" + +#include "bts/fibre/strand/set.h" + +#include "k_means/KMlocal.h" // k-means algorithms + + + + +#include "bts/inline_functions.h" + + +using namespace BTS; + +SET_VERSION_DEFAULT; +SET_AUTHOR ("Thomas G. Close"); +SET_COPYRIGHT (NULL); + +DESCRIPTION = { + "Clusters strands together and returns the cluster centres as a new strand set.", + "", + NULL +}; + +ARGUMENTS = { + Argument ("input", "The strands to be merged.").type_file (), + Argument ("output", "The output merged strands").type_file(), + Argument() +}; + + +OPTIONS = { + + Option ("new_num_strands", "The number of strands ('k' in k-means) in the strands will be clustered into.") + + Argument ("new_num_strands", "The number of strands ('k' in k-means) in the strands will be clustered into.").type_integer (1, 1000, 20), + + Option ("save_clusters", "Save the generated clusters as seperate Strand sets in the directory provided.") + + Argument ("save_clusters", ""), + +//Consult the KML documentation for the following options. + + Option ("stages", "The number of stages the k-means clustering is run for.") + + Argument ("stages", "The number of stages the k-means clustering is run for.").type_integer (1, 1000, 20), + + Option ("max_accum_RDL","") + + Argument ("max_accum_RDL").type_float (0.0, 1.0, 0.1), + + Option ("min_accum_RDL","") + + Argument ("min_accum_RDL").type_float (0.0, 1.0, 0.1), + + Option ("max_run_stages","") + + Argument ("max_run_stages").type_integer (1, 100, 3), + + Option ("init_prob_acceptance","") + + Argument ("init_prob_acceptance").type_float (0.0, 1.0, 0.1), + + Option ("temp_run_length","") + + Argument ("temp_run_length").type_integer (1, 100, 10), + + Option ("temp_reduc_factor","") + + Argument ("temp_reduc_factor").type_float (0.0, 1.0, 0.95), + + Option ("num_points", "The number of points that will be generated along the strand location") + + Argument ("points").type_integer (1, 2000, 100), + + Option ("degree", "The degree of the Strand coefficients used to describe the strands") + + Argument ("degree").type_integer (1, 200, 3), + + +Option() }; + + +void printSummary( // print final summary + const KMlocal& theAlg, // the algorithm + const KMdata& dataPts, // the points + KMfilterCenters& ctrs); // the centers + +//void printPt( // print a point +// ostream& out, // output stream +// const KMpoint& p, +// size_t dim); // the point + + +EXECUTE { + + std::string input_location = argument[0]; + std::string output_location = argument[1]; + + + size_t new_num_strands = 20; + bool save_clusters = false; + std::string cluster_location = ""; + size_t num_stages = 100; + double max_accum_RDL = 0.1; + double min_accum_RDL = 0.1; + int max_run_stages = 3; + double init_prob_acceptance = 0.5; + int temp_run_length = 10; + double temp_reduc_factor = 0.95; + size_t degree = 0; + size_t num_points = 0; + + Options opt = get_options("new_num_strands"); + if (opt.size()) + new_num_strands = opt[0][0]; + + opt = get_options("cluster_location"); + if (opt.size()) { + save_clusters = true; + cluster_location = opt[0][0].c_str(); + } + + opt = get_options("num_stages"); + if (opt.size()) + num_stages = opt[0][0]; + + opt = get_options("max_accum_RDL"); + if (opt.size()) + max_accum_RDL = opt[0][0]; + + opt = get_options("min_accum_RDL"); + if (opt.size()) + min_accum_RDL = opt[0][0]; + + opt = get_options("max_run_stages"); + if (opt.size()) + max_run_stages = opt[0][0]; + + opt = get_options("init_prob_acceptance"); + if (opt.size()) + init_prob_acceptance = opt[0][0]; + + opt = get_options("temp_run_length"); + if (opt.size()) + temp_run_length = opt[0][0]; + + opt = get_options("temp_reduc_factor"); + if (opt.size()) + temp_reduc_factor = opt[0][0]; + + opt = get_options("num_points"); + if (opt.size()) + num_points = opt[0][0]; + + opt = get_options("degree"); + if (opt.size()) + degree = opt[0][0]; + + + Fibre::Strand::Set input_strands(input_location, degree); + + if (new_num_strands >= input_strands.size()) + throw Exception("New number of strands (" + str(new_num_strands) + ") must be less than the original number of strands (" + str(input_strands.size()) + ")"); + + + KMterm term(num_stages, 0, 0, 0, // run for 100 stages + min_accum_RDL, // min consec RDL + max_accum_RDL, // min accum RDL + max_run_stages, // max run stages + init_prob_acceptance, // init. prob. of acceptance + temp_run_length, // temp. run length + temp_reduc_factor); // temp. reduction factor + + + +//-------------------------// +// k-means cluster strands +//-------------------------// + + degree = input_strands[0].degree(); + + int ptDim = degree * 3; // dimension + + KMdata dataPts(ptDim, input_strands.size()); // allocate data storage + + for (size_t strand_i = 0; strand_i < input_strands.size(); strand_i++) { + for (size_t degree_i = 0; degree_i < input_strands[strand_i].degree(); degree_i++) { + dataPts[strand_i][degree_i * 3 + X] = input_strands[strand_i][degree_i][X]; + dataPts[strand_i][degree_i * 3 + Y] = input_strands[strand_i][degree_i][Y]; + dataPts[strand_i][degree_i * 3 + Z] = input_strands[strand_i][degree_i][Z]; + } + } + + + + dataPts.buildKcTree(); // build filtering structure + + KMfilterCenters ctrs(new_num_strands, dataPts); // allocate centers +// +// KMlocalLloyds kmLloyds(ctrs, term); // repeated Lloyd's +// ctrs = kmLloyds.execute(); // execute +// +// KMlocalSwap kmSwap(ctrs, term); // Swap heuristic +// ctrs = kmSwap.execute(); +// +// KMlocalEZ_Hybrid kmEZ_Hybrid(ctrs, term); // EZ-Hybrid heuristic +// ctrs = kmEZ_Hybrid.execute(); + + KMlocalHybrid kmHybrid(ctrs, term); // Hybrid heuristic + ctrs = kmHybrid.execute(); + +//--------------------------// +// Get cluster information +//--------------------------// + + + KMctrIdxArray closeCtr = new KMctrIdx[dataPts.getNPts()]; + double* sqDist = new double[dataPts.getNPts()]; + ctrs.getAssignments(closeCtr, sqDist); + + + + +//------------------------------// +// Print results of clustering +//------------------------------// + + for (int ctr_i = 0; ctr_i < ctrs.getK(); ctr_i++) { + + std::cout << "Centre: " << ctr_i << " ["; + + for (int pt_i = 0; pt_i < dataPts.getNPts(); pt_i++) { + if (closeCtr[pt_i] == ctr_i) + std::cout << pt_i << ","; + } + + std::cout << "] - ["; + + for (int pt_i = 0; pt_i < dataPts.getNPts(); pt_i++) { + if (closeCtr[pt_i] == ctr_i) + std::cout << setprecision(2) << sqDist[pt_i] << ","; + } + + std::cout << "]"; + + std::cout << std::endl; + } + + +//-----------------------------------// +// Save centre points as new strands +//-----------------------------------// + + Fibre::Strand::Set output_strands(input_strands.get_extend_props()); + + for (size_t ctr_i = 0; ctr_i < new_num_strands; ctr_i++) { + + Fibre::Strand strand(degree); + + for (size_t degree_i = 0; degree_i < input_strands[0].degree(); degree_i++) { + for (size_t dim_i = 0; dim_i < 3; dim_i++) + strand[degree_i][dim_i] = ctrs[ctr_i][degree_i * 3 + dim_i]; + } + + output_strands.push_back(strand); + + } + + output_strands.save(output_location, num_points); + + + +//----------------------------------------------// +// Save clusters in separate files if required +//----------------------------------------------// + + + if (save_clusters) { + + size_t num_cluster_dec_places = num_dec_places(new_num_strands); + + std::vector clusters; + + for (size_t ctr_i = 0; ctr_i < new_num_strands; ctr_i++) + clusters.push_back(Fibre::Strand::Set()); + + + for (size_t strand_i = 0; strand_i < input_strands.size(); strand_i++) + clusters[closeCtr[strand_i]].push_back(input_strands[strand_i]); + + + for (size_t ctr_i = 0; ctr_i < new_num_strands; ctr_i++) + clusters[ctr_i].save(File::join(cluster_location, "cluster_" + str(ctr_i, num_cluster_dec_places) + "." + Fibre::Strand::FILE_EXTENSION)); + + + } + + delete [] closeCtr; + delete [] sqDist; + + +} + + + + + + + +void printPt(ostream& out, const KMpoint& p, int dim) +{ + out << "(" << p[0]; + for (int i = 1; i < dim; i++) { + out << ", " << p[i]; + } + out << ")\n"; +} + +//------------------------------------------------------------------------ +// Print summary of execution +//------------------------------------------------------------------------ +void printSummary( + const KMlocal& theAlg, // the algorithm + const KMdata& dataPts, // the points + KMfilterCenters& ctrs) // the centers +{ + cout << "Number of stages: " << theAlg.getTotalStages() << "\n"; + cout << "Average distortion: " << + ctrs.getDist(false)/double(ctrs.getNPts()) << "\n"; + // print final center points + cout << "(Final Center Points:\n"; + ctrs.print(); + cout << ")\n"; + // get/print final cluster assignments + KMctrIdxArray closeCtr = new KMctrIdx[dataPts.getNPts()]; + double* sqDist = new double[dataPts.getNPts()]; + ctrs.getAssignments(closeCtr, sqDist); + + *kmOut << "(Cluster assignments:\n" + << " Point Center Squared Dist\n" + << " ----- ------ ------------\n"; + for (int i = 0; i < dataPts.getNPts(); i++) { + *kmOut << " " << setw(5) << i + << " " << setw(5) << closeCtr[i] + << " " << setw(10) << sqDist[i] + << "\n"; + } + *kmOut << ")\n"; + delete [] closeCtr; + delete [] sqDist; +} diff --git a/cmd/combine_fibres.cpp b/cmd/combine_fibres.cpp new file mode 100644 index 0000000..9ba6e59 --- /dev/null +++ b/cmd/combine_fibres.cpp @@ -0,0 +1,170 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Written by Thomas G. Close, 04/03/2009. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + +*/ + +#include "bts/cmd.h" + + +#include "bts/common.h" + + +#include "progressbar.h" + +#include "bts/fibre/strand/set.h" +#include "bts/fibre/track/set.h" +#include "bts/fibre/tractlet/set.h" + + + + +#include "bts/inline_functions.h" + +using namespace BTS; + +SET_VERSION_DEFAULT; +SET_AUTHOR ("Thomas G. Close"); +SET_COPYRIGHT (NULL); + +DESCRIPTION = { + "Merge multiple fibres files into one file.", + "", + NULL +}; + +ARGUMENTS = { + Argument ("input", "The input strands to be merged into the output file.").allow_multiple().type_file (), + Argument ("output", "The merged strands file in BTS format").type_file(), + Argument() +}; + + +OPTIONS = { + +Option() }; + + +template void combine_fibres(const std::vector& input_locations, const std::string& output_location, MR::ProgressBar& progress_bar); + +template void add_fibres(typename T::Writer& writer, const std::string& location, MR::ProgressBar& progress_bar); + + +EXECUTE { + + + std::vector input_locations; + + if (!argument.size()) + throw Exception ("No input_locations provided."); + + for (size_t arg_i = 0; arg_i < argument.size()-1; arg_i++) + input_locations.push_back(argument[arg_i]); + + std::string output_location = argument.back(); + + MR::ProgressBar progress_bar ("Combining fibres ..."); + + + + if (File::has_extension(output_location)) { + + combine_fibres(input_locations,output_location, progress_bar); + + } else if (File::has_extension(output_location)) { + + combine_fibres(input_locations,output_location, progress_bar); + + } else if (File::has_extension(output_location)) { + + combine_fibres(input_locations,output_location, progress_bar); + + } else if (File::has_extension(output_location)) { + + combine_fibres(input_locations,output_location, progress_bar); + + } else if (File::has_extension(output_location)) { + + combine_fibres(input_locations,output_location, progress_bar); + + } else if (File::has_extension(output_location)) { + + combine_fibres(input_locations,output_location, progress_bar); + + } else + throw Exception ("Unknown file extension in output file " + output_location + "."); + + + //MR::ProgressBar::done(); + +} + + +template void combine_fibres(const std::vector& input_locations, const std::string& output_location, MR::ProgressBar& progress_bar) { + + + std::map properties; + std::vector set_header, elem_header; + + typename T::Reader sneak_peek_reader(input_locations[0]); + + sneak_peek_reader.close(); + + typename T::Writer writer (output_location, sneak_peek_reader); + + for (typename std::vector::const_iterator input_it = input_locations.begin(); input_it != input_locations.end(); ++input_it) + add_fibres(writer, *input_it, progress_bar); + + +} + + +template void add_fibres (typename T::Writer& writer, const std::string& location, MR::ProgressBar& progress_bar) { + + + //If location is directory recursively enter and add all + if (File::is_dir(location)) { + + std::vector filenames = File::list_filenames(location, "", T::FILE_EXTENSION); + + for (size_t filename_i = 0; filename_i < filenames.size(); filename_i++) + add_fibres(writer, File::join(location,filenames[filename_i]), progress_bar); + + } else { + + if (!File::has_extension(location)) + throw Exception ("Incompatible file extension found at " + location + "."); + + std::map properties; + std::vector set_header, elem_header; + + typename T::Reader reader(location); + + T fibre; + std::map row; + + while (reader.next(fibre,row)) + writer.append(fibre,row); + + + progress_bar++; + + } + +} diff --git a/cmd/display_fibres.cpp b/cmd/display_fibres.cpp new file mode 100644 index 0000000..4ccebd3 --- /dev/null +++ b/cmd/display_fibres.cpp @@ -0,0 +1,238 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Written by Thomas G. Close, 04/03/2009. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + + +#include "bts/cmd.h" + +#include "bts/common.h" + + +#include "bts/fibre/strand/set.h" + + +#include "bts/fibre/strand/set.h" +#include "bts/fibre/track/set.h" +#include "bts/fibre/tractlet/set.h" +#include "bts/fibre/tractlet/section.h" +#include "bts/fibre/base/set_reader.h" +#include "bts/fibre/base/set_writer.h" + + +#include "bts/inline_functions.h" + +using namespace BTS; + +SET_VERSION_DEFAULT; +SET_AUTHOR ("Thomas G. Close"); +SET_COPYRIGHT (NULL); + +DESCRIPTION = { + "Print strands to screen", + "", + NULL +}; + +ARGUMENTS = { + Argument ("input", "The strands to be displayed.").allow_multiple().type_file (), + Argument() +}; + + +OPTIONS = { + +Option() }; + + + +EXECUTE { + + + for (size_t arg_i = 0; arg_i < argument.size(); ++arg_i) { + + std::string input_location = argument[arg_i]; + + if (input_location.at(input_location.length()-1) == 'x') + continue; + + if (File::has_extension(input_location)) { + + Fibre::Strand::Set s_set(input_location); + + std::cout << "\n\n\n**************************************\n"; + std::cout << "Strands at: '" << input_location << "'.\n"; + std::cout << "**************************************\n" << std::endl; + + std::cout << s_set; + + } else if (File::has_extension(input_location)) { + + Fibre::Track::Set k_set(input_location); + + std::cout << "\n\n\n**************************************\n"; + std::cout << "Tracks at: '" << input_location << "'.\n"; + std::cout << "**************************************\n" << std::endl; + + std::cout << k_set; + + } else if (File::has_extension(input_location)) { + + Fibre::Tractlet::Set t_set(input_location); + + std::cout << "\n\n\n**************************************\n"; + std::cout << "Tractlets at: '" << input_location << "'.\n"; + std::cout << "**************************************\n" << std::endl; + + std::cout << t_set; + + } else if (File::has_extension(input_location)) { + + Fibre::Strand::Set::Reader reader(input_location); + + Fibre::Strand::Set s_set; + + std::cout << "\n\n\n**************************************\n"; + std::cout << "Strand Sets at: '" << input_location << "'.\n"; + std::cout << "**************************************\n" << std::endl; + + + size_t count = 0; + + while (reader.next(s_set)) { + + std::cout << "**** STRAND SET " << str(count++) << " ***" << std::endl; + + std::map extend_props = s_set.get_extend_props(); + + for (std::map::iterator prop_it = extend_props.begin(); prop_it != extend_props.end(); ++prop_it) + std::cout << prop_it->first << ": " << prop_it->second << ", "; + + std::cout << std::endl << std::endl; + + + std::cout << std::endl << s_set << std::endl << std::endl; + + } + + } else if (File::has_extension(input_location)) { + + Fibre::Tractlet::Set::Reader reader(input_location); + + Fibre::Tractlet::Set t_set; + + std::cout << "\n\n\n**************************************\n"; + std::cout << "Tractlet Sets at: '" << input_location << "'.\n"; + std::cout << "**************************************\n" << std::endl; + + size_t count = 0; + + std::map prop_row; + + while (reader.next(t_set)) { + + std::cout << "**** TRACTLET SET " << str(count++) << " ***" << std::endl; + + std::cout << std::endl << std::endl; + + std::map extend_props = t_set.get_extend_props(); + + for (std::map::iterator prop_it = extend_props.begin(); prop_it != extend_props.end(); ++prop_it) + std::cout << prop_it->first << ": " << prop_it->second << ", "; + + std::cout << std::endl << std::endl; + + std::cout << t_set << std::endl << std::endl; + + } + + } else if (File::has_extension(input_location)) { + + Fibre::Track::Set::Reader reader(input_location); + + Fibre::Track::Set k_set; + + std::cout << "\n\n\n**************************************\n"; + std::cout << "Track Sets at: '" << input_location << "'.\n"; + std::cout << "**************************************\n" << std::endl; + + size_t count = 0; + + std::map prop_row; + + while (reader.next(k_set)) { + + std::cout << "**** TRACK SET " << str(count++) << " ***" << std::endl; + + std::cout << std::endl << std::endl; + + std::map extend_props = k_set.get_extend_props(); + + for (std::map::iterator prop_it = extend_props.begin(); prop_it != extend_props.end(); ++prop_it) + std::cout << prop_it->first << ": " << prop_it->second << ", "; + + std::cout << std::endl << std::endl; + + std::cout << k_set << std::endl << std::endl; + + } + + } else if (File::has_extension(input_location)) { + + Fibre::Strand::Section::Reader reader(input_location); + + Fibre::Strand::Section sec; + + std::cout << "\n\n\n**************************************\n"; + std::cout << "Strand Sections at: '" << input_location << "'.\n"; + std::cout << "**************************************\n" << std::endl; + + while (reader.next(sec)) { + + std::cout << sec << std::endl; + + } + + } else if (File::has_extension(input_location)) { + + Fibre::Tractlet::Section::Reader reader(input_location); + + Fibre::Tractlet::Section sec; + + std::cout << "\n\n\n**************************************\n"; + std::cout << "Tractlet Sections at: '" << input_location << "'.\n"; + std::cout << "**************************************\n" << std::endl; + + while (reader.next(sec)) { + + std::cout << sec << std::endl; + + } + + } else { + if (argument.size() == 1) + throw Exception ("Unrecognised file extension, \"" + File::extension(input_location) + "\", for input file " + input_location + "."); + else + std::cout << "Skipped '" << input_location << "'." << std::endl; + } + } + + +} diff --git a/cmd/dummy.cpp b/cmd/dummy.cpp new file mode 100644 index 0000000..3a49594 --- /dev/null +++ b/cmd/dummy.cpp @@ -0,0 +1,84 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Written by Thomas G. Close, 04/03/2009. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + + +#include "bts/cmd.h" + +#include "bts/common.h" + + +#include "bts/fibre/strand/set.h" + + +#include "bts/fibre/strand/set.h" +#include "bts/fibre/track/set.h" +#include "bts/fibre/tractlet/set.h" +#include "bts/fibre/tractlet/section.h" +#include "bts/fibre/base/set_reader.h" +#include "bts/fibre/base/set_writer.h" + + +#include "bts/inline_functions.h" + +using namespace BTS; + +SET_VERSION_DEFAULT; +SET_AUTHOR ("Thomas G. Close"); +SET_COPYRIGHT (NULL); + +DESCRIPTION = { + "Print strands to screen", + "", + NULL +}; + +ARGUMENTS = { + Argument() +}; + + +OPTIONS = { + +Option() }; + + + +EXECUTE { + + Fibre::Tractlet t(3); + + t(0,0) = Coord(0,0,0); + t(0,1) = Coord(.25,0,0); + t(0,2) = Coord(0,0,0); + t(1,0) = Coord(0,0.1,0); + t(1,1) = Coord(0,0,0); + t(1,2) = Coord(0,0,0); + t(2,0) = Coord(0,0,0.1); + t(2,1) = Coord(0,0,0); + t(2,2) = Coord(0,0,0); + + std::vector areas = t.cross_sectional_areas(100); + + for (size_t i = 0; i < areas.size(); ++i) + std::cout << areas[i] << std::endl; + +} diff --git a/cmd/echo_parameters.cpp b/cmd/echo_parameters.cpp new file mode 100644 index 0000000..6938a8e --- /dev/null +++ b/cmd/echo_parameters.cpp @@ -0,0 +1,1278 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, Jul 6, 2010. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ +/* + +#include "bts/cmd.h" + +#include "bts/common.h" +#include "bts/fibre/tractlet/set.h" +#include "bts/fibre/strand/set.h" +#include "bts/image/observed/buffer.h" + +#include "bts/mcmc/riemannian.h" +#include "bts/mcmc/hamiltonian.h" +#include "bts/mcmc/metropolis.h" +#include "bts/analysis/scan.h" +#include "bts/analysis/gradient_tester.h" +#include "bts/image/expected/buffer.h" + +#include "bts/prob/likelihood.h" + +#include "bts/prob/prior.h" + + + + + +#include "bts/mcmc/proposal/momentum.h" +#include "bts/mcmc/proposal/distribution.h" +#include "bts/mcmc/proposal/distribution/gaussian.h" + +#include "bts/fibre/tractlet/set/momentum.h" +#include "bts/fibre/strand/set/momentum.h" +#include "bts/fibre/strand/set/walker.h" + +#include "bts/fibre/tractlet/set/walker.h" + + +#include "image/header.h" +#include "bts/image/observed/buffer.h" + + +#include "bts/inline_functions.h" + + +using namespace BTS; + + +void check_parameter(std::map& echo_options, + const std::string& key, + const std::string& default_value); + +void check_parameters_group ( std::map& echo_options, + const std::string& name, + std::vector< std::pair > key_default_value_pairs, + bool default_active); + + +template void load_and_check_parameters(std::map& echo_options, + const std::string& key, + const std::string& default_value_location = ""); + +void load_and_check_state_parameters ( std::map& echo_options, + const std::string& key, + const std::vector& default_value_locations = std::vector(3)); + +bool is_riemannian(const std::string& method) + { return method == "riemannian"; } + +bool is_hamiltonian(const std::string& method) + { return method == "hamiltonian"; } + +bool is_metropolis(const std::string& method) + { return method == "metropolis"; } + +bool is_scan(const std::string& method) + { return method == "scan" || method == "scan_batch"; } + +bool is_gradient_test(const std::string& method) + { return method == "test_gradient"; } + +bool is_mcmc(const std::string& method) + { return is_metropolis(method) || is_hamiltonian(method) || is_riemannian(method); } + +bool is_analysis(const std::string& method) + { return is_scan(method) || is_gradient_test(method); } + + + +SET_VERSION_DEFAULT; +SET_AUTHOR ("Thomas G. Close"); +SET_COPYRIGHT (NULL); + +DESCRIPTION = { + "Echo Parameters", + "Determine which parameters in a previous run need to be set to exactly copy the run", + NULL +}; + +ARGUMENTS = { + Argument ("template_location", "Template location", "Location of template file, from which to copy the parameters.").type_file (), + + Argument() +}; + + +OPTIONS = { + + Option ("method", "The output method", "The output method to print if not the original method.") + + Argument ("method", ""), + + Option ("output_location", "Output location", "Override the location of the output.") + + Argument ("output_location", ""), + + Option ("state_location", "New state location", "Override the location of the state.") + + Argument ("state_location", ""), + + Option ("seed_copy", "Copy seed", "Also copy the seed."), + + Option ("last_place_output", "Put the output location last", "Put the output location last for easy access to change the name."), + + Option ("origin_location", "New origin location", "Override the location of the origin.") + + Argument ("origin_location", ""), + + Option ("axis1_location", "Axis 1 location", "Pass the location for axis1 for use in mcmc -> scan echo's.") + + Argument ("axis1_location", ""), + + Option ("axis2_location", "Axis 2 location", "Pass the location for axis2 for use in mcmc -> scan echo's.") + + Argument ("axis2_location", ""), + + Option ("axis3_location", "Axis 3 location", "Pass the location for axis3 for use in mcmc -> scan echo's.") + + Argument ("axis3_location", ""), +Option() }; + + +EXECUTE { + + + std::vector echo_arguments; + std::map echo_options; + + + + + + +//------------------------------// +// Load the template echo_options. // +//------------------------------// + + std::string template_location = argument[0]; + + + if (File::has_extension(template_location)) { + + Fibre::Strand::Set::Reader reader(template_location); + + echo_options = reader.get_extend_props(); + + } else if (File::has_extension(template_location)) { + + Fibre::Tractlet::Set::Reader reader(template_location); + + echo_options = reader.get_extend_props(); + + } else if (File::has_extension(template_location)) { + + MR::Image::Header header; + + header.open(template_location); + + echo_options = header; + + } else + throw Exception ("Unrecognised extension '" + File::extension(template_location) + "'."); + + + + + //-----------------------// + // Legacy conversions. // + //-----------------------// + + if (echo_options.count("origin_state")) { + echo_options["origin"] = echo_options["origin_state"]; + echo_options.erase("origin_state"); + } + + if (echo_options.count("momen_rand_scales")) + echo_options.erase("momen_rand_scales"); + + if (echo_options.count("momen_step_sizes")) { + echo_options["momen_step"] = echo_options["momen_step_sizes"]; + echo_options.erase("momen_step_sizes"); + } + + + if (echo_options.count("leapfrog")) { + echo_options["momen_step"] = echo_options["leapfrog"]; + echo_options.erase("leapfrog"); + } + + echo_options.erase("momen_over_rand_scale"); + echo_options.erase("momen_rand_scales_location"); + echo_options.erase("momen_over_randomize"); + echo_options.erase("momen_randomize_location"); + echo_options.erase("momen_randomize"); + + if (echo_options.count("momen_over_step_size")) { + echo_options["momen_step_scale"] = echo_options["momen_over_step_size"]; + echo_options.erase("momen_over_step_size"); + } + + + if (echo_options.count("momen_step_sizes_location")) { + echo_options["momen_step_location"] = echo_options["momen_step_sizes_location"]; + echo_options.erase("momen_step_sizes_location"); + } + + + if (echo_options.count("leapfrog_scale")) { + echo_options["momen_step_scale"] = echo_options["leapfrog_scale"]; + echo_options.erase("leapfrog_scale"); + } + + + if (echo_options.count("leapfrog_location")) { + echo_options["momen_step_location"] = echo_options["leapfrog_location"]; + echo_options.erase("leapfrog_location"); + } + + + if (echo_options.count("reference_image")) { + echo_options["obs_image"] = echo_options["reference_image"]; + echo_options.erase("reference_image"); + } + + if (echo_options.count("ref_image")) { + echo_options["obs_image"] = echo_options["ref_image"]; + echo_options.erase("ref_image"); + } + +//---------------------------------------// +// Set the template and output method. // +//---------------------------------------// + + std::string loaded_method; + loaded_method = echo_options["method"]; + + + //Check for legacy names for methods. + if (loaded_method == "Hamiltonian") + loaded_method = "hamiltonian"; + + else if (loaded_method == "Metropolis Hastings") + loaded_method = "metropolis"; + + else if (loaded_method == "Scan") + loaded_method = "scan"; + + else if (loaded_method == "Container Test") + loaded_method = "test_gradient"; + + + std::string method = loaded_method; + + //Get the method. + Options opt = get_options("method"); + if (opt.size()) + method = opt[0][0]; + + + echo_options.erase("method"); + + + +//----------------------------// +// Get the Output location. // +//----------------------------// + + std::string output_location; + + //If it is the same method, default to overide previous file. + if (loaded_method == method) + output_location = template_location; + else + output_location = "__output_location_place_holder__"; + + opt = get_options("output_location"); + if (opt.size()) + output_location = opt[0][0]; + + + +//------------------------------------// +// Get the Observed Image location. // +//------------------------------------// + + std::string obs_image_location; + std::string origin_location; + + if (echo_options.count("obs_image")) { + obs_image_location = echo_options["obs_image"]; + echo_options.erase("obs_image"); + + } else + obs_image_location = "__obs_image_place_holder__"; + + + //Load the observed image to check the auto generated parameters. + Image::Observed::Buffer obs_image; + + if (obs_image_location != "__obs_image_place_holder__") { + + try { + + obs_image.load(obs_image_location); + origin_location = obs_image.properties()["state_location"]; + + } catch(...) { + + std::cout << "Warning!! Could not load image from observed image location." << std::endl; + + } + + } + + +//---------------------------// +// Get the state location. // +//---------------------------// + + std::string state_location, state_key; + bool overide_state_location = false; + + if (is_mcmc(loaded_method)) + state_key = "initial_state"; + else if (is_scan(loaded_method)) + state_key = "origin"; + + opt = get_options("overide_state_location"); + if (opt.size()) { + state_location = opt[0][0]; + overide_state_location = true; + echo_options.erase(state_key); + echo_options.erase(state_key + "_location"); + } else { + + state_location = echo_options[state_key + "_location"]; + + if (File::has_extension(state_location)) + load_and_check_parameters(echo_options, state_key); + else if (File::has_extension(state_location)) + load_and_check_parameters(echo_options, state_key); + + } + + +//------------------------------------// +// Set the random seed if required. // +//------------------------------------// + + bool seed_copy = false; + opt = get_options("seed_copy"); + if (opt.size()) + seed_copy = true; + + + if (echo_options.count("random_seed")) { + echo_options["seed"] = echo_options["random_seed"]; + echo_options.erase("random_seed"); + } + + if (seed_copy) { + + if (!echo_options.count("seed")) + echo_options["seed"] = "__seed_place_holder__"; + + } else + echo_options.erase("seed"); + + +//----------------------------------------------// +// Get the remaining options for this program // +//----------------------------------------------// + + bool set_output_last = 0; + std::string axis1_location; + std::string axis2_location; + std::string axis3_location; + + opt = get_options("last_place_output"); + if (opt.size()) + set_output_last = 1; + + opt = get_options("origin_location"); + if (opt.size()) + origin_location = opt[0][0]; + + opt = get_options("axis1_location"); + if (opt.size()) + axis1_location = opt[0][0]; + + opt = get_options("axis2_location"); + if (opt.size()) + axis2_location = opt[0][0]; + + opt = get_options("axis3_location"); + if (opt.size()) + axis3_location = opt[0][0]; +//-----------------------------------// +// Erase non-parameter properties. // +//-----------------------------------// + + echo_options.erase("datetime"); + echo_options.erase("count"); + echo_options.erase("total_count"); + echo_options.erase("method"); + echo_options.erase("software version"); + + +//-----------------------------------// +// Check base density parameter. // +//-----------------------------------// + + if (obs_image_location != "__obs_image_place_holder__" && state_location != "") { + + MR::Math::Matrix diff_encodings; + Image::Expected::Buffer::Buffer* exp_image; + MR::Math::Vector diff_response_SH; + bool can_check_base_intensity = true; + + + bool load_encodings = false; + + if (echo_options.count("diff_encodings")) + load_encodings = echo_options["diff_encodings"] == "from observed image" || echo_options["diff_encodings"] == "from reference image"; + else if (echo_options.count("diff_encodings_location")) + load_encodings = echo_options["diff_encodings_location"] == "from observed image" || echo_options["diff_encodings_location"] == "from reference image"; + + if (load_encodings) { + + try { + + MR::Image::Header header; + + header.open(obs_image_location); + + //If gradient scheme is included in reference image header, use that instead of default (NB: Will override any gradients passed to '-diff_encodings' option). + diff_encodings = header.get_DW_scheme(); + + } catch(...) { + + std::cout << "Warning!! Could not load image from observed image location." << std::endl; + + } + + } else if (echo_options.count("diff_encodings_location")) { + + diff_encodings.load(echo_options["diff_encodings_location"]); + + } else + can_check_base_intensity = false; + + + Diffusion::Model diffusion_model; + bool diff_isotropic = false; + + if (echo_options.count("diff_isotropic")) + diff_isotropic = to(echo_options["diff_isotropic"]); + + if (echo_options.count("diff_response_SH_location")) { + + try { + + diff_response_SH.load(echo_options["diff_response_SH_location"]); + + diffusion_model = Diffusion::Model (diff_encodings, diff_response_SH, diff_isotropic); + + } catch (Exception e) { + + std::cout << "WARNING!! Could not load diffusion responses from location '" << echo_options["diff_response_SH_location"] << "'." << std::endl; + can_check_base_intensity = false; + } + + } else if (echo_options.count("diff_adc") && echo_options.count("diff_fa") && echo_options.count("diff_b_value")) { + + diffusion_model = Diffusion::Model (diff_encodings, + to(echo_options["diff_adc"]), + to(echo_options["diff_fa"]), + diff_isotropic); + + } else + can_check_base_intensity = false; + + + if (can_check_base_intensity && state_location.size()) { + + + exp_image = Image::Expected::Buffer::Buffer::factory( echo_options["exp_type"], + obs_image, + diffusion_model, + to(echo_options["exp_num_length_sections"]), + to(echo_options["exp_num_width_sections"]), + to(echo_options["exp_interp_extent"]), + to(echo_options["exp_enforce_bounds"]), + to(echo_options["exp_half_width"])); + + double calc_exp_base_intensity = exp_image->base_intensity_default(obs_image, state_location); + + check_parameter(echo_options, "exp_base_intensity", str(calc_exp_base_intensity)); + + } + + } + +//-----------------------------// +// Check general parameters. // +//-----------------------------// + + //General image parameters. + check_parameter(echo_options, "img_dims", str(Image::Expected::Buffer::DIMS_DEFAULT)); + check_parameter(echo_options, "img_vox_lengths", str(Image::Expected::Buffer::VOX_LENGTHS_DEFAULT)); + check_parameter(echo_options, "img_offsets", str(- obs_image.vox_lengths() * obs_image.dims() * 0.5)); + + //Diffusion response parameters. + check_parameter(echo_options, "diff_encodings_location", "from observed image"); + check_parameter(echo_options, "diff_encodings_location", "from reference image"); + check_parameter(echo_options, "diff_isotropic", str(Diffusion::Model::ISOTROPIC_DEFAULT)); + + + if (echo_options.count("diff_response_SH_location")) + load_and_check_parameters< MR::Math::Vector >(echo_options, "diff_response_SH", ""); + else { + check_parameter(echo_options, "diff_adc", str(Diffusion::Model::ADC_DEFAULT)); + check_parameter(echo_options, "diff_fa", str(Diffusion::Model::FA_DEFAULT)); + } + + //Expected image parameters. + check_parameter(echo_options, "exp_num_length_sections", str(Image::Expected::Buffer::NUM_LENGTH_SECTIONS_DEFAULT)); + check_parameter(echo_options, "exp_num_width_sections", str(Image::Expected::Buffer::NUM_WIDTH_SECTIONS_DEFAULT)); + check_parameter(echo_options, "exp_type", str(Image::Expected::Buffer::TYPE_DEFAULT)); + check_parameter(echo_options, "exp_interp_extent", str(Image::Expected::Buffer::INTERP_EXTENT_DEFAULT)); + check_parameter(echo_options, "exp_enforce_bounds", str(Image::Expected::Buffer::ENFORCE_BOUNDS_DEFAULT)); + check_parameter(echo_options, "exp_half_width", str(Image::Expected::Buffer::HALF_WIDTH_DEFAULT)); + + + + //Legacy conversion. + if (echo_options["like_type"] == "strong") + echo_options["like_type"] = "gaussian"; + + //Likelihood parameters. + check_parameter(echo_options, "like_snr", str(Prob::Likelihood::SNR_DEFAULT)); + check_parameter(echo_options, "like_type", str(Prob::Likelihood::TYPE_DEFAULT)); + check_parameter(echo_options, "like_b0_include", str(Prob::Likelihood::B0_INCLUDE_DEFAULT)); + check_parameter(echo_options, "like_outside_scale", str(Prob::Likelihood::OUTSIDE_SCALE_DEFAULT)); + + //Proposal parameters. + if (File::has_extension(state_location)) { + check_parameter(echo_options, "walk_type", str(Fibre::Strand::Set::Walker::TYPE_DEFAULT)); + check_parameter(echo_options, "walk_scale", str(Fibre::Strand::Set::Walker::STEP_SCALE_DEFAULT)); + check_parameter(echo_options, "walk_intens_scale", str(Fibre::Strand::Walker::Constrained::INTENSITY_SCALE_DEFAULT)); + check_parameter(echo_options, "walk_base_intens_scale", str(Fibre::Strand::Set::Walker::Constrained::BASE_INTENSITY_SCALE_DEFAULT)); + } else if (File::has_extension(state_location)) { + check_parameter(echo_options, "walk_type", str(Fibre::Tractlet::Set::Walker::TYPE_DEFAULT)); + check_parameter(echo_options, "walk_scale", str(Fibre::Tractlet::Set::Walker::STEP_SCALE_DEFAULT)); + check_parameter(echo_options, "walk_intens_scale", str(Fibre::Tractlet::Walker::Constrained::INTENSITY_SCALE_DEFAULT)); + check_parameter(echo_options, "walk_base_intens_scale", str(Fibre::Tractlet::Set::Walker::Constrained::BASE_INTENSITY_SCALE_DEFAULT)); + } + + check_parameter(echo_options, "walk_midpoint_scale", str(Fibre::Strand::Walker::Constrained::MIDPOINT_SCALE_DEFAULT)); + check_parameter(echo_options, "walk_endpoint_scale", str(Fibre::Strand::Walker::Constrained::ENDPOINT_SCALE_DEFAULT)); + check_parameter(echo_options, "walk_sheer_scale", str(Fibre::Tractlet::Walker::Constrained::SHEER_SCALE_DEFAULT)); + check_parameter(echo_options, "walk_basewidth_scale", str(Fibre::Tractlet::Walker::Constrained::BASEWIDTH_SCALE_DEFAULT)); + check_parameter(echo_options, "prop_distr_type", str(MCMC::Proposal::Distribution::TYPE_DEFAULT)); + check_parameter(echo_options, "walk_sphere_radius", str(Fibre::Strand::Walker::Constrained::radius_default(obs_image))); + + + std::vector walk_step_sizes_defaults; + walk_step_sizes_defaults.push_back(str(Fibre::Strand::Set::Walker::STEP_LOCATION_DEFAULT)); + walk_step_sizes_defaults.push_back(str(Fibre::Tractlet::Set::Walker::STEP_LOCATION_DEFAULT)); + walk_step_sizes_defaults.push_back(""); + + load_and_check_state_parameters(echo_options, "walk_step", walk_step_sizes_defaults); + + std::vector momen_step_sizes_defaults; + momen_step_sizes_defaults.push_back(str(Fibre::Strand::Set::Momentum::STEP_LOCATION_DEFAULT)); + momen_step_sizes_defaults.push_back(str(Fibre::Tractlet::Set::Momentum::STEP_LOCATION_DEFAULT)); + momen_step_sizes_defaults.push_back(""); + + load_and_check_state_parameters(echo_options, "momen_step", momen_step_sizes_defaults); + + //Prior parameters. + check_parameter(echo_options, "prior_scale", str(Prob::Prior::SCALE_DEFAULT)); + check_parameter(echo_options, "prior_only", str(0)); + + + //-----------------------------------// + // Check general group parameters. // + //-----------------------------------// + + if (echo_options.count("prior_curv_scale")) { + + std::vector< std::pair > key_values; + + key_values.push_back(std::pair ("prior_curv_scale", str(Prob::Prior::Magnitude::SCALE_DEFAULT))); + + check_parameters_group(echo_options, "prior_curv", key_values, Prob::Prior::Magnitude::ACTIVE_DEFAULT); + + + } else if (Prob::Prior::Magnitude::ACTIVE_DEFAULT == Active) + echo_options["prior_curv"] = "0"; + + + if (echo_options.count("prior_sheer_scale")) { + + std::vector< std::pair > key_values; + + key_values.push_back(std::pair ("prior_sheer_scale", str(Prob::Prior::Sheer::SCALE_DEFAULT))); + + check_parameters_group(echo_options, "prior_sheer", key_values, Prob::Prior::Sheer::ACTIVE_DEFAULT); + + + } else if (Prob::Prior::Sheer::ACTIVE_DEFAULT == Active) + echo_options["prior_sheer"] = "0 1"; + + + if (echo_options.count("prior_end_in_sphere_scale")) { + + std::vector< std::pair > key_values; + + key_values.push_back(std::pair ("prior_end_in_sphere_scale", str(Prob::Prior::EndInSphere::SCALE_DEFAULT))); + key_values.push_back(std::pair ("prior_end_in_sphere_radius", str(Prob::Prior::EndInSphere::radius_default(obs_image)))); + + + check_parameters_group(echo_options, "prior_end_in_sphere", key_values, Prob::Prior::EndInSphere::ACTIVE_DEFAULT); + + + } else if (Prob::Prior::EndInSphere::ACTIVE_DEFAULT == Active) + echo_options["prior_end_in_sphere"] = "0 1"; + + + if (echo_options.count("prior_end_out_sphere_scale")) { + + std::vector< std::pair > key_values; + + key_values.push_back(std::pair ("prior_end_out_sphere_scale", str(Prob::Prior::EndOutSphere::SCALE_DEFAULT))); + key_values.push_back(std::pair ("prior_end_out_sphere_sd", str(Prob::Prior::EndOutSphere::STD_DEV_DEFAULT))); + key_values.push_back(std::pair ("prior_end_out_sphere_radius", str(Prob::Prior::EndOutSphere::radius_default(obs_image)))); + + + check_parameters_group(echo_options, "prior_end_out_sphere", key_values, Prob::Prior::EndOutSphere::ACTIVE_DEFAULT); + + + } else if (Prob::Prior::EndOutSphere::ACTIVE_DEFAULT == Active) + echo_options["prior_end_out_sphere"] = "0 1"; + + if (echo_options.count("prior_end_on_sphere_scale")) { + + std::vector< std::pair > key_values; + + key_values.push_back(std::pair ("prior_end_on_sphere_scale", str(Prob::Prior::EndOnSphere::SCALE_DEFAULT))); + key_values.push_back(std::pair ("prior_end_on_sphere_radius", str(Prob::Prior::EndOnSphere::radius_default(obs_image)))); + + + check_parameters_group(echo_options, "prior_end_on_sphere", key_values, Prob::Prior::EndOnSphere::ACTIVE_DEFAULT); + + + } else if (Prob::Prior::EndOnSphere::ACTIVE_DEFAULT == Active) + echo_options["prior_end_on_sphere"] = "0 1"; + + + if (echo_options.count("prior_mid_sphere_scale")) { + + std::vector< std::pair > key_values; + + key_values.push_back(std::pair ("prior_mid_sphere_scale", str(Prob::Prior::MidpointInSphere::SCALE_DEFAULT))); + key_values.push_back(std::pair ("prior_mid_sphere_sd", str(Prob::Prior::MidpointInSphere::STD_DEV_DEFAULT))); + key_values.push_back(std::pair ("prior_mid_sphere_radius", str(Prob::Prior::MidpointInSphere::radius_default(obs_image)))); + + + check_parameters_group(echo_options, "prior_mid_sphere", key_values, Prob::Prior::MidpointInSphere::ACTIVE_DEFAULT); + + + } else if (Prob::Prior::MidpointInSphere::ACTIVE_DEFAULT == Active) + echo_options["prior_mid_sphere"] = "0 1"; + + if (echo_options.count("prior_hook_scale")) { + + std::vector< std::pair > key_values; + + key_values.push_back(std::pair ("prior_hook_scale", str(Prob::Prior::Hook::SCALE_DEFAULT))); + key_values.push_back(std::pair ("prior_mid_cube_sd", str(Prob::Prior::Hook::STD_DEV_DEFAULT))); + key_values.push_back(std::pair ("prior_hook_num_points", str(Prob::Prior::Hook::side_length_default(obs_image)))); + + + check_parameters_group(echo_options, "prior_mid_cube", key_values, Prob::Prior::Hook::ACTIVE_DEFAULT); + + + } else if (Prob::Prior::Hook::ACTIVE_DEFAULT == Active) + echo_options["prior_mid_cube"] = "0 1"; + + + if (echo_options.count("prior_all_scale")) { + + std::vector< std::pair > key_values; + + key_values.push_back(std::pair ("prior_all_scale", str(Prob::Prior::AllInCube::SCALE_DEFAULT))); + key_values.push_back(std::pair ("prior_all_sd", str(Prob::Prior::AllInCube::STD_DEV_DEFAULT))); + key_values.push_back(std::pair ("prior_all_num_length_sections", str(Prob::Prior::AllInCube::NUM_LENGTH_SECTIONS_DEFAULT))); + key_values.push_back(std::pair ("prior_all_num_width_sections", str(Prob::Prior::AllInCube::NUM_WIDTH_SECTIONS_DEFAULT))); + + check_parameters_group(echo_options, "prior_all", key_values, Prob::Prior::Hook::ACTIVE_DEFAULT); + + + } else if (Prob::Prior::Hook::ACTIVE_DEFAULT == Active) + echo_options["prior_all"] = "0 1"; + + + if (echo_options.count("prior_tract_sheer_scale")) { + + std::vector< std::pair > key_values; + + key_values.push_back(std::pair ("prior_tract_sheer_scale", str(Prob::Prior::Sheer::SCALE_DEFAULT))); + + check_parameters_group(echo_options, "prior_tract_sheer", key_values, Prob::Prior::Sheer::ACTIVE_DEFAULT); + + + } else if (Prob::Prior::Sheer::ACTIVE_DEFAULT == Active) + echo_options["prior_tract_sheer"] = "0 1"; + + + if (echo_options.count("prior_prior_tract_mag_scale")) { + + std::vector< std::pair > key_values; + + key_values.push_back(std::pair ("prior_prior_tract_mag_scale", str(Prob::Prior::Magnitude::SCALE_DEFAULT))); + + check_parameters_group(echo_options, "prior_prior_tract_mag", key_values, Prob::Prior::Magnitude::ACTIVE_DEFAULT); + + + } else if (Prob::Prior::Magnitude::ACTIVE_DEFAULT == Active) + echo_options["prior_prior_tract_mag"] = "0 1"; + + + if (echo_options.count("prior_tract_avg_width_scale")) { + + std::vector< std::pair > key_values; + + key_values.push_back(std::pair ("prior_tract_avg_width_scale", str(Prob::Prior::BaseWidth::SCALE_DEFAULT))); + key_values.push_back(std::pair ("prior_tract_avg_width_sd", str(Prob::Prior::BaseWidth::STD_DEV_DEFAULT))); + key_values.push_back(std::pair ("prior_tract_avg_width_mean", str(Prob::Prior::BaseWidth::MEAN_DEFAULT))); + + check_parameters_group(echo_options, "prior_tract_basewidth", key_values, Prob::Prior::BaseWidth::ACTIVE_DEFAULT); + + + } else if (Prob::Prior::BaseWidth::ACTIVE_DEFAULT == Active) + echo_options["prior_tract_basewidth"] = "0 1"; + + + if (echo_options.count("prior_intens_gauss_scale")) { + + std::vector< std::pair > key_values; + + key_values.push_back(std::pair ("prior_intens_gauss_scale", str(Prob::Prior::GaussDensity::SCALE_DEFAULT))); + key_values.push_back(std::pair ("prior_intens_gauss_mean", str(Prob::Prior::GaussDensity::MEAN_DEFAULT))); + + check_parameters_group(echo_options, "prior_intens_gauss", key_values, Prob::Prior::GaussDensity::ACTIVE_DEFAULT); + + + } else if (Prob::Prior::GaussDensity::ACTIVE_DEFAULT == Active) + echo_options["prior_intens_gauss"] = "0 1"; + + + if (echo_options.count("prior_b_intens_gauss_scale")) { + + std::vector< std::pair > key_values; + + key_values.push_back(std::pair ("prior_b_intens_gauss_scale", str(Prob::Prior::BaseIntensity::SCALE_DEFAULT))); + key_values.push_back(std::pair ("prior_b_intens_gauss_sd_frac", str(Prob::Prior::BaseIntensity::STD_DEV_FRACTION_DEFAULT))); + + check_parameters_group(echo_options, "prior_b_intens_gauss", key_values, Prob::Prior::BaseIntensity::ACTIVE_DEFAULT); + + + } else if (Prob::Prior::BaseIntensity::ACTIVE_DEFAULT == Active) + echo_options["prior_b_intens_gauss"] = "0 1"; + + + if (echo_options.count("prior_intens_flattop_scale")) { + + std::vector< std::pair > key_values; + + key_values.push_back(std::pair ("prior_b_intens_flattop_scale", str(Prob::Prior::BaseIntensity::FlatTopQuadratic::SCALE_DEFAULT))); + key_values.push_back(std::pair ("prior_b_intens_flattop_sd", str(Prob::Prior::BaseIntensity::FlatTopQuadratic::STD_DEV_DEFAULT))); + key_values.push_back(std::pair ("prior_b_intens_flattop_low", str(Prob::Prior::BaseIntensity::FlatTopQuadratic::LOW_DEFAULT))); + key_values.push_back(std::pair ("prior_b_intens_flattop_high", str(Prob::Prior::BaseIntensity::FlatTopQuadratic::HIGH_DEFAULT))); + + check_parameters_group(echo_options, "prior_intens_flattop", key_values, Prob::Prior::BaseIntensity::FlatTopQuadratic::ACTIVE_DEFAULT); + + + } else if (Prob::Prior::BaseIntensity::FlatTopQuadratic::ACTIVE_DEFAULT == Active) + echo_options["prior_intens_flattop"] = "0 1"; + + + if (echo_options.count("prior_intens_log_scale")) { + + std::vector< std::pair > key_values; + + key_values.push_back(std::pair ("prior_b_intens_log_scale", str(Prob::Prior::BaseIntensity::Log::SCALE_DEFAULT))); + key_values.push_back(std::pair ("prior_b_intens_log_in_scale", str(Prob::Prior::BaseIntensity::Log::INPUT_SCALE_DEFAULT))); + + check_parameters_group(echo_options, "prior_intens_log", key_values, Prob::Prior::BaseIntensity::Log::ACTIVE_DEFAULT); + + + } else if (Prob::Prior::BaseIntensity::Log::ACTIVE_DEFAULT == Active) + echo_options["prior_intens_log"] = "0 1"; + + //------------------------------// + // Method Specific Paramters. // + //------------------------------// + + + if (is_mcmc(method)) { + + echo_arguments.push_back(obs_image_location); + + if (overide_state_location) { + echo_arguments.push_back(state_location); + echo_options.erase("initial_state"); + echo_options.erase("initial_state_location"); + + } else if (is_mcmc(loaded_method)) { + load_and_check_state_parameters(echo_options, "initial_state"); + echo_arguments.push_back(echo_options["initial_state_location"]); + echo_options.erase("initial_state_location"); + + } else + echo_arguments.push_back("__initial_state_location_place_holder__"); + + } else if (is_mcmc(loaded_method)) { + + echo_options.erase("initial_state"); + echo_options.erase("initial_state_location"); + echo_options.erase("sample_period"); + echo_options.erase("burn_sample_period"); + echo_options.erase("burn_snr"); + + } + + + if (is_analysis(method)) { + + if (obs_image_location != "__obs_image_place_holder__") + echo_options["obs_image"] = obs_image_location; + + } + + //Hamiltonian method + if (is_riemannian(method)) { + + check_parameter(echo_options,"num_samples", str(MCMC::Riemannian::NUM_SAMPLES_DEFAULT)); + check_parameter(echo_options,"num_leapfrog_steps", str(MCMC::Hamiltonian::NUM_LEAPFROG_STEPS_DEFAULT)); + check_parameter(echo_options,"num_newton_steps", str(MCMC::Riemannian::NUM_NEWTON_STEPS_DEFAULT)); + check_parameter(echo_options,"burn_num_samples", str(MCMC::Riemannian::BURN_NUM_SAMPLES_DEFAULT)); + check_parameter(echo_options,"burn_num_leapfrog_steps", str(MCMC::Riemannian::BURN_NUM_LEAPFROG_STEPS_DEFAULT)); + check_parameter(echo_options,"burn_num_newton_steps", str(MCMC::Riemannian::BURN_NUM_NEWTON_STEPS_DEFAULT)); + check_parameter(echo_options,"burn_snr", str(MCMC::Riemannian::BURN_SNR_DEFAULT)); + check_parameter(echo_options,"precondition", str(MCMC::Riemannian::PRECONDITION_DEFAULT)); + + std::vector leapfrog_defaults; + +// leapfrog_defaults.push_back(str(Fibre::Strand::Set::Momentum::STEP_LOCATION_DEFAULT)); +// leapfrog_defaults.push_back(str(Fibre::Tractlet::Set::Momentum::STEP_LOCATION_DEFAULT)); +// leapfrog_defaults.push_back(""); +// +// load_and_check_state_parameters (echo_options, "momen_step", leapfrog_defaults); + + + } else if (is_hamiltonian(loaded_method)) { + + echo_options.erase("num_samples"); + echo_options.erase("burn_num_samples"); + + echo_options.erase("leapfrog"); + echo_options.erase("leapfrog_location"); + echo_options.erase("leapfrog_scale"); + + } + + + //Hamiltonian method + if (is_hamiltonian(method)) { + + check_parameter(echo_options,"num_samples", str(MCMC::Hamiltonian::NUM_SAMPLES_DEFAULT)); + check_parameter(echo_options,"num_leapfrog_steps", str(MCMC::Hamiltonian::NUM_LEAPFROG_STEPS_DEFAULT)); + check_parameter(echo_options,"burn_num_samples", str(MCMC::Hamiltonian::BURN_NUM_SAMPLES_DEFAULT)); + check_parameter(echo_options,"burn_num_leapfrog_steps", str(MCMC::Hamiltonian::BURN_NUM_LEAPFROG_STEPS_DEFAULT)); + check_parameter(echo_options,"burn_snr", str(MCMC::Hamiltonian::BURN_SNR_DEFAULT)); + + std::vector leapfrog_defaults; + +// leapfrog_defaults.push_back(str(Fibre::Strand::Set::Momentum::STEP_LOCATION_DEFAULT)); +// leapfrog_defaults.push_back(str(Fibre::Tractlet::Set::Momentum::STEP_LOCATION_DEFAULT)); +// leapfrog_defaults.push_back(""); +// +// load_and_check_state_parameters (echo_options, "leapfrog", leapfrog_defaults); + + + } else if (is_hamiltonian(loaded_method)) { + + echo_options.erase("num_samples"); + echo_options.erase("burn_num_samples"); + + echo_options.erase("leapfrog"); + echo_options.erase("leapfrog_location"); + echo_options.erase("leapfrog_scale"); + + } + + + //Metropolis method + if (is_metropolis(method)) { + + check_parameter(echo_options,"num_iterations", str(MCMC::Metropolis::NUM_ITERATIONS_DEFAULT)); + check_parameter(echo_options,"sample_period", str(MCMC::Metropolis::SAMPLE_PERIOD_DEFAULT)); + check_parameter(echo_options,"burn_num_iterations", str(MCMC::Metropolis::BURN_NUM_ITERATIONS_DEFAULT)); + check_parameter(echo_options,"burn_sample_period", str(MCMC::Metropolis::BURN_SAMPLE_PERIOD_DEFAULT)); + check_parameter(echo_options,"burn_snr", str(MCMC::Metropolis::BURN_SNR_DEFAULT)); + + } else if (is_metropolis(loaded_method)) { + + echo_options.erase("num_iterations"); + echo_options.erase("burn_num_iterations"); + + } + + + + //Scan method + if (is_scan(method)) { + + check_parameter(echo_options, "only_first", "0"); + + //Append the origin location to the argument list. + if (origin_location.size()) + echo_arguments.push_back(origin_location); + + else if (is_scan(loaded_method)) { + + load_and_check_state_parameters(echo_options, "origin"); + echo_arguments.push_back(echo_options["origin_location"]); + + } else + echo_arguments.push_back("__origin_location_place_holder__"); + + + //Append the axes locations to the argument list. + if (axis1_location.size()) { + + echo_arguments.push_back(axis1_location); + + if (axis2_location.size()) { + + echo_arguments.push_back(axis2_location); + + if (axis3_location.size()) + echo_arguments.push_back(axis3_location); + + } + + } else { + + if (echo_options.count("axis1")) { + load_and_check_state_parameters(echo_options, "axis1"); + echo_arguments.push_back(echo_options["axis1_location"]); + } else + echo_arguments.push_back("__axes_place_holder__"); + + if (echo_options.count("axis2")) { + load_and_check_state_parameters(echo_options, "axis2"); + echo_arguments.push_back(echo_options["axis2_location"]); + } + + if (echo_options.count("axis3")) { + load_and_check_state_parameters(echo_options, "axis3"); + echo_arguments.push_back(echo_options["axis3_location"]); + } + + } + + + } else if (is_scan(loaded_method)) { + + echo_options.erase("only_first"); + + } + + echo_options.erase("origin"); + echo_options.erase("origin_location"); + echo_options.erase("axis1"); + echo_options.erase("axis1_scale"); + echo_options.erase("axis1_location"); + echo_options.erase("axis2"); + echo_options.erase("axis2_scale"); + echo_options.erase("axis2_location"); + echo_options.erase("axis3"); + echo_options.erase("axis3_scale"); + echo_options.erase("axis3_location"); + + + + + //Test gradient method + if (is_gradient_test(method)) { + + if (state_location.size()) + echo_arguments.push_back(state_location); + else if (is_gradient_test(loaded_method)) + echo_arguments.push_back(echo_options["state_location"]); + else + echo_arguments.push_back("__state_location_place_holder__"); + + echo_options["obs_image"] = obs_image_location; + + } else if (is_gradient_test(loaded_method)) { + + echo_options.erase("state_location"); + + } + + + + + //All methods + echo_arguments.push_back(output_location); + + + +//--------------------------------// +// Echo the required parameters // +//--------------------------------// + + + //Print preceding newlines. + std::cout << std::endl << std::endl; + + //print method name. + std::cout << method; + + //print echo_arguments. + for (size_t arg_i = 0; arg_i < echo_arguments.size() - set_output_last; arg_i++) + std::cout << " " << echo_arguments[arg_i]; + + //print echo_options. + for (std::map::iterator opt_it = echo_options.begin(); opt_it != echo_options.end(); ++opt_it) { + + //If option actuall has value (in the checking procedure empty values may be added). + if (opt_it->second.size()) + std::cout << " -" << opt_it->first << " " << opt_it->second; + + } + + //If output argument is to be printed last, then print it now. + if (set_output_last) + std::cout << " " << echo_arguments.back(); + + //print following newlines. + std::cout << std::endl << std::endl; + +} + + + +void check_parameter(std::map& echo_options, + const std::string& key, + const std::string& default_value) { + + if (echo_options.count(key)) { + + if (echo_options[key] == default_value) + echo_options.erase(key); + + } + +} + + +void check_parameters_group (std::map& echo_options, + const std::string& name, + std::vector< std::pair > key_default_value_pairs, + bool default_active) { + + int num_append = 0; + + for (size_t pair_i = 0; pair_i < key_default_value_pairs.size(); pair_i++) { + + if (echo_options.count(key_default_value_pairs[pair_i].first)) { + + if (echo_options[key_default_value_pairs[pair_i].first] != key_default_value_pairs[pair_i].second) { + key_default_value_pairs[pair_i].second = echo_options[key_default_value_pairs[pair_i].first]; + num_append = pair_i+1; + } + + echo_options.erase(key_default_value_pairs[pair_i].first); + + } + + } + + if (num_append || !default_active) { + + echo_options[name] = ""; + + for (size_t append_i = 0; append_i < key_default_value_pairs.size(); append_i++) // for (size_t append_i = 0; append_i < num_append; append_i++) + echo_options[name] += " " + key_default_value_pairs[append_i].second; + + } + +} + + +template void load_and_check_parameters ( std::map& echo_options, + const std::string& key, + const std::string& default_value_location = "") { + + + T default_value, scaled_default_value, loaded_value, scaled_loaded_value; + std::string value_str = echo_options[key]; + std::string place_holder = "\"__" + key + "(" + value_str + ")_place_holder__\""; + + if (value_str.size()) { + + double scale = 1.0; + bool matches_default = false; + + if (echo_options.count(key + "_scale")) + scale = to(echo_options[key + "_scale"]); + + std::string loaded_value_location = echo_options[key + "_location"]; + + echo_options.erase(key); + echo_options.erase(key+"_scale"); + echo_options.erase(key+"_location"); + + + //First, check to see if saved value matches default value or a scaled version of the defaul value + if (default_value_location.size()) { + + try { + + default_value.load (default_value_location); + scaled_default_value = default_value; + scaled_default_value *= scale; + + //Loaded value still matches saved value. + if (default_value.matlab_str() == value_str) + + //'loaded value' == 'Default_value' no paramters need to be set. + matches_default = true; + + else if (scaled_default_value.matlab_str() == value_str) { + + //'loaded value' == scaled version of 'Default_value' only scale parameter needs to be set. + echo_options[key+"_scale"] = str(scale); + matches_default = true; + + } + + } catch (Exception e) { + + std::cout << "WARNING!! Could not load default parameter from location '" + default_value_location + "'." << std::endl << std::endl; + + } + + } + + //If saved value does not equal default, check to see if it still matches the saved location + if (!matches_default) { + + if (!loaded_value_location.size()) { + echo_options[key] = place_holder; + + } else { + + //If it doesn't check the loaded value to see if that is still the same. + try { + + loaded_value.load(loaded_value_location); + scaled_loaded_value = loaded_value; + scaled_loaded_value *= scale; + + //Loaded value still matches saved value. + if (loaded_value.matlab_str() == value_str) + + echo_options[key+"_location"] = loaded_value_location; + + else if (scaled_loaded_value.matlab_str() == value_str) { + + //Scale is added back into the echo_options + echo_options[key+"_location"] = loaded_value_location; + echo_options[key+"_scale"] = str(scale); + + + } else + + echo_options[key] = place_holder; + + + } catch (Exception e) { + + std::cout << "WARNING!! Could not load parameter from location '" + loaded_value_location + "', skipping." << std::endl << std::endl; + + echo_options[key] = place_holder; + + } + + } + + } + + } + +} + + +void load_and_check_state_parameters ( std::map& echo_options, + const std::string& key, + const std::vector& default_value_locations) { + + + if (echo_options.count(key)) { + + std::string state_location = echo_options[key + "_location"]; + + if (File::has_extension(state_location)) + load_and_check_parameters(echo_options, key, default_value_locations[0]); + + else if (File::has_extension(state_location)) + load_and_check_parameters(echo_options, key, default_value_locations[1]); + + else if (File::has_extension(state_location)) + load_and_check_parameters(echo_options, key, default_value_locations[2]); + + else { + echo_options[key + "_location"] = "__" + key + "_place_holder_(" + echo_options[key] + ")__"; + echo_options.erase(key); + echo_options.erase(key+"_scale"); + } + + } + +} +*/ + +int main() { + + return 0; + +} diff --git a/cmd/export_fibres.cpp b/cmd/export_fibres.cpp new file mode 100644 index 0000000..759a4f6 --- /dev/null +++ b/cmd/export_fibres.cpp @@ -0,0 +1,160 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Written by Thomas G. Close, 04/03/2009. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + + */ + +#include "progressbar.h" + +#include "bts/cmd.h" + + +#include "bts/triple.h" + +#include "bts/common.h" + +#include "bts/fibre/strand/set.h" +#include "bts/fibre/track/set.h" + +const double RADII_DEFAULT = 0.03; +const size_t NUM_LENGTH_SECTIONS_DEFAULT = 100; + +using namespace BTS; + +SET_VERSION_DEFAULT; +SET_AUTHOR ("Thomas G. Close"); +SET_COPYRIGHT (NULL); + +DESCRIPTION = { + "Export MRtrix tracks file to NFG format.", + "The output ascii files will consist of 3xN matrices, corresponding to the [ X Y Z ] coordinates of the N points making up the path. All paths will be written to the output folder.", + NULL +}; + +ARGUMENTS = { + Argument ("input", "The strands to be exported.").type_file (), + Argument ("output", "The output directory where the ASCII files will be written to.").type_file(), + Argument() +}; + + +OPTIONS = { + + Option ("radii","The radii of the exported tracks.") + + Argument ("radii","").type_float (SMALL_FLOAT, RADII_DEFAULT, LARGE_FLOAT), + + Option ("num_length_sections","Number of length sections to convert strands into tracks before exporting.") + + Argument ("num_length_sections","").type_integer (0,NUM_LENGTH_SECTIONS_DEFAULT,LARGE_INT), + + +Option() }; + + + +EXECUTE { + + std::string input_location = argument[0]; + std::string output_location = argument[1]; + + double radii = RADII_DEFAULT; + size_t num_length_sections = NUM_LENGTH_SECTIONS_DEFAULT; + + bool use_loaded_radii = true; + + Options opt = get_options("radii"); + if (opt.size()) { + radii = opt[0][0]; + use_loaded_radii = false; + } + + opt = get_options("num_length_sections"); + if (opt.size()) + num_length_sections = opt[0][0]; + + + + Fibre::Track::Set tcks(input_location, num_length_sections); + + MR::ProgressBar progress_bar ("Exporting MRtrix tracks file to NFG format...", tcks.size()); + + File::mkdir(output_location); + + size_t count = 0; + + size_t max_bundle_index = 0; + + if (tcks.has_extend_elem_prop(Fibre::Track::BUNDLE_INDEX_EPROP)) { + + for (size_t tck_i = 0; tck_i < tcks.size(); ++tck_i) { + + size_t bundle_index = to(tcks.get_extend_elem_prop(Fibre::Track::BUNDLE_INDEX_EPROP, tck_i)); + + if (bundle_index > max_bundle_index) + max_bundle_index = bundle_index; + + } + + } else + max_bundle_index = tcks.size(); + + size_t num_tck_i_dec_places = num_dec_places(tcks.size()); + size_t num_bundle_dec_places = num_dec_places(max_bundle_index); + + + for (size_t tck_i = 0; tck_i < tcks.size(); ++tck_i) { + + size_t bundle_index; + + if (tcks.has_extend_elem_prop(Fibre::Track::BUNDLE_INDEX_EPROP)) + bundle_index = to(tcks.get_extend_elem_prop(Fibre::Track::BUNDLE_INDEX_EPROP, tck_i)); + else + bundle_index = tck_i; + + double track_radius; + + if (tcks.has_extend_elem_prop(Fibre::Track::RADIUS_PROP) && use_loaded_radii) + track_radius = to(tcks.get_extend_elem_prop(Fibre::Track::RADIUS_PROP, tck_i)); + else + track_radius = radii; + + std::stringstream filename_stream; + + filename_stream << output_location << std::setfill('0') << "/strand_" << std::setw(num_tck_i_dec_places) << tck_i << "-" << std::setw(num_bundle_dec_places) << bundle_index << "-r" << track_radius << ".txt"; + std::string filename = filename_stream.str(); + + std::ofstream out (filename.c_str()); + + if (!out) { + throw Exception ("error opening ascii file \"" + filename + "\": " + strerror (errno)); + } + + for (size_t point_i = 0; point_i < tcks[tck_i].size(); ++point_i) + out << tcks[tck_i][point_i][X] << " " << tcks[tck_i][point_i][Y] << " " << tcks[tck_i][point_i][Z] << "\n"; + + + out.close(); + count++; + ++progress_bar; + + + } + + + +} diff --git a/cmd/fibre_info.cpp b/cmd/fibre_info.cpp new file mode 100644 index 0000000..e18ebeb --- /dev/null +++ b/cmd/fibre_info.cpp @@ -0,0 +1,95 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by J-Donald Tournier, 27/06/08. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + + +#include "bts/cmd.h" +#include "bts/common.h" + +#include "bts/inline_functions.h" +#include "bts/fibre/strand.h" + +using namespace BTS; + +SET_VERSION_DEFAULT; +SET_AUTHOR ("Thomas G. Close"); +SET_COPYRIGHT (NULL); + +DESCRIPTION = { + "Displays fibres file header.", + "", + NULL +}; + +ARGUMENTS = { + Argument ("fibres_file", "the input track file.").allow_multiple().type_file (), + Argument() +}; + + +OPTIONS = { + + Option ("property", "Print only the selected properties.") + + Argument ("property", "").allow_multiple(), + + + Option() +}; + +EXECUTE { + + std::vector selected_properties; + + Options opt = get_options("property"); + if (opt.size()) + for (size_t prop_i = 0; prop_i < opt.size(); ++prop_i) + selected_properties.push_back(opt[prop_i][0]); + + + for (std::vector::iterator arg = argument.begin(); arg != argument.end(); ++arg) { + Fibre::Strand::Reader reader; // Doesn't really matter if it is a Strand/Tractlet or Track + reader.open (arg->c_str()); + + + if (selected_properties.size()) { + + for (std::vector::iterator select_it = selected_properties.begin(); select_it != selected_properties.end(); ++select_it) + std::cout << reader.get_extend_props()[*select_it] << " "; + + std::cout << std::endl; + + + } else { + + std::cout << "***********************************\n"; + std::cout << " Fibre file: \"" << arg->c_str() << "\"\n"; + std::map extended_props = reader.get_extend_props(); + for (std::map::map::iterator i = extended_props.begin(); i != extended_props.end(); ++i) { + std::string str (i->first + ':'); + str.resize (40, ' '); + std::cout << " " << str << i->second << "\n"; + } + + } + + } + +} diff --git a/cmd/generate_image.cpp b/cmd/generate_image.cpp new file mode 100644 index 0000000..dd94d78 --- /dev/null +++ b/cmd/generate_image.cpp @@ -0,0 +1,278 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + + + +extern "C" { +#include +#include +} + + +#include "bts/cmd.h" + +#include "bts/math/common.h" + +#include "image/header.h" +#include "image/header.h" +#include "dwi/gradient.h" +#include "progressbar.h" + +#include "bts/common.h" + +#include "bts/fibre/strand/set.h" +#include "bts/fibre/tractlet/set.h" + +#include "bts/image/observed/buffer.h" +#include "bts/image/expected/buffer.h" +#include "bts/image/expected/trilinear/buffer.h" +#include "bts/image/expected/gaussian/buffer.h" +#include "bts/image/expected/quartic/buffer.h" +#include "bts/diffusion/model.h" + +#include "bts/image/noise/gaussian.h" +#include "bts/image/noise/rician.h" + + + +#include "bts/inline_functions.h" + + +using namespace BTS; + +SET_VERSION_DEFAULT; +SET_AUTHOR ("Thomas G. Close"); +SET_COPYRIGHT (NULL); + +DESCRIPTION = { + "Generates a set of DW-BTS images from a given strand or tractlet configuration.", + "", + NULL +}; + +ARGUMENTS = { + Argument ("input", "The strands file the image set will be expected_image from.").type_file (), + Argument ("output", "The generated DW-MR image set").optional().type_image_out (), + Argument() +}; + + +OPTIONS = { + + Option ("clean", "No noise added to the image."), + + Option ("seed", "The random seed that is passed to the random generator") + + Argument ("seed", ""), + + Option ("degree", "Degree of strands when converted from tracks") + + Argument ("degree", "").type_integer (0, Fibre::Strand::DEFAULT_DEGREE, LARGE_INT), + + DIFFUSION_PARAMETERS, + + IMAGE_PARAMETERS, + + EXPECTED_IMAGE_PARAMETERS, + + NOISE_PARAMETERS, + + COMMON_PARAMETERS, + + +Option() }; + + + +EXECUTE { + + +//--------------// +// Get options // +//--------------// + + std::string input_location = argument[0]; + std::string output_location; + + if (argument.size() > 1) + output_location = argument[1].c_str(); + else + output_location = File::strip_extension (input_location) + ".mif"; + + bool clean = false; + size_t seed = time(0); + size_t degree = Fibre::Strand::DEFAULT_DEGREE; + + + Options opt = get_options("clean"); + if (opt.size()) + clean = true; + + opt = get_options("seed"); + if (opt.size()) { + std::string seed_str = opt[0][0]; + seed = to(seed_str); + } + + opt = get_options("degree"); + if (opt.size()) + degree = opt[0][0]; + + // Loads parameters to construct Diffusion::Model ('diff_' prefix) + SET_DIFFUSION_PARAMETERS; + + // Loads parameters to construct Image::Expected::*::Buffer that are inherited from Image::Observed::Buffer ('img_' prefix) + SET_IMAGE_PARAMETERS; + + // Loads extra parameters to construct Image::Expected::*::Buffer ('img_' prefix) + SET_EXPECTED_IMAGE_PARAMETERS; + + // Loads parameters to construct Image::Noise::* ('noise_' prefix) + SET_NOISE_PARAMETERS; + + // Loads parameters that are common to all commands. + SET_COMMON_PARAMETERS; + + +//----------------------------------------------------// +// Auto generate parameters if not set or irrelevant // +//----------------------------------------------------// + + if (!img_offsets.valid()) + img_offsets = Image::Observed::Buffer::default_corner_offset(img_dims, img_vox_lengths); + + + exp_enforce_bounds = true; + + if (!diff_isotropic && (noise_type == "rician")) + throw Exception ("Rician noise cannot be added to images with isotropic components removed."); + +//-------------------------// +// Set up diffusion model // +//-------------------------// + + Diffusion::Model diffusion_model = Diffusion::Model::factory (diff_encodings, + diff_response_SH, + diff_adc, + diff_fa, + diff_isotropic); + + +//----------------------------------// +// Initialize expected_image image // +//----------------------------------// + + + + Image::Expected::Buffer* image = Image::Expected::Buffer::factory(exp_type, + img_dims, + img_vox_lengths, + diffusion_model, + exp_num_length_sections, + exp_num_width_sections, + exp_interp_extent, + img_offsets, + exp_enforce_bounds, + exp_half_width); + + + +//-----------------// +// Fabricate image // +//-----------------// + + + MR::ProgressBar progress_bar ("Generating image from provided fibres..."); + + if (File::has_or_txt_extension(input_location) || File::has_or_txt_extension(input_location)) { + + Fibre::Strand::Set strands (input_location, degree); + + //exp_base_intensity is recorded in header so needs to be synchronised with base_intensity of strands + if (exp_base_intensity < 0) + exp_base_intensity = strands.base_intensity(); + else + strands.set_base_intensity(exp_base_intensity); + + image->expected_image(strands); + + } else if (File::has_or_txt_extension(input_location)) { + + Fibre::Tractlet::Set tractlets (input_location); + + //exp_base_intensity is recorded in header so needs to be synchronised with base_intensity of tractlets + if (exp_base_intensity < 0) + exp_base_intensity = tractlets.base_intensity(); + else + tractlets.set_base_intensity(exp_base_intensity); + + image->expected_image(tractlets); + + } else + throw Exception ("Unrecognised extension '" + input_location + "'."); + + image->properties()["type"] = "synthetic"; + image->properties()["method"] = "generate_image"; + image->properties()["state_location"] = input_location; + + image->properties()["software version"] = version_number_string(); + image->properties()["datetime"] = current_datetime(); + + + ADD_DIFFUSION_PROPERTIES(image->properties()); + + ADD_IMAGE_PROPERTIES(image->properties()); + + ADD_EXPECTED_IMAGE_PROPERTIES(image->properties()); + + ADD_COMMON_PROPERTIES(image->properties()); + + + //If '-clean' option is not selected noise is be added to the image. + if (!clean) { + + gsl_rng* rand_gen = gsl_rng_alloc(gsl_rng_taus); + gsl_rng_set(rand_gen, seed); + + if (isnan(noise_ref_signal)) + noise_ref_signal = image->max_b0(); + + Image::Noise* noise = Image::Noise::factory(rand_gen, noise_type, noise_snr, noise_ref_signal); + + noise->noisify(*image); + + ADD_NOISE_PROPERTIES(image->properties()); + } + + + //------------// + // Save image // + //------------// + + + image->save(output_location); + + + +} + + + + diff --git a/cmd/hamiltonian.cpp b/cmd/hamiltonian.cpp new file mode 100644 index 0000000..c1786de --- /dev/null +++ b/cmd/hamiltonian.cpp @@ -0,0 +1,552 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + + + +extern "C" { +#include +#include +} + + +#include + +#include "bts/cmd.h" + +#include "math/matrix.h" + +#include "progressbar.h" + + +#include "bts/common.h" +#include "bts/file.h" + + +#include "bts/fibre/tractlet/set.h" +#include "bts/fibre/strand/set.h" + + + + +#include "bts/diffusion/model.h" +#include "bts/image/expected/trilinear/buffer.h" +#include "bts/image/expected/gaussian/buffer.h" +#include "bts/image/expected/quartic/buffer.h" + +#include "bts/image/observed/buffer.h" + +#include "bts/prob/uniform.h" +#include "bts/prob/prior.h" + +#include "bts/prob/likelihood.h" +#include "bts/prob/likelihood.h" +#include "bts/prob/likelihood/one_sided_gaussian.h" +#include "bts/prob/likelihood/gaussian.h" + +#include "bts/fibre/strand/set/momentum.h" +#include "bts/fibre/tractlet/set/momentum.h" +#include "bts/mcmc/proposal/distribution.h" +#include "bts/mcmc/proposal/distribution/gaussian.h" +#include "bts/mcmc/proposal/momentum/weighted.h" + +#include "bts/math/common.h" + +#include "bts/mcmc/hamiltonian.h" + +#include "bts/file.h" + + + +#include "bts/inline_functions.h" + +using namespace BTS; + + +SET_VERSION_DEFAULT; +SET_AUTHOR ("Thomas G. Close"); +SET_COPYRIGHT (NULL); + +DESCRIPTION = { + "Runs Hamiltonian MCMC sampling on a given image from a given starting configuration of tractlets or strands.", + "", + NULL +}; + +ARGUMENTS = { + Argument ("input_image", "The image the tractlets will be fit against.").type_image_in(), + + Argument ("inital tractlets", "A starting point for the MCMC algorithm.").type_file (), + + Argument ("samples location", "The location where the samples will be saved.").type_file (), + + Argument() +}; + + +OPTIONS = { + + + Option ("num_samples", "The Number of MCMC iterations to take of the prob distribution over the tractlets") + + Argument ("num_samples", "").type_integer (1, MCMC::Hamiltonian::NUM_SAMPLES_DEFAULT, LARGE_INT), + + Option ("num_leapfrog_steps", "The number of MCMC iterations that will be performed before a sample is saved") + + Argument ("num_leapfrog_steps", "").type_integer (1, MCMC::Hamiltonian::NUM_LEAPFROG_STEPS_DEFAULT, LARGE_INT), + + Option ("burn_num_samples", "The Number of MCMC iterations to take as part of the Burn-in.") + + Argument ("burn_num_samples", "").type_integer (0, MCMC::Hamiltonian::BURN_NUM_SAMPLES_DEFAULT, LARGE_INT), + + Option ("burn_num_leapfrog_steps", "The number of MCMC iterations that will be performed before a sample is saved in the Burn-in.") + + Argument ("burn_num_leapfrog_steps", "").type_integer (1, MCMC::Hamiltonian::BURN_NUM_LEAPFROG_STEPS_DEFAULT, LARGE_INT), + + Option ("burn_snr", "The Signal-to-noise ratio assumed for the burn-in period.") + + Argument ("burn_snr", "").type_float (SMALL_FLOAT, MCMC::Hamiltonian::BURN_SNR_DEFAULT, LARGE_FLOAT), + + Option ("seed", "The random seed that is passed to the random generator") + + Argument ("seed", ""), + + Option ("prior_only", "Only sample from the prior distribution."), + + Option ("save_iterations", "Save all iterations not just samples."), + + DIFFUSION_PARAMETERS, + + EXPECTED_IMAGE_PARAMETERS, + + LIKELIHOOD_PARAMETERS, + + PRIOR_PARAMETERS, + + PROPOSAL_DISTRIBUTION_PARAMETERS, + + PROPOSAL_MOMENTUM_PARAMETERS, + + COMMON_PARAMETERS, + +Option() }; + + +EXECUTE { + +//-----------------// +// Load Arguments // +//-----------------// + + std::string obs_image_location = argument[0]; + std::string initial_location = argument[1]; + std::string samples_location = argument[2]; + std::string burn_samples_location = File::strip_extension (samples_location) + ".burn." + File::extension(samples_location); + + MR::Image::Header header (argument[0]); + + if (header.ndim() != 4) + throw Exception ("dwi image should contain 4 dimensions"); + + + +//----------------------------------// +// Get and Set Optional Parameters // +//----------------------------------// + + + size_t num_samples = MCMC::Hamiltonian::NUM_SAMPLES_DEFAULT; + size_t num_leapfrog_steps = MCMC::Hamiltonian::NUM_LEAPFROG_STEPS_DEFAULT; + size_t burn_num_samples = MCMC::Hamiltonian::BURN_NUM_SAMPLES_DEFAULT; + size_t burn_num_leapfrog_steps = MCMC::Hamiltonian::BURN_NUM_LEAPFROG_STEPS_DEFAULT; + double burn_snr = MCMC::Hamiltonian::BURN_SNR_DEFAULT; + size_t seed = time(NULL); + bool prior_only = false; + bool save_iterations = true; + + + Options opt = get_options("num_samples"); + if (opt.size()) + num_samples = opt[0][0]; + + opt = get_options("num_leapfrog_steps"); + if (opt.size()) + num_leapfrog_steps = opt[0][0]; + + opt = get_options("burn_num_samples"); + if (opt.size()) + burn_num_samples = opt[0][0]; + + opt = get_options("burn_num_leapfrog_steps"); + if (opt.size()) + burn_num_leapfrog_steps = opt[0][0]; + + opt = get_options("burn_snr"); + if (opt.size()) + burn_snr = opt[0][0]; + + opt = get_options("seed"); + if (opt.size()) { + std::string seed_string = opt[0][0]; + seed = to(seed_string); + } else + std::cout << "No random seed supplied. Using timestamp: " << seed << std::endl; + + opt = get_options("prior_only"); + if (opt.size()) + prior_only = true; + + opt = get_options("save_iterations"); + if (opt.size()) + save_iterations = true; + + // Loads parameters to construct Diffusion::Model ('diff_' prefix) + SET_DIFFUSION_PARAMETERS; + + // Loads parameters to construct Image::Expected::*::Buffer ('img_' prefix) + SET_EXPECTED_IMAGE_PARAMETERS; + + // Loads parameters to construct Prob::Likelihood ('like_' prefix) + SET_LIKELIHOOD_PARAMETERS; + + // Loads parameters to construct Prob::Prior ('prior_' prefix) + SET_PRIOR_PARAMETERS; + + // Loads parameters to construct Proposal::Distribution (any variables with 'prop_' prefix) + SET_PROPOSAL_DISTRIBUTION_PARAMETERS; + + // Loads parameters to construct Proposal::Distribution ('prop_' prefix) + SET_PROPOSAL_MOMENTUM_PARAMETERS(initial_location); + + // Loads parameters that are common to all commands. + SET_COMMON_PARAMETERS; + + + //--------------------------------// + // Set up reference image buffer // + //--------------------------------// + + + Image::Observed::Buffer obs_image(obs_image_location, Diffusion::Encoding::Set(diff_encodings)); + + + //If gradient scheme is included in reference image header, use that instead of default (NB: Will override any gradients passed to '-diff_encodings' option). + if (header.get_DW_scheme().rows()) { + diff_encodings = header.get_DW_scheme(); + diff_encodings_location = "from observed image"; + } + + if ((header.count("diff_response_SH")) && (Math::matlab_str(diff_response_SH) != header["diff_response_SH"])) + std::cout << std::endl << "Warning! Diffusion response function harmonics (" << Math::matlab_str(diff_response_SH) << ") do not match reference image (" << header["diff_response_SH"] + ")!" << std::endl; + + + //----------------------------// + // Initialize Expected Image // + //----------------------------// + + + + Diffusion::Model diffusion_model = Diffusion::Model::factory (diff_encodings, + diff_response_SH, + diff_adc, + diff_fa, + diff_isotropic); + + Image::Expected::Buffer* exp_image = Image::Expected::Buffer::factory(exp_type, + obs_image, + diffusion_model, + exp_num_length_sections, + exp_num_width_sections, + exp_interp_extent, + exp_enforce_bounds, + exp_half_width); + + + + + //----------------------------------------------------------------// + // Auto-generate base intensity initial value/b_intens_gauss_mean // + //----------------------------------------------------------------// + + if (exp_base_intensity < 0) + exp_base_intensity = exp_image->base_intensity_default(obs_image, initial_location); + + //-----------------------// + // Initialize Likelihood // + //-----------------------// + + Prob::Likelihood* likelihood = Prob::Likelihood::factory(like_type, obs_image, exp_image, like_snr, like_b0_include, like_outside_scale, like_ref_b0, like_ref_signal); + + + + //----------------------------------// + // Initialize Proposal Distribution // + //----------------------------------// + + gsl_rng* rand_gen = gsl_rng_alloc(gsl_rng_taus); + gsl_rng_set(rand_gen, seed); + + MCMC::Proposal::Distribution* proposal_distribution = MCMC::Proposal::Distribution::factory(prop_distr_type, rand_gen); + + + +// Proposal::Intensity* intensity_proposer = Proposal::Intensity::factory(prop_intens_type, proposal_distribution, prop_intens_scale); +// +// Proposal::BaseIntensity* base_intensity_proposer = Proposal::BaseIntensity::factory(prop_base_intens_type, proposal_distribution, prop_base_intens_scale); + + + + //-------------------------// + // Set Output Properties // + //-------------------------// + + std::map run_properties; + + run_properties["Method"] = "hamiltonian"; + run_properties["num_leapfrog_steps"] = str(num_leapfrog_steps); + run_properties["seed"] = str(seed); + run_properties["num_samples"] = str(num_samples); + run_properties["burn_num_leapfrog_steps"] = str(burn_num_leapfrog_steps); + run_properties["burn_num_samples"] = str(burn_num_samples); + run_properties["burn_snr"] = str(burn_snr); + run_properties["obs_image"] = obs_image_location; + run_properties["initial_state"] = Fibre::Base::Object::load_matlab_str(initial_location); + run_properties["initial_state_location"]= initial_location; + + run_properties["prior_only"] = str(prior_only); + + ADD_DIFFUSION_PROPERTIES(run_properties); + + ADD_LIKELIHOOD_PROPERTIES(run_properties); + + ADD_EXPECTED_IMAGE_PROPERTIES(run_properties); + + ADD_PRIOR_PROPERTIES(run_properties); + + ADD_PROPOSAL_DISTRIBUTION_PROPERTIES(run_properties); + + ADD_PROPOSAL_MOMENTUM_PROPERTIES(run_properties); + + ADD_COMMON_PROPERTIES(run_properties); + + + //-------------------------// + // Sampling from Strands // + //-------------------------// + + //------------------// + // Initialize Prior // + //------------------// + + Prob::Prior prior (prior_scale, + prior_mag_scale, + prior_mag_aux_scale, + prior_hook_scale, + prior_hook_num_points, + prior_density_high_scale, + prior_density_low_scale, + prior_density_num_points, + prior_acs_scale, + prior_acs_mean, + prior_length_scale, + prior_length_mean); + + + if (File::has_extension(initial_location)) { + + + //------------------------// + // Load Initial Strands // + //------------------------// + + Fibre::Strand::Set strands (initial_location); + + strands.set_base_intensity(exp_base_intensity); + + + //---------------------// + // Initialize Momentum // + //---------------------// + + MCMC::Proposal::Momentum momentum = MCMC::Proposal::Momentum::factory ( strands, + momen_step_scale, + momen_step_location, + momen_weight_location, + proposal_distribution); + + + //------------------// + // Perform sampling // + //------------------// + + Fibre::Strand::Set burnt_strands; + + + + if (burn_num_samples) { + + likelihood->set_assumed_snr(burn_snr, like_ref_b0, like_ref_signal); + + burnt_strands = MCMC::hamiltonian < Fibre::Strand::Set, + Prob::Likelihood, + Prob::Prior> ( + strands, + *likelihood, + prior, + momentum, + burn_samples_location, + run_properties, + burn_num_samples, + burn_num_leapfrog_steps, + rand_gen, + prior_only, + save_iterations + ); + + likelihood->set_assumed_snr(like_snr, like_ref_b0, like_ref_signal); + + } else + burnt_strands = strands; + + + MCMC::hamiltonian < Fibre::Strand::Set, + Prob::Likelihood, + Prob::Prior> ( + burnt_strands, + *likelihood, + prior, + momentum, + samples_location, + run_properties, + num_samples, + num_leapfrog_steps, + rand_gen, + prior_only, + save_iterations + ); + + + + //------------------------// + // Sampling from Tractlets // + //------------------------// + + + } else if (File::has_extension(initial_location)) { + + + //-------------// + // Load Tractlets // + //-------------// + + Fibre::Tractlet::Set tractlets (initial_location); + + tractlets.set_base_intensity(exp_base_intensity); + + + //---------------------// + // Initialize Proposer // + //---------------------// + + + MCMC::Proposal::Momentum momentum = MCMC::Proposal::Momentum::factory ( tractlets, + momen_step_scale, + momen_step_location, + momen_weight_location, + proposal_distribution); + + + + + //------------------// + // Perform sampling // + //------------------// + + Fibre::Tractlet::Set burnt_tractlets; + + if (burn_num_samples) { + + likelihood->set_assumed_snr(burn_snr, like_ref_b0, like_ref_signal); + + burnt_tractlets = MCMC::hamiltonian ( + + tractlets, + *likelihood, + prior, + momentum, + burn_samples_location, + run_properties, + burn_num_samples, + burn_num_leapfrog_steps, + rand_gen, + prior_only, + save_iterations + ); + + likelihood->set_assumed_snr(like_snr, like_ref_b0, like_ref_signal); + + } else + burnt_tractlets = tractlets; + + + + MCMC::hamiltonian ( + + burnt_tractlets, + *likelihood, + prior, + momentum, + samples_location, + run_properties, + num_samples, + num_leapfrog_steps, + rand_gen, + prior_only, + save_iterations + ); + + + } else + throw Exception ("Unrecognised extension of initial state location, '" + initial_location + "'."); + + + std::cout << "MATLAB plot commands:\n\nplot_fibres " << samples_location << "\nscan.py " << samples_location << std::endl; + + + gsl_rng_free(rand_gen); + + delete exp_image; + delete proposal_distribution; + delete likelihood; + + +} + + + + + + + + + + + + + diff --git a/cmd/import_fibres.cpp b/cmd/import_fibres.cpp new file mode 100644 index 0000000..5857b60 --- /dev/null +++ b/cmd/import_fibres.cpp @@ -0,0 +1,249 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Written by Thomas G. Close, 04/03/2009. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + +*/ + +#include "bts/cmd.h" + +#include "progressbar.h" + +#include "bts/common.h" +#include "bts/file.h" + +#include "bts/fibre/track/set.h" +#include "bts/fibre/strand/set.h" + + + + +#include "bts/inline_functions.h" + +using namespace BTS; + +SET_VERSION_DEFAULT; +SET_AUTHOR ("Thomas G. Close"); +SET_COPYRIGHT (NULL); + +DESCRIPTION = { + "Import ascii path files into BTS format.", + "The input ascii files should consist of 3xN matrices, corresponding to the [ X Y Z ] coordinates of the N points making up the path. All the input paths will be included into the same output BTS path file.", + NULL +}; + +ARGUMENTS = { + Argument ("input", "The input strand text files to be imported into BTSTrix format.").allow_multiple().type_file (), + Argument ("output", "The output strands file in BTS format").type_file(), + Argument() +}; + + +OPTIONS = { + + Option ("prefix", "Match files in the input directory with the following prefix") + + Argument ("prefix", ""), + + + Option ("nfg_format", "Import the NFG format and save the extended track properties"), + + +Option() }; + + +void import(Fibre::Strand::Set& s_set, const std::string& location, const std::string& prefix, MR::ProgressBar& progress_bar); +void import(Fibre::Track::Set& t_set, const std::string& location, const std::string& prefix, bool nfg_format, MR::ProgressBar& progress_bar); + + +EXECUTE { + + + std::string input_location = argument[0]; + std::string output_location = argument.back(); + + bool nfg_format = false; + std::string prefix = ""; + + Options opt = get_options("prefix"); + if (opt.size()) + prefix = opt[0][0].c_str(); + + opt = get_options("nfg_format"); + + if (opt.size()) { + + nfg_format = true; + + if (File::has_extension(output_location)) + throw Exception ("'-nfg_format' can only be used with the '.tck' file format."); + + if (prefix.size()) + throw Exception ("'-prefix' option cannot be used in conjunction with '-nfg_format'."); + + prefix = "strand_"; + + } + + + if (!File::exists(input_location)) + throw Exception("Input location, " + input_location + ", does not exist"); + + + MR::ProgressBar progress_bar ("adding ASCII strand files"); + + if (File::has_extension(output_location)) { + + Fibre::Strand::Set s_set; + + std::string input_locations = ""; + for (size_t n = 0; n < argument.size()-1; n++) { + import(s_set, argument[n], prefix, progress_bar); + input_locations += argument[n].c_str(); + } + + std::map properties; + properties["import_dir"] = input_locations; + + s_set.save(output_location); + + } else if (File::has_extension(output_location)) { + + Fibre::Track::Set t_set; + + if (nfg_format) { + t_set.add_extend_elem_prop(Fibre::Track::BUNDLE_INDEX_EPROP, "0"); + + t_set.add_extend_elem_prop(Fibre::Track::RADIUS_PROP, "0.0"); + } + + std::string input_locations = ""; + for (size_t n = 0; n < argument.size()-1; n++) { + + input_locations += argument[n].c_str(); + import(t_set, argument[n], prefix, nfg_format, progress_bar); + + } + + t_set.set_extend_prop("import_dir", input_locations); + + t_set.save(output_location); + + } else + throw Exception ("Unknown file extension in output file " + output_location + "."); + + + //MR::ProgressBar::done(); +} + + + +void import(Fibre::Strand::Set& s_set, const std::string& location, const std::string& prefix, MR::ProgressBar& progress_bar) { + + if (location.length() >= 21) { + if (!location.substr(location.length() - 21).compare("isotropic_regions.txt")) + throw Exception ("Found 'isotropic_regions.txt' file, which is assumed to be from Numerical Fibre Generator (NFG) output, please use '-nfg_format' option to import these tracks, and use the '.tck' for the imported tracks file extension."); + } + + + + if (File::is_dir(location)) { + + std::vector filenames = File::list_filenames(location, prefix, "txt"); + + for (size_t filename_i = 0; filename_i < filenames.size(); filename_i++) + import(s_set, File::join(location,filenames[filename_i]), prefix, progress_bar); + + + } else { + + + MR::Math::Matrix M; + + M.load (location); + if (M.columns() != 3) + throw Exception ("WARNING: file \"" + location + "\" does not contain 3 columns - ignored"); + + + Fibre::Strand strand; + + for (size_t i = 0; i < M.rows(); i++) { + Triple d(M(i,0), M(i,1), M(i,2)); + strand.push_back(d); + } + s_set.push_back(strand); + + progress_bar++; + + } + + +} + + + +void import(Fibre::Track::Set& t_set, const std::string& location, const std::string& prefix, bool nfg_format, MR::ProgressBar& progress_bar) { + + if (location.length() >= 21) { + if (!location.substr(location.length() - 21).compare("isotropic_regions.txt") && !nfg_format) + throw Exception ("Found 'isotropic_regions.txt' file, which is assumed to be from Numerical Fibre Generator (NFG) output, please use '-nfg_format' option to import these tracks."); + } + + if (File::is_dir(location)) { + + + std::vector filenames = File::list_filenames(location, prefix, "txt"); + + for (size_t filename_i = 0; filename_i < filenames.size(); filename_i++) + import(t_set, File::join(location,filenames[filename_i]), prefix, nfg_format, progress_bar); + + + } else { + + MR::Math::Matrix M; + + M.load (location); + if (M.columns() != 3) + throw Exception ("WARNING: file \"" + location + "\" does not contain 3 columns - ignored"); + + Fibre::Track tck; + + for (size_t i = 0; i < M.rows(); i++) { + tck.push_back(Coord(M(i,0), M(i,1), M(i,2))); + } + + t_set.push_back(tck); + + if (nfg_format) { + + int bundle_index; + double track_radius; + + sscanf(File::basename(location).c_str(), "strand_%*d-%d-r%lf.txt", &bundle_index, &track_radius); + + t_set.set_extend_elem_prop(Fibre::Track::BUNDLE_INDEX_EPROP, str(bundle_index), t_set.size()-1); + + t_set.set_extend_elem_prop(Fibre::Track::RADIUS_PROP, str(track_radius), t_set.size()-1); + + } + + progress_bar++; + + } + + +} diff --git a/cmd/init_fibres.cpp b/cmd/init_fibres.cpp new file mode 100644 index 0000000..be480fd --- /dev/null +++ b/cmd/init_fibres.cpp @@ -0,0 +1,408 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, 18/06/2010. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + + +extern "C" { +#include +#include +} + +#include "progressbar.h" +#include "bts/cmd.h" + +#include "bts/common.h" + +#include "bts/image/expected/buffer.h" + +#include "bts/fibre/tractlet/set.h" +#include "bts/fibre/strand/set.h" +#include "bts/fibre/track/set.h" + + +#include "bts/inline_functions.h" + +using namespace BTS; + +const double ACS_DEFAULT =-1.0; +const double BASE_INTENSITY_DEFAULT = -1.0; +const size_t DEGREE_DEFAULT = 3; +const size_t NUM_FIBRES_DEFAULT = 5; +const float LENGTH_STDDEV_DEFAULT = 0.02; +const float WIDTH_MEAN_DEFAULT= 0.05; +const float WIDTH_STDDEV_DEFAULT= 0.005; +const float REJECT_RADIUS_DEFAULT = NAN; +const float DEFAULT_REJECT_RADIUS_SCALE = 1.5; +const double EDGE_BUFFER_DEFAULT = 0.075; +const size_t MAX_NUM_ATTEMPTS = 10000; + + +SET_VERSION_DEFAULT; +SET_AUTHOR ("Thomas G. Close"); +SET_COPYRIGHT (NULL); + +DESCRIPTION = { + "new_fibres", + "", + NULL +}; + +ARGUMENTS = { + Argument ("output","Output file location"), + Argument() +}; + + +OPTIONS = { + + Option("acs", "Intensity of the generated fibres.") + + Argument("acs","").type_float(SMALL_FLOAT,ACS_DEFAULT,LARGE_FLOAT), + + Option("base_intensity", "Base intensity of the generated fibres.") + + Argument("base_intensity","").type_float(SMALL_FLOAT,BASE_INTENSITY_DEFAULT,LARGE_FLOAT), + + Option("degree", "The degree of the generated fibres.") + + Argument("degree","").type_integer(0,DEGREE_DEFAULT,LARGE_INT), + + Option("num_fibres", "Size of the generated fibre sets.") + + Argument("num_fibres","").type_integer(0,NUM_FIBRES_DEFAULT,LARGE_INT), + + Option("length_stddev", "Standard deviation of the projection along each (i.e. x,y,z) axes.") + + Argument("length_stddev","").type_float(SMALL_FLOAT, LENGTH_STDDEV_DEFAULT,LARGE_FLOAT), + + Option("width_mean", "Mean width of the initialised fibres.") + + Argument("width_mean","").type_float(SMALL_FLOAT, WIDTH_MEAN_DEFAULT,LARGE_FLOAT), + + Option("width_stddev", "Standard deviation of width of the initialised fibres.") + + Argument("width_stddev","").type_float(SMALL_FLOAT, WIDTH_STDDEV_DEFAULT,LARGE_FLOAT), + + Option("reject_radius", "If a centre of a randomly generated fibre lies within the radius of a previously generated strand it is rejected.") + + Argument("reject_radius","").type_float(SMALL_FLOAT, REJECT_RADIUS_DEFAULT,LARGE_FLOAT), + + Option("edge_buffer", "Restrict the distributed_centres of the generated fibres to be within a certain distance from the edge of the ROI.") + + Argument("edge_buffer","").type_float(SMALL_FLOAT, EDGE_BUFFER_DEFAULT,LARGE_FLOAT), + + Option("curve_stddev", "The standard deviation of the curvature parameters.") + + Argument("curve_stddev", "").type_float(0, 0, LARGE_FLOAT), + + Option ("seed", "Seed for the random generation") + + Argument ("seed", ""), + + Option ("centre_radius", "Radius from origin that the fibre centres will be initiated on.") + + Argument("centre_radius","").type_float(SMALL_FLOAT, -1.0,LARGE_FLOAT), + + IMAGE_PARAMETERS, + + +Option() }; + + +std::vector< Triple > distributed_centres(const Triple& roi_extent, size_t num_fibres, gsl_rng* rand_gen, double reject_radius); + +std::vector< Triple > distant_centres(size_t num_fibres, double centre_radius, gsl_rng* rand_gen); + +std::vector< Triple > orientations(size_t num_fibres, gsl_rng* rand_gen, double length_stddev); + + +EXECUTE { + + + std::string output_location = argument[0]; + + + double acs = ACS_DEFAULT; + double base_intensity = BASE_INTENSITY_DEFAULT; + size_t degree = DEGREE_DEFAULT; + size_t num_fibres = NUM_FIBRES_DEFAULT; + double length_stddev = LENGTH_STDDEV_DEFAULT; + double width_mean = WIDTH_MEAN_DEFAULT; + double width_stddev = WIDTH_STDDEV_DEFAULT; + double reject_radius = REJECT_RADIUS_DEFAULT; + double edge_buffer = EDGE_BUFFER_DEFAULT; + double centre_radius = -1.0; + double curve_stddev = 0; + size_t seed = time(NULL); + + + Options opt; + + opt = get_options("acs"); + if (opt.size()) + acs = opt[0][0]; + + opt = get_options("base_intensity"); + if (opt.size()) + base_intensity = opt[0][0]; + + opt = get_options("degree"); + if (opt.size()) + degree = opt[0][0]; + + opt = get_options("num_fibres"); + if (opt.size()) + num_fibres = opt[0][0]; + + opt = get_options("length_stddev"); + if (opt.size()) + length_stddev = opt[0][0]; + + opt = get_options("width_mean"); + if (opt.size()) + width_mean = opt[0][0]; + + opt = get_options("width_stddev"); + if (opt.size()) + width_stddev = opt[0][0]; + + opt = get_options("reject_radius"); + if (opt.size()) + reject_radius = opt[0][0]; + + opt = get_options("edge_buffer"); + if (opt.size()) + edge_buffer = opt[0][0]; + + opt = get_options("centre_radius"); + if (opt.size()) + centre_radius = opt[0][0]; + + opt = get_options("curve_stddev"); + if (opt.size()) + curve_stddev = opt[0][0]; + + opt = get_options("seed"); + if (opt.size()) { + std::string seed_string = opt[0][0]; + seed = to(seed_string); + } else + std::cout << "No random seed provided, using: " << seed << std::endl; + + SET_IMAGE_PARAMETERS; + + Triple roi_extent = (img_vox_lengths * img_dims) / 2.0 - edge_buffer; + + if (isnan(reject_radius)) { + double vol = roi_extent[X] * roi_extent[Y] * roi_extent[Z] * 8.0; + + reject_radius = MR::Math::pow((3.0 * vol) / (4.0 * M_PI * (double)num_fibres), 1.0/3.0) * DEFAULT_REJECT_RADIUS_SCALE; + } + + + std::map properties; + + ADD_IMAGE_PROPERTIES(properties); + properties["length_stddev"] = str(length_stddev); + properties["width_stddev"] = str(width_stddev); + + if (centre_radius > 0) + properties["centre_radius"] = str(centre_radius); + else + properties["reject_radius"] = str(reject_radius); + + properties["edge_buffer"] = str(edge_buffer); + properties["seed"] = str(seed); + + + + //Initialise random number generator. + gsl_rng* rand_gen = gsl_rng_alloc(gsl_rng_taus); + gsl_rng_set(rand_gen, seed); + + + std::vector props; + if (base_intensity >= 0.0) + props.push_back(Fibre::Strand::Set::BASE_INTENSITY_PROP); + + + std::vector elem_props; + if (acs >= 0.0) + elem_props.push_back(Fibre::Base::Object::ACS_SQRT_PROP); + + + + + if (File::has_or_txt_extension(output_location)) { + + MR::ProgressBar progress_bar ("Initialising strands..."); + + Fibre::Strand::Set strands(num_fibres, degree, props, elem_props); + strands.zero(); + strands.set_extend_props(properties); + if (base_intensity >= 0.0) + strands.set_base_intensity(base_intensity); + + std::vector< Triple > centres; + if (centre_radius > 0) + centres = distant_centres(num_fibres, centre_radius, rand_gen); + else + centres = distributed_centres(roi_extent, num_fibres, rand_gen, reject_radius); + + std::vector< Triple > orients = orientations(num_fibres, rand_gen, length_stddev); + + for (size_t strand_i = 0; strand_i < strands.size(); ++strand_i) { + + strands[strand_i][0] = centres[strand_i]; + strands[strand_i][1] = orients[strand_i]; + + if (curve_stddev) + strands[strand_i][2] = rand_triple(curve_stddev,rand_gen); + + if (acs >= 0.0) + strands[strand_i].set_acs(acs); + + } + + + strands.save(output_location); + + } else if (File::has_or_txt_extension(output_location)) { + + MR::ProgressBar progress_bar ("Initialising tractlets..."); + + Fibre::Tractlet::Set tractlets(num_fibres, degree, props, elem_props); + tractlets.zero(); + tractlets.set_extend_props(properties); + if (base_intensity >= 0.0) + tractlets.set_base_intensity(base_intensity); + + std::vector< Triple > centres; + if (centre_radius > 0) + centres = distant_centres(num_fibres, centre_radius, rand_gen); + else + centres = distributed_centres(roi_extent, num_fibres, rand_gen, reject_radius); + + std::vector< Triple > orients = orientations(num_fibres, rand_gen, length_stddev); + + for (size_t tractlet_i = 0; tractlet_i < tractlets.size(); ++tractlet_i) { + + tractlets[tractlet_i][0][0] = centres[tractlet_i]; + tractlets[tractlet_i][0][1] = orients[tractlet_i]; + + if (curve_stddev) + tractlets[tractlet_i][0][2] = rand_triple(curve_stddev,rand_gen); + + //Get width axes perpendicular to the main orientation and each other. + Triple ax1 = orients[tractlet_i].cross(orients[tractlet_i].min_axis()).normalise(); + Triple ax2 = orients[tractlet_i].cross(ax1).normalise(); + + //Scale width axes by width parameter + tractlets[tractlet_i][1][0] = ax1 * (width_mean + gsl_ran_gaussian(rand_gen, width_stddev)); + tractlets[tractlet_i][2][0] = ax2 * (width_mean + gsl_ran_gaussian(rand_gen, width_stddev)); + + if (acs >= 0.0) + tractlets[tractlet_i].set_acs(acs); + + } + + tractlets.save(output_location); + + } else + throw Exception ("Unrecognised file extension '" + File::extension(output_location) + "'."); + +} + + +//Randomly generate centre points within the region of interest +std::vector< Triple > distributed_centres(const Triple& roi_extent, size_t num_fibres, gsl_rng* rand_gen, double reject_radius) { + + std::vector< Triple > points; + + for (size_t fibre_i = 0; fibre_i < num_fibres; ++fibre_i) { + + Triple centre; + + bool accept = false; + + for (size_t attempt_i = 0; attempt_i < MAX_NUM_ATTEMPTS; ++attempt_i) { + + for (size_t dim_i = 0; dim_i < 3; ++dim_i) + centre[dim_i] = gsl_ran_flat(rand_gen, -roi_extent[Z], roi_extent[Z]); + + bool reject = false; + + for (size_t point_i = 0; point_i < points.size(); ++point_i) + if (dist(centre,points[point_i]) < reject_radius) { + reject = true; + break; + } + + + if (!reject) { + accept = true; + break; + } + + } + + if (accept) + points.push_back(centre); + else + throw Exception ("Could not find centre position for fibre " + str(fibre_i) + + " that lies outside the rejection radius of previously generated fibre centres after " + + str(MAX_NUM_ATTEMPTS) + ". Suggest reducing the reject_radius (" + str(reject_radius) + ")."); + + } + + + return points; + +} + + +std::vector< Triple > distant_centres(size_t num_fibres, double centre_radius, gsl_rng* rand_gen) { + + std::vector< Triple > points; + + for (size_t fibre_i = 0; fibre_i < num_fibres; ++fibre_i) { + + Triple point = rand_triple(1.0,rand_gen); + + point.normalise(); + + point *= centre_radius; + + points.push_back(point); + + } + + return points; + +} + +//Randomly generate orientations +std::vector< Triple > orientations(size_t num_fibres, gsl_rng* rand_gen, double length_stddev) { + + std::vector< Triple > orients; + + for (size_t fibre_i = 0; fibre_i < num_fibres; ++fibre_i) { + + Triple orient; + + for (size_t dim_i = 0; dim_i < 3; ++dim_i) + orient[dim_i] = gsl_ran_gaussian(rand_gen, length_stddev); + + orients.push_back(orient); + + } + + return orients; + +} diff --git a/cmd/map_colours.cpp b/cmd/map_colours.cpp new file mode 100644 index 0000000..b0a8eef --- /dev/null +++ b/cmd/map_colours.cpp @@ -0,0 +1,373 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, Mar 14, 2011. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + + +#include "bts/cmd.h" + +#include "bts/common.h" + +#include "bts/fibre/tractlet/set.h" +#include "bts/fibre/strand/set.h" +#include "bts/fibre/track/set.h" + +#include "bts/inline_functions.h" + +using namespace BTS; + +SET_VERSION_DEFAULT; +SET_AUTHOR ("Thomas G. Close"); +SET_COPYRIGHT (NULL); + + +DESCRIPTION = { + "Map colours to reference set by switching bundle indices to closest match.", + "", + NULL +}; + +ARGUMENTS = { + Argument ("reference", "Reference fibres the match fibres will be mapped to.").type_file (), + Argument ("match", "Input fibres that will have their bundle indices mapped.").type_file (), + Argument ("output", "Output fibres (if not provided will be same as match fibres)").optional().type_file (), + Argument ("input", "Input fibres (if not provided will be same as match fibres)").optional().type_file (), + Argument() +}; + + +OPTIONS = { + + Option ("num_length_sections", "Number of samples to take along the strand path") + + Argument ("num_length_sections", "").type_integer (1, 100, 2000), + + Option ("degree", "The degree of the Strand coefficients used to describe the strands") + + Argument ("degree", "").type_integer (1, Fibre::Strand::DEFAULT_DEGREE, LARGE_INT), + +Option() }; + + +EXECUTE { + + std::string reference_location = argument[0]; + std::string match_location= argument[1]; + std::string output_location = match_location; + std::string input_location = match_location; + + if (argument.size() == 3) + output_location = argument[2].c_str(); + + if (argument.size() == 4) { + output_location = argument[2].c_str(); + input_location = argument[3].c_str(); + } + + size_t degree = Fibre::Strand::DEFAULT_DEGREE; +// size_t num_length_sections = 0; + + + Options opt = get_options("degree"); + if (opt.size()) + degree = opt[0][0]; + + // Options opt = get_options("num_length_sections"); + // if (opt.size()) + // num_length_sections = opt[0][0]; + + + + //TODO: Make this into a template function to avoid replication + + if (File::has_extension(match_location)) { + + Fibre::Tractlet::Set reference(reference_location, degree); + + if (!reference.size()) + throw Exception ("Reference set, loaded from '" + reference_location + "' does not contain any fibres."); + + if (!reference.has_extend_elem_prop(Fibre::Track::BUNDLE_INDEX_EPROP)) { + + std::cout << std::endl << "Warning! Reference set does not have bundle_index property, will use strand order." << std::endl; + + reference.add_extend_elem_prop(Fibre::Track::BUNDLE_INDEX_EPROP,"-1"); + for (size_t tract_i = 0; tract_i < reference.size(); ++tract_i) + reference.set_extend_elem_prop(Fibre::Track::BUNDLE_INDEX_EPROP,str(tract_i), tract_i); + + } + + std::vector bundle_indices; + + for (size_t ref_i = 0; ref_i < reference.size(); ++ref_i) + bundle_indices.push_back(to(reference.get_extend_elem_prop(Fibre::Track::BUNDLE_INDEX_EPROP, ref_i))); + + size_t new_bundle_index = *std::max_element(bundle_indices.begin(), bundle_indices.end()); + + //Check bundle indices are unique in reference set. + size_t num_bundles = bundle_indices.size(); + std::unique(bundle_indices.begin(), bundle_indices.end()); + if (bundle_indices.size() != num_bundles) + throw Exception ("Bundle indices were not unique in reference set '" + reference_location + "'."); + + + + Fibre::Tractlet::Set match(match_location); + + std::vector reference_match(match.size()); + + + if (reference.size() > match.size()) { + + MR::ProgressBar progress_bar("Getting closest match between match template and reference set..."); + + match.distance(reference, reference_match); + + } else { + + MR::ProgressBar progress_bar("Getting closest match between match template and reference set..."); + + std::vector inv_reference_match; + + reference.distance(match, inv_reference_match); + + size_t extra_index = reference.size(); + + for (size_t tract_i = 0; tract_i < match.size(); ++tract_i) { + + std::vector::iterator index = std::find(inv_reference_match.begin(), inv_reference_match.end(), tract_i); + + if (index != inv_reference_match.end()) + reference_match[tract_i] = index - inv_reference_match.begin(); + else { + reference_match[tract_i] = extra_index++; + bundle_indices.push_back(new_bundle_index++); + } + + } + + + } + + if (File::has_extension(input_location)) { + + MR::ProgressBar progress_bar("Mapping bundle indices to output set..."); + + Fibre::Tractlet::Set input; + + if (input_location != match_location) { + input.load(input_location); + if (input.size() != match.size()) + throw Exception ("Size of match set (" + str(match.size()) + ") and input set (" + str(input.size()) + ") do not match."); + } else + input = match; + + if (!match.has_extend_elem_prop(Fibre::Track::BUNDLE_INDEX_EPROP)) + input.add_extend_elem_prop(Fibre::Track::BUNDLE_INDEX_EPROP, "-1"); + + for (size_t tract_i = 0; tract_i < match.size(); ++tract_i) { + + input.set_extend_elem_prop(Fibre::Track::BUNDLE_INDEX_EPROP, str(bundle_indices[reference_match[tract_i]]), tract_i); + + ++progress_bar; + } + + input.save(output_location); + + + } else if (File::has_extension(input_location)) { + + MR::ProgressBar progress_bar("Mapping bundle indices to output set..."); + + if (input_location == output_location) + throw Exception ("Output location ('" + output_location + "') cannot be the same as input location ('" + input_location + "') for tractlet sets."); + + Fibre::Tractlet::Set::Reader reader(input_location); + + std::vector elem_header = reader.extend_elem_prop_keys(); + + if (std::find(elem_header.begin(), elem_header.end(), Fibre::Track::BUNDLE_INDEX_EPROP) == elem_header.end()) + elem_header.push_back(Fibre::Track::BUNDLE_INDEX_EPROP); + + Fibre::Tractlet::Set::Writer writer(output_location, reader, reader.extend_prop_keys(), elem_header, reader.get_extend_props()); + + Fibre::Tractlet::Set tractlets; + + size_t count = 0; + while (reader.next(tractlets)) { + + if (tractlets.size() != match.size()) + throw Exception ("Size of tractlet set " + str(count) + " (" + str(tractlets.size()) + ") does not match that of 'match' set (" + str(match.size()) + ")"); + + tractlets.add_extend_elem_prop(Fibre::Track::BUNDLE_INDEX_EPROP, "-1"); + + for (size_t tract_i = 0; tract_i < tractlets.size(); ++tract_i) + tractlets.set_extend_elem_prop(Fibre::Track::BUNDLE_INDEX_EPROP, str(bundle_indices[reference_match[tract_i]]), tract_i); + + writer.append(tractlets); + ++count; + ++progress_bar; + + } + + + } else + throw Exception ("Usupported output file type ('" + output_location + "') for match of type tractlet."); + + + + } else if (File::has_extension(match_location)) { + + Fibre::Strand::Set reference(reference_location, degree); + + if (!reference.size()) + throw Exception ("Reference set, loaded from '" + reference_location + "' does not contain any fibres."); + + if (!reference.has_extend_elem_prop(Fibre::Track::BUNDLE_INDEX_EPROP)) { + + std::cout << std::endl << "Warning! Reference set does not have bundle_index property, will use strand order." << std::endl; + + reference.add_extend_elem_prop(Fibre::Track::BUNDLE_INDEX_EPROP,"-1"); + for (size_t tract_i = 0; tract_i < reference.size(); ++tract_i) + reference.set_extend_elem_prop(Fibre::Track::BUNDLE_INDEX_EPROP,str(tract_i), tract_i); + + } + std::vector bundle_indices; + + for (size_t ref_i = 0; ref_i < reference.size(); ++ref_i) + bundle_indices.push_back(to(reference.get_extend_elem_prop(Fibre::Track::BUNDLE_INDEX_EPROP, ref_i))); + + size_t new_bundle_index = *std::max_element(bundle_indices.begin(), bundle_indices.end()); + + //Check bundle indices are unique in reference set. + size_t num_bundles = bundle_indices.size(); + std::unique(bundle_indices.begin(), bundle_indices.end()); + if (bundle_indices.size() != num_bundles) + throw Exception ("Bundle indices were not unique in reference set '" + reference_location + "'."); + + + + Fibre::Strand::Set match(match_location); + + std::vector reference_match(match.size()); + + + if (reference.size() > match.size()) { + + MR::ProgressBar progress_bar("Getting closest match between match template and reference set..."); + + match.distance(reference, reference_match); + + } else { + + MR::ProgressBar progress_bar("Getting closest match between match template and reference set..."); + + std::vector inv_reference_match; + + reference.distance(match, inv_reference_match); + + size_t extra_index = reference.size(); + + for (size_t tract_i = 0; tract_i < match.size(); ++tract_i) { + + std::vector::iterator index = std::find(inv_reference_match.begin(), inv_reference_match.end(), tract_i); + + if (index != inv_reference_match.end()) + reference_match[tract_i] = index - inv_reference_match.begin(); + else { + reference_match[tract_i] = extra_index++; + bundle_indices.push_back(new_bundle_index++); + } + + } + + + } + + if (File::has_extension(input_location)) { + + MR::ProgressBar progress_bar("Mapping bundle indices to output set..."); + + Fibre::Strand::Set input; + + if (input_location != match_location) { + input.load(input_location); + if (input.size() != match.size()) + throw Exception ("Size of match set (" + str(match.size()) + ") and input set (" + str(input.size()) + ") do not match."); + } else + input = match; + + if (!match.has_extend_elem_prop(Fibre::Track::BUNDLE_INDEX_EPROP)) + input.add_extend_elem_prop(Fibre::Track::BUNDLE_INDEX_EPROP, "-1"); + + for (size_t tract_i = 0; tract_i < match.size(); ++tract_i) { + + input.set_extend_elem_prop(Fibre::Track::BUNDLE_INDEX_EPROP, str(bundle_indices[reference_match[tract_i]]), tract_i); + + ++progress_bar; + } + + input.save(output_location); + + + } else if (File::has_extension(input_location)) { + + MR::ProgressBar progress_bar("Mapping bundle indices to output set..."); + + if (input_location == output_location) + throw Exception ("Output location ('" + output_location + "') cannot be the same as input location ('" + input_location + "') for tractlet sets."); + + Fibre::Strand::Set::Reader reader(input_location); + + std::vector elem_header = reader.extend_elem_prop_keys(); + + if (std::find(elem_header.begin(), elem_header.end(), Fibre::Track::BUNDLE_INDEX_EPROP) == elem_header.end()) + elem_header.push_back(Fibre::Track::BUNDLE_INDEX_EPROP); + + Fibre::Strand::Set::Writer writer(output_location, reader, reader.extend_prop_keys(), elem_header, reader.get_extend_props()); + + Fibre::Strand::Set tractlets; + + size_t count = 0; + while (reader.next(tractlets)) { + + if (tractlets.size() != match.size()) + throw Exception ("Size of tractlet set " + str(count) + " (" + str(tractlets.size()) + ") does not match that of 'match' set (" + str(match.size()) + ")"); + + tractlets.add_extend_elem_prop(Fibre::Track::BUNDLE_INDEX_EPROP, "-1"); + + for (size_t tract_i = 0; tract_i < tractlets.size(); ++tract_i) + tractlets.set_extend_elem_prop(Fibre::Track::BUNDLE_INDEX_EPROP, str(bundle_indices[reference_match[tract_i]]), tract_i); + + writer.append(tractlets); + ++count; + ++progress_bar; + + } + + + } else + throw Exception ("Usupported output file type ('" + output_location + "') for match of type tractlet."); + + + + } else + throw Exception ("Unsupported extension of match file '" + match_location+ "'."); + + +} diff --git a/cmd/maxb0.cpp b/cmd/maxb0.cpp new file mode 100644 index 0000000..249c4fa --- /dev/null +++ b/cmd/maxb0.cpp @@ -0,0 +1,81 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + + +extern "C" { +#include +#include +} + + +#include "bts/cmd.h" +#include "progressbar.h" + +#include "bts/common.h" +#include "bts/image/expected/buffer.h" +#include "bts/image/observed/buffer.h" + +#include "bts/image/noise.h" +#include "bts/image/noise/gaussian.h" + + + +#include "bts/inline_functions.h" + +using namespace BTS; + +SET_VERSION_DEFAULT; +SET_AUTHOR ("Thomas G. Close"); +SET_COPYRIGHT (NULL); + +DESCRIPTION = { + "Finds the maximum b0 intensity of an image", + "", + NULL +}; + +ARGUMENTS = { + Argument ("image", "The image.").type_file(), + + Argument() +}; + + +OPTIONS = { + +Option() + +}; + + + +EXECUTE { + + std::string input_location = argument[0]; + + Image::Observed::Buffer image(input_location); + + std::cout << image.max_b0(); + +} + + diff --git a/cmd/merge_fibres.cpp b/cmd/merge_fibres.cpp new file mode 100644 index 0000000..8b980ec --- /dev/null +++ b/cmd/merge_fibres.cpp @@ -0,0 +1,400 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Written by Thomas G. Close, 04/03/2009. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + +#include "bts/cmd.h" +#include "point.h" +#include "progressbar.h" + +#include "bts/common.h" +#include "bts/file.h" + + +#include "bts/fibre/strand/set.h" +#include "bts/fibre/track/set.h" +#include "bts/fibre/tractlet/set.h" +#include "bts/fibre/properties/extended.h" + + +#include "bts/diffusion/model.h" +#include "bts/image/expected/trilinear/buffer.h" +#include "bts/image/expected/gaussian/buffer.h" +#include "bts/image/expected/quartic/buffer.h" + +#include "bts/prob/uniform.h" +#include "bts/prob/prior.h" + + + + +#include "bts/math/common.h" + +#include "bts/prob/likelihood.h" +#include "bts/prob/likelihood.h" +#include "bts/prob/likelihood/one_sided_gaussian.h" +#include "bts/prob/likelihood/gaussian.h" + +#include "bts/image/observed/buffer.h" + +#include "bts/image/expected/buffer.h" + +#include "bts/math/blossom.h" +#include "bts/math/blossom/edge.h" + + +#include "bts/inline_functions.h" + + +using namespace BTS; + +const double THRESHOLD_DEFAULT = -0.5; +const size_t NUM_LENGTH_SECTIONS_DEFAULT=5; + +SET_VERSION_DEFAULT; +SET_AUTHOR ("Thomas G. Close"); +SET_COPYRIGHT (NULL); + +DESCRIPTION = { + "Merge strands that can be better represented by a single strand", + "", + NULL +}; + +ARGUMENTS = { + Argument ("observed image", "The observed image the strands will be fit against.").type_image_in (), + Argument ("input", "The strands to be selected from.").type_file (), + Argument ("output", "The selected strands.").type_file (), + Argument() +}; + + +OPTIONS = { + + Option ("threshold","Threshold above which to strands will be merged together.") + + Argument ("","").type_float (-1, Fibre::Tractlet::STRANDS_PER_AREA_DEFAULT, LARGE_FLOAT), + + Option ("strands_per_acs","Basewidth of the imported tractlets.") + + Argument ("","").type_float (-1, THRESHOLD_DEFAULT, LARGE_FLOAT), + + Option ("num_tractlets", "Number of tractlets to convert the strands into if outputting tractlets (default to number of input tractlets") + + Argument ("num_tractlets", "").type_integer (0, 0, LARGE_INT), + + Option ("num_length_sections", "Number of samples to take along the strand path") + + Argument ("num_length_sections", "").type_integer (1, NUM_LENGTH_SECTIONS_DEFAULT, LARGE_INT), + + Option ("new_degree", "The degree the merged strands will have") + + Argument ("new_degree", "").type_integer (1, Fibre::Strand::DEFAULT_DEGREE, LARGE_INT), + + DIFFUSION_PARAMETERS, + + IMAGE_PARAMETERS, + + EXPECTED_IMAGE_PARAMETERS, + + LIKELIHOOD_PARAMETERS, + + PRIOR_PARAMETERS, + +Option() }; + + +EXECUTE { + + std::string obs_image_location = argument[0]; + std::string input_location = argument[1]; + std::string output_location = argument[2]; + + + + MR::Image::Header header (argument[0]); + + if (header.ndim() != 4) + throw Exception ("dwi image should contain 4 dimensions"); + + + float threshold = THRESHOLD_DEFAULT; + float strands_per_acs = Fibre::Tractlet::STRANDS_PER_AREA_DEFAULT; + size_t num_tractlets = 0; + size_t num_length_sections = NUM_LENGTH_SECTIONS_DEFAULT; + size_t new_degree = Fibre::Strand::DEFAULT_DEGREE; + + Options opt = get_options("threshold"); + if (opt.size()) + threshold = opt[0][0]; + + opt = get_options("strands_per_acs"); + if (opt.size()) + strands_per_acs = opt[0][0]; + + opt = get_options("num_tractlets"); + if (opt.size()) + num_tractlets = opt[0][0]; + + opt = get_options("num_length_sections"); + if (opt.size()) + num_length_sections = opt[0][0]; + + opt = get_options("new_degree"); + if (opt.size()) + new_degree = opt[0][0]; + + + // Loads parameters to construct Diffusion::Model ('diff_' prefix) + SET_DIFFUSION_PARAMETERS; + + // Loads parameters to construct Image::Expected::*::Buffer that are inherited from Image::Observed::Buffer ('img_' prefix) + SET_IMAGE_PARAMETERS; + + // Loads parameters to construct Image::Expected::*::Buffer ('img_' prefix) + SET_EXPECTED_IMAGE_PARAMETERS; + + // Loads parameters to construct Prob::Likelihood ('like_' prefix) + SET_LIKELIHOOD_PARAMETERS; + + // Loads parameters to construct Prob::Prior ('prior_' prefix) + SET_PRIOR_PARAMETERS; + + + + Image::Observed::Buffer obs_image(obs_image_location, Diffusion::Encoding::Set(diff_encodings)); + + if (obs_image.properties().count("diff_response_SH")) { + + if (Math::matlab_str(diff_response_SH) != obs_image.properties()["diff_response_SH"]) + std::cout << std::endl << "Warning! Diffusion response function harmonics (" << Math::matlab_str(diff_response_SH) << ") do not match reference image (" << obs_image.properties()["diff_response_SH"] + ")!" << std::endl; + + } + + + //If gradient scheme is included in reference image header, use that instead of default (NB: Will override any gradients passed to '-diff_encodings' option). + if (header.get_DW_scheme().rows()) { + diff_encodings = header.get_DW_scheme(); + diff_encodings_location = "From observed image"; + } + + + if ((header.count("diff_response_SH")) && (Math::matlab_str(diff_response_SH) != header["diff_response_SH"])) + std::cout << std::endl << "Warning! Diffusion response function harmonics (" << Math::matlab_str(diff_response_SH) << ") do not match reference image (" << header["diff_response_SH"] + ")!" << std::endl; + + + + //----------------------------// + // Initialize Expected Image // + //----------------------------// + + + Diffusion::Model diffusion_model = Diffusion::Model::factory (diff_encodings, + diff_response_SH, + diff_adc, + diff_fa, + diff_isotropic); + + + Image::Expected::Buffer& exp_image = *Image::Expected::Buffer::factory(exp_type, + obs_image, + diffusion_model, + exp_num_length_sections, + exp_num_width_sections, + exp_interp_extent, + exp_enforce_bounds, + exp_half_width); + + Image::Expected::Buffer& diff_image = *exp_image.clone(); + + //-----------------------// + // Initialize Likelihood // + //-----------------------// + + + Prob::Likelihood* likelihood = Prob::Likelihood::factory(like_type, obs_image, &exp_image, like_snr, like_b0_include, like_outside_scale, like_ref_b0, like_ref_signal); + + + + //------------------// + // Initialize Prior // + //------------------// + + Prob::Prior prior (prior_scale, + prior_mag_scale, + prior_mag_aux_scale, + prior_hook_scale, + prior_hook_num_points, + prior_density_high_scale, + prior_density_low_scale, + prior_density_num_points, + prior_acs_scale, + prior_acs_mean, + prior_length_scale, + prior_length_mean); + + + Fibre::Strand::Set strands(input_location,strands_per_acs); + + if (exp_base_intensity <= 0) + exp_base_intensity = exp_image.base_intensity_default(obs_image, strands); + + strands.save("/home/tclose/data/input_strands.str"); + + strands.set_base_intensity(exp_base_intensity); + + if ((num_tractlets == 0) && strands.has_extend_prop(Fibre::Strand::Set::ORIGINAL_NUM_TRACTLETS_PROP)) + num_tractlets = to(strands.get_extend_prop(Fibre::Strand::Set::ORIGINAL_NUM_TRACTLETS_PROP)); + + exp_image.expected_image(strands); + + + obs_image.save("/home/tclose/data/orig_observed.mif"); + exp_image.save("/home/tclose/data/orig_expected.mif"); + + double orig_like = likelihood->log_prob(strands); + + std::set edges; + + MR::ProgressBar progress_bar ("Calculating merge weights...", strands.size()); + + for (size_t row_i = 0; row_i < strands.size(); ++row_i) { + for (size_t col_i = row_i+1; col_i < strands.size(); ++col_i) { + + bool same_bundle = false; + + if (strands.has_extend_elem_prop(Fibre::Track::BUNDLE_INDEX_EPROP)) + if (to(strands.get_extend_elem_prop(Fibre::Track::BUNDLE_INDEX_EPROP,row_i)) == to(strands.get_extend_elem_prop(Fibre::Track::BUNDLE_INDEX_EPROP,col_i))) + same_bundle = true; + + if (!same_bundle) { + + Fibre::Strand row_strand = strands[row_i]; + Fibre::Strand col_strand = strands[col_i]; + + Fibre::Strand merged = row_strand.merge(col_strand, num_length_sections, new_degree); + + diff_image.zero(); + diff_image.part_image(row_strand); + + diff_image.part_image(col_strand); + + diff_image.negate(); + + diff_image.part_image(merged); + + exp_image += diff_image; + + //The distance measure. The original prior is averaged by number of strands, and the merged prior and likelihood + //are subtracted from it so that unlikely matches are assigned a large distance. + + double orig_prior = prior.log_prob(row_strand) + prior.log_prob(col_strand); + double merged_prior = prior.log_prob(merged); + double merged_like = likelihood->log_prob(exp_image); + +// exp_image.save("/home/tclose/data/merged_expected.mif"); + + double diff_lprob = (merged_prior - orig_prior) + (merged_like - orig_like); + + //If difference in log prob is greater than zero. i.e. if merging improves probability add to list of edges to + //find the best fit. + +// if (!(row_i == 3 && col_i == 8)) + if (diff_lprob > 0) + edges.insert(Math::Blossom::Edge(row_i,col_i,-diff_lprob)); + + exp_image -= diff_image; + + } + + + } + + ++progress_bar; + } + + + std::vector merge_list; + + for (std::set::iterator edge_it = edges.begin(); edge_it !=edges.end();) { + + merge_list.push_back(*edge_it); + + std::set::iterator edge_it2 = edge_it; + + ++edge_it2; + + while (edge_it2 != edges.end()) + if (edge_it2->has_node(edge_it->first) || edge_it2->has_node(edge_it->second)) + edges.erase(edge_it2++); + else + ++edge_it2; + + edges.erase(edge_it++); + } + + + std::set not_merge_list; + + for (size_t strand_i = 0; strand_i < strands.size(); ++strand_i) + not_merge_list.insert(strand_i); + + double expected_improvement = 0; + + std::cout << std::endl; + + for (std::vector::iterator merge_it = merge_list.begin(); merge_it != merge_list.end(); ++merge_it) { + not_merge_list.erase(merge_it->first); + not_merge_list.erase(merge_it->second); + expected_improvement -= merge_it->weight; + std::cout << merge_it->first << " " << merge_it->second << ": " << - merge_it->weight << std::endl; + } + + + Fibre::Strand::Set merged; + + for (std::vector::iterator merge_it = merge_list.begin(); merge_it != merge_list.end(); ++merge_it) { + merged.push_back(strands[merge_it->first].merge(strands[merge_it->second], num_length_sections, new_degree)); + } + + for (std::set::iterator not_merge_it = not_merge_list.begin(); not_merge_it != not_merge_list.end(); ++not_merge_it) { + Fibre::Strand strand = strands[*not_merge_it]; + strand.resize(new_degree,0.0); + merged.push_back(strand); + + } + + + double improvement = likelihood->log_prob(merged) + prior.log_prob(merged) - likelihood->log_prob(strands) - prior.log_prob(strands); + + merged.save("/home/tclose/data/merged.str"); + +// if (improvement > 0) { + merged.save(output_location,0,num_tractlets); + std::cout << "\n\nMerged " << merge_list.size() << " strand pairs for a combined improvement of the posterior of " << improvement << " (" << expected_improvement << " expected) over the original set." << std::endl; +// } else { +// strands.save(output_location,0,num_tractlets); +// std::cout << "\n\nNo improvement could be found from the original set." << std::endl; +// } + + + } + +//} + + + + + diff --git a/cmd/metropolis.cpp b/cmd/metropolis.cpp new file mode 100644 index 0000000..309e999 --- /dev/null +++ b/cmd/metropolis.cpp @@ -0,0 +1,571 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + + +extern "C" { +#include +#include +} + + +#include + +#include "bts/cmd.h" + +#include "math/matrix.h" +#include "progressbar.h" + + +#include "bts/common.h" +#include "bts/file.h" + + +#include "bts/fibre/tractlet/set.h" +#include "bts/fibre/strand/set.h" + + +#include "bts/diffusion/model.h" +#include "bts/image/expected/trilinear/buffer.h" +#include "bts/image/expected/gaussian/buffer.h" +#include "bts/image/expected/quartic/buffer.h" + +#include "bts/image/observed/buffer.h" + +#include "bts/prob/uniform.h" +#include "bts/prob/prior.h" + + + + + +#include "bts/prob/likelihood.h" +#include "bts/prob/likelihood.h" +#include "bts/prob/likelihood/one_sided_gaussian.h" +#include "bts/prob/likelihood/gaussian.h" + +#include "bts/mcmc/proposal/walker.h" +#include "bts/mcmc/proposal/distribution.h" +#include "bts/mcmc/proposal/distribution/gaussian.h" + +#include "bts/mcmc/metropolis.h" + +#include "bts/fibre/strand/set/walker.h" +#include "bts/fibre/tractlet/set/walker.h" + +#include "bts/math/common.h" + + +#include "bts/inline_functions.h" + +using namespace BTS; + + + +SET_VERSION_DEFAULT; +SET_AUTHOR ("Thomas G. Close"); +SET_COPYRIGHT (NULL); + +DESCRIPTION = { + "Runs Metropolis-Hastings sampling on a given image from a given starting configuration of tractlets or strands.", + "", + NULL +}; + +ARGUMENTS = { + Argument ("input_image", "The image the tractlets will be fit against.").type_image_in(), + + Argument ("inital_tractlets", "A starting point for the MCMC algorithm.").type_file (), + + Argument ("samples_location", "The location where the samples will be saved.").type_file (), + + Argument() +}; + + +OPTIONS = { + + + Option ("num_iterations", "The Number of MCMC iterations to take of the prob distribution over the tractlets") + + Argument ("num_iterations", "").type_integer (1, MCMC::Metropolis::NUM_ITERATIONS_DEFAULT, LARGE_INT), + + Option ("sample_period", "The number of MCMC iterations that will be performed before a sample is saved") + + Argument ("sample_period", "").type_integer (1, MCMC::Metropolis::SAMPLE_PERIOD_DEFAULT, LARGE_INT), + + Option ("burn_num_iterations", "The Number of MCMC iterations to take as part of the Burn-in.") + + Argument ("burn_num_iterations", "").type_integer (0, MCMC::Metropolis::BURN_NUM_ITERATIONS_DEFAULT, LARGE_INT), + + Option ("burn_sample_period", "The number of MCMC iterations that will be performed before a sample is saved in the Burn-in.") + + Argument ("burn_sample_period", "").type_integer (1, MCMC::Metropolis::BURN_SAMPLE_PERIOD_DEFAULT, LARGE_INT), + + Option ("burn_enforce_bounds", "Enforce the image bounds during the burn-in period. Otherwise the signal outside the image expected, given the fibre configuration will be recorded and its likelihood compared with empty (isotropic) intensities."), + + Option("anneal_frac_start", "Over the burn-in period annealing can be simulated via linear linear cooling specified by a scalar fraction that begins a defined value and linearly increases to 1.0.") + + Argument("anneal_frac_start","").type_float(0.0, MCMC::Metropolis::ANNEAL_FRAC_START_DEFAULT, 1.0), + + Option ("seed", "The random seed that is passed to the random generator") + + Argument ("seed", ""), + + Option ("prior_only", "Only sample from the prior distribution."), + + Option ("unverbose", "Turn off verbose output of sampling."), + + Option ("save_images", "Save both observed and expected images for debugging."), + + DIFFUSION_PARAMETERS, + + EXPECTED_IMAGE_PARAMETERS, + + LIKELIHOOD_PARAMETERS, + + PRIOR_PARAMETERS, + + PROPOSAL_WALKER_PARAMETERS, + + PROPOSAL_DISTRIBUTION_PARAMETERS, + + COMMON_PARAMETERS, + +Option() }; + + + + +EXECUTE { + +//-----------------// +// Load Arguments // +//-----------------// + + std::string obs_image_location = argument[0]; + std::string initial_location = argument[1]; + std::string samples_location = argument[2]; + std::string burn_samples_location = File::strip_extension (samples_location) + ".burn." + File::extension(samples_location); + + + + MR::Image::Header header (argument[0]); + + if (header.ndim() != 4) + throw Exception ("dwi image should contain 4 dimensions"); + + + +//----------------------------------// +// Get and Set Optional Parameters // +//----------------------------------// + + size_t num_iterations = MCMC::Metropolis::NUM_ITERATIONS_DEFAULT; + size_t sample_period = MCMC::Metropolis::SAMPLE_PERIOD_DEFAULT; + size_t burn_num_iterations = MCMC::Metropolis::BURN_NUM_ITERATIONS_DEFAULT; + size_t burn_sample_period = MCMC::Metropolis::BURN_SAMPLE_PERIOD_DEFAULT; + bool burn_enforce_bounds = false; + double anneal_frac_start = MCMC::Metropolis::ANNEAL_FRAC_START_DEFAULT; + size_t seed = time(NULL); + bool prior_only = false; + bool verbose = true; + bool save_images = false; + + + + Options opt = get_options("num_iterations"); + if (opt.size()) + num_iterations = opt[0][0]; + + opt = get_options("sample_period"); + if (opt.size()) + sample_period = opt[0][0]; + + opt = get_options("burn_num_iterations"); + if (opt.size()) + burn_num_iterations = opt[0][0]; + + opt = get_options("burn_sample_period"); + if (opt.size()) + burn_sample_period = opt[0][0]; + + opt = get_options("burn_enforce_bounds"); + if (opt.size()) + burn_enforce_bounds = true; + + opt = get_options("anneal_frac_start"); + if (opt.size()) + anneal_frac_start = opt[0][0]; + + opt = get_options("seed"); + if (opt.size()) { + std::string seed_string = opt[0][0]; + seed = to(seed_string); + } else + std::cout << "No random seed supplied. Using timestamp: " << seed << std::endl; + + opt = get_options("prior_only"); + if (opt.size()) + prior_only = true; + + opt = get_options("unverbose"); + if (opt.size()) + verbose = false; + + opt = get_options("save_images"); + if (opt.size()) + save_images = true; + + // Loads parameters to construct Diffusion::Model ('diff_' prefix) + SET_DIFFUSION_PARAMETERS; + + // Loads parameters to construct Image::Expected::*::Buffer ('img_' prefix) + SET_EXPECTED_IMAGE_PARAMETERS; + + // Loads parameters to construct Prob::Likelihood ('like_' prefix) + SET_LIKELIHOOD_PARAMETERS; + + // Loads parameters to construct Prob::Prior ('prior_' prefix) + SET_PRIOR_PARAMETERS; + + // Loads parameters to construct Proposal::Distribution ('walk_' prefix) + SET_PROPOSAL_WALKER_PARAMETERS(initial_location); + + // Loads parameters to construct Proposal::Distribution ('walk_' prefix) + SET_PROPOSAL_DISTRIBUTION_PARAMETERS; + + // Loads parameters that are common to all commands. + SET_COMMON_PARAMETERS; + + + //--------------------------------// + // Set up reference image buffer // + //--------------------------------// + + Image::Observed::Buffer obs_image(obs_image_location, Diffusion::Encoding::Set(diff_encodings)); + + //If gradient scheme is included in reference image header, use that instead of default (NB: Will override any gradients passed to '-diff_encodings' option). + if (header.get_DW_scheme().rows()) { + diff_encodings = header.get_DW_scheme(); + diff_encodings_location = "From observed image"; + } + + + if ((header.count("diff_response_SH")) && (Math::matlab_str(diff_response_SH) != header["diff_response_SH"])) + std::cout << std::endl << "Warning! Diffusion response function harmonics (" << Math::matlab_str(diff_response_SH) << ") do not match reference image (" << header["diff_response_SH"] + ")!" << std::endl; + + + //----------------------------// + // Initialize Expected Image // + //----------------------------// + + + + Diffusion::Model diffusion_model = Diffusion::Model::factory (diff_encodings, + diff_response_SH, + diff_adc, + diff_fa, + diff_isotropic); + + Image::Expected::Buffer* exp_image = Image::Expected::Buffer::factory(exp_type, + obs_image, + diffusion_model, + exp_num_length_sections, + exp_num_width_sections, + exp_interp_extent, + exp_enforce_bounds, + exp_half_width); + + //----------------------------------------------------------------// + // Auto-generate base acs initial value/b_intens_gauss_mean // + //----------------------------------------------------------------// + + if (exp_base_intensity < 0) + exp_base_intensity = exp_image->base_intensity_default(obs_image, initial_location); + + + //-----------------------// + // Initialize Likelihood // + //-----------------------// + + Prob::Likelihood* likelihood = Prob::Likelihood::factory(like_type, obs_image, exp_image, like_snr, like_b0_include, like_outside_scale, like_ref_b0, like_ref_signal); + + + + //----------------------// + // Initialize Proposals // + //----------------------// + + gsl_rng* rand_gen = gsl_rng_alloc(gsl_rng_taus); + gsl_rng_set(rand_gen, seed); + + + MCMC::Proposal::Distribution *proposal_distribution = MCMC::Proposal::Distribution::factory(prop_distr_type, rand_gen); + +// +// Proposal::Intensity* acs_proposer = Proposal::Intensity::factory(walk_intens_type, proposal_distribution, walk_intens_scale); +// +// Proposal::BaseIntensity* base_intensity_proposer = Proposal::BaseIntensity::factory(walk_base_intens_type, proposal_distribution, walk_base_intens_scale); + + + + //-------------------------// + // Set Output Properties // + //-------------------------// + + std::map run_properties; + + run_properties["Method"] = "metropolis"; + run_properties["sample_period"] = str(sample_period); + run_properties["seed"] = str(seed); + run_properties["burn_sample_period"] = str(burn_sample_period); + run_properties["burn_num_iterations"] = str(burn_num_iterations); + run_properties["obs_image"] = obs_image_location; + run_properties["initial_state"] = Fibre::Base::Object::load_matlab_str(initial_location); + run_properties["initial_state_location"]= initial_location; + run_properties["prior_only"] = str(prior_only); + run_properties["num_iterations"] = str(num_iterations); + run_properties["burn_enforce_bounds"] = str(burn_enforce_bounds); + run_properties["anneal_frac_start"] = str(anneal_frac_start); + + + ADD_DIFFUSION_PROPERTIES(run_properties); + + ADD_LIKELIHOOD_PROPERTIES(run_properties); + + ADD_EXPECTED_IMAGE_PROPERTIES(run_properties); + + ADD_PRIOR_PROPERTIES(run_properties); + + ADD_PROPOSAL_WALKER_PROPERTIES(run_properties); + + ADD_PROPOSAL_DISTRIBUTION_PROPERTIES(run_properties); + + ADD_COMMON_PROPERTIES(run_properties); + + + Prob::Prior prior (prior_scale, + prior_mag_scale, + prior_mag_aux_scale, + prior_hook_scale, + prior_hook_num_points, + prior_density_high_scale, + prior_density_low_scale, + prior_density_num_points, + prior_acs_scale, + prior_acs_mean, + prior_length_scale, + prior_length_mean); + + + //-------------------------// + // Sampling from Strands // + //-------------------------// + + + if (File::has_extension(initial_location)) { + + + //------------------------// + // Load Initial Strands // + //------------------------// + + Fibre::Strand::Set strands (initial_location); + + strands.set_base_intensity(exp_base_intensity); + + //---------------------// + // Initialize Proposer // + //---------------------// + + Fibre::Strand::Set::Walker* walker = Fibre::Strand::Set::Walker::factory(strands, + walk_type, + walk_step_scale, + walk_step_location, + proposal_distribution, + walk_base_intens_scale); + + //------------------// + // Perform sampling // + //------------------// + + + Fibre::Strand::Set burnt_strands; + + if (burn_num_iterations) { + + + if (burn_enforce_bounds != exp_enforce_bounds) + likelihood->set_enforce_bounds(burn_enforce_bounds); + + burnt_strands = MCMC::metropolis + + ( strands, + *likelihood, + prior, + *walker, + burn_samples_location, + run_properties, + burn_num_iterations, + burn_sample_period, + rand_gen, + anneal_frac_start, + prior_only, + verbose, + save_images); + + + if (burn_enforce_bounds != exp_enforce_bounds) + likelihood->set_enforce_bounds(exp_enforce_bounds); + + + } else + burnt_strands = strands; + + + MCMC::metropolis + + (burnt_strands, + *likelihood, + prior, + *walker, + samples_location, + run_properties, + num_iterations, + sample_period, + rand_gen, + 1.0, + prior_only, + verbose, + save_images); + + + + //------------------------// + // Sampling from Tractlets // + //------------------------// + + } else if (File::has_extension(initial_location)) { + + + //-------------// + // Load Tractlets // + //-------------// + + Fibre::Tractlet::Set tractlets (initial_location); + + tractlets.set_base_intensity(exp_base_intensity); + + + //---------------------// + // Initialize Proposer // + //---------------------// + + Fibre::Tractlet::Set::Walker* walker = Fibre::Tractlet::Set::Walker::factory ( tractlets, + walk_type, + walk_step_scale, + walk_step_location, + proposal_distribution, + walk_base_intens_scale); + + + if (walk_type == "manifold") { + + Fibre::Tractlet::Set dummy (tractlets); + + //Ensures that tractlets lie on the manifold to begin with + walker->step(tractlets, dummy); + + tractlets = dummy; + + } + + + + //------------------// + // Perform sampling // + //------------------// + + Fibre::Tractlet::Set burnt_tractlets; + + if (burn_num_iterations) { + + if (burn_enforce_bounds != exp_enforce_bounds) + likelihood->set_enforce_bounds(burn_enforce_bounds); + + burnt_tractlets = MCMC::metropolis < Fibre::Tractlet::Set, + Prob::Likelihood, + Prob::Prior> ( + + tractlets, + *likelihood, + prior, + *walker, + burn_samples_location, + run_properties, + burn_num_iterations, + burn_sample_period, + rand_gen, + anneal_frac_start, + prior_only, + verbose, + save_images + ); + + if (burn_enforce_bounds != exp_enforce_bounds) + likelihood->set_enforce_bounds(exp_enforce_bounds); + + + } else + burnt_tractlets = tractlets; + + MCMC::metropolis ( + + burnt_tractlets, + *likelihood, + prior, + *walker, + samples_location, + run_properties, + num_iterations, + sample_period, + rand_gen, + 1.0, + prior_only, + verbose, + save_images + ); + + } + + + delete exp_image; + delete proposal_distribution; + delete likelihood; + + gsl_rng_free(rand_gen); + + + +} + + diff --git a/cmd/new_fibres.cpp b/cmd/new_fibres.cpp new file mode 100644 index 0000000..29ee4ba --- /dev/null +++ b/cmd/new_fibres.cpp @@ -0,0 +1,253 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, 18/06/2010. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + +#include "progressbar.h" +#include "bts/cmd.h" + +#include "bts/common.h" + +#include "bts/fibre/tractlet/set.h" +#include "bts/fibre/strand/set.h" +#include "bts/fibre/track/set.h" + + +#include "bts/inline_functions.h" + +using namespace BTS; + +const double ACS_DEFAULT = 1.0; +const double BASE_INTENSITY_DEFAULT = 0.0; +const size_t DEGREE_DEFAULT = 3; +const size_t NUM_LENGTH_SECTIONS_DEFAULT = 10; +const size_t SET_SIZE_DEFAULT = 1; +const size_t NUM_SETS_DEFAULT = 1; +const double INITIAL_VALUE_DEFAULT = 0.0; + +SET_VERSION_DEFAULT; +SET_AUTHOR ("Thomas G. Close"); +SET_COPYRIGHT (NULL); + +DESCRIPTION = { + "Generates new fibres [sets] of arbitrary size initialised to an arbitrary value", + "", + NULL +}; + +ARGUMENTS = { + Argument ("output","Output Location"), + Argument() +}; + + +OPTIONS = { + + Option("acs","Apparrent Connection Strength (ACS) of the generated fibres.") + + Argument("acs","").type_float(SMALL_FLOAT,ACS_DEFAULT,LARGE_FLOAT), + + Option("base_intensity","Base intensity of the generated fibres.") + + Argument("base_intensity","").type_float(SMALL_FLOAT,ACS_DEFAULT,LARGE_FLOAT), + + Option("degree","The degree of the generated fibres.") + + Argument("degree","").type_integer(0,DEGREE_DEFAULT,LARGE_INT), + + Option("num_points","The degree of the generated fibres.") + + Argument("degree","").type_integer(0,NUM_LENGTH_SECTIONS_DEFAULT,LARGE_INT), + + Option("set_size","Size of the generated fibre sets.") + + Argument("set_size","").type_integer(0,SET_SIZE_DEFAULT,LARGE_INT), + + Option("num_sets","Number of generated fibre sets.") + + Argument("num_sets","").type_integer(0,NUM_SETS_DEFAULT,LARGE_INT), + + Option("initial_value","Value all the elements will be initialized to.") + + Argument("initial_value","").type_float(-INFINITY,ACS_DEFAULT,INFINITY), + + +Option() }; + + +EXECUTE { + + + std::string output_location = argument[0]; + + + double acs = 1.0; + double base_intensity = 1.0; + size_t degree = DEGREE_DEFAULT; + size_t num_points = NUM_LENGTH_SECTIONS_DEFAULT; + size_t set_size = SET_SIZE_DEFAULT; + size_t num_sets = NUM_SETS_DEFAULT; + double initial_value = INITIAL_VALUE_DEFAULT; + + + Options opt; + + opt = get_options("acs"); + if (opt.size()) + acs = opt[0][0]; + + opt = get_options("base_intensity"); + if (opt.size()) + base_intensity = opt[0][0]; + + opt = get_options("degree"); + if (opt.size()) + degree = opt[0][0]; + + opt = get_options("num_points"); + if (opt.size()) + num_points = opt[0][0]; + + opt = get_options("set_size"); + if (opt.size()) + set_size = opt[0][0]; + + opt = get_options("num_sets"); + if (opt.size()) + num_sets = opt[0][0]; + + opt = get_options("initial_value"); + if (opt.size()) + initial_value = opt[0][0]; + + + MR::ProgressBar progress_bar ("Generating new fibres..."); + + std::vector props; + if (base_intensity >= 0.0) + props.push_back(Fibre::Strand::Set::BASE_INTENSITY_PROP); + + std::vector elem_props; + if (acs >= 0.0) + elem_props.push_back(Fibre::Strand::ACS_SQRT_PROP); + + + if (File::has_or_txt_extension(output_location) || File::has_extension(output_location) || File::has_txt_extension(output_location)) { + + Fibre::Strand::Set strands(set_size, degree, props, elem_props); + + strands = initial_value; + + if (base_intensity >= 0.0) + strands.set_base_intensity(base_intensity); + + if (acs >= 0.0) + for (size_t strand_i = 0; strand_i < strands.size(); ++strand_i) + strands[strand_i].set_acs(acs); + + if (File::has_or_txt_extension(output_location)) { + + strands.save(output_location); + + } else if (File::has_extension(output_location)) { + + Fibre::Strand::Set::Writer writer(output_location, strands); + + for (size_t set_i = 0; set_i < num_sets; set_i++) + writer.append(strands); + + } else if (File::has_txt_extension(output_location)) { + + Fibre::Strand::Set::TextWriter writer(output_location, strands); + + for (size_t set_i = 0; set_i < num_sets; set_i++) + writer.append(strands); + + } else + throw Exception ("should not be able to get here."); + + } else if (File::has_or_txt_extension(output_location) || File::has_extension(output_location) || File::has_txt_extension(output_location)) { + + Fibre::Tractlet::Set tractlets(set_size, degree, props, elem_props); + + tractlets = initial_value; + + if (base_intensity >= 0.0) + tractlets.set_base_intensity(base_intensity); + + if (acs >= 0.0) + for (size_t tractlet_i = 0; tractlet_i < tractlets.size(); ++tractlet_i) + tractlets[tractlet_i].set_acs(acs); + + if (File::has_or_txt_extension(output_location)) { + + tractlets.save(output_location); + + } else if (File::has_extension(output_location)) { + + Fibre::Tractlet::Set::Writer writer(output_location, tractlets); + + for (size_t set_i = 0; set_i < num_sets; set_i++) + writer.append(tractlets); + + } else if (File::has_txt_extension(output_location)) { + + Fibre::Tractlet::Set::TextWriter writer(output_location, tractlets); + + for (size_t set_i = 0; set_i < num_sets; set_i++) + writer.append(tractlets); + + } else + throw Exception ("should not be able to get here."); + + } else if (File::has_or_txt_extension(output_location) || File::has_extension(output_location) || File::has_txt_extension(output_location)) { + + Fibre::Track::Set tcks(set_size, num_points, props, elem_props); + + tcks = initial_value; + + if (base_intensity >= 0.0) + tcks.set_base_intensity(base_intensity); + + if (acs >= 0.0) + for (size_t track_i = 0; track_i < tcks.size(); ++track_i) + tcks[track_i].set_acs(acs); + + if (File::has_or_txt_extension(output_location)) { + + tcks.save(output_location); + + } else if (File::has_extension(output_location)) { + + Fibre::Track::Set::Writer writer(output_location, tcks); + + for (size_t set_i = 0; set_i < num_sets; set_i++) + writer.append(tcks); + + } else if (File::has_txt_extension(output_location)) { + + Fibre::Track::Set::TextWriter writer(output_location, tcks); + + for (size_t set_i = 0; set_i < num_sets; set_i++) + writer.append(tcks); + + } else + throw Exception ("should not be able to get here."); + + } else + throw Exception ("Unrecognised file extension '" + File::extension(output_location) + "'."); + + + //MR::ProgressBar::done(); + +} diff --git a/cmd/noisify_image.cpp b/cmd/noisify_image.cpp new file mode 100644 index 0000000..3fa74a7 --- /dev/null +++ b/cmd/noisify_image.cpp @@ -0,0 +1,138 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + + +extern "C" { +#include +#include +} + + +#include "bts/cmd.h" +#include "progressbar.h" + +#include "bts/common.h" +#include "bts/image/expected/buffer.h" +#include "bts/image/observed/buffer.h" + +#include "bts/image/noise.h" +#include "bts/image/noise/gaussian.h" + + + +#include "bts/inline_functions.h" + +using namespace BTS; + +SET_VERSION_DEFAULT; +SET_AUTHOR ("Thomas G. Close"); +SET_COPYRIGHT (NULL); + +DESCRIPTION = { + "Selects a rectangular ROI from a larger image", + "", + NULL +}; + +ARGUMENTS = { + Argument ("initial", "The initial image the second image will be subtracted from.").type_file(), + + Argument ("output_image", "The resulting image").type_file (), + + Argument() +}; + + +OPTIONS = { + + NOISE_PARAMETERS, + + Option ("seed", "Random seed used to initialise the random generator.") + + Argument ("", "").type_float (1e-9, INFINITY, 0.1), + + +Option() + +}; + + + +EXECUTE { + + +//------------------------------// +// Load Input Image Buffer // +//------------------------------// + + + + size_t seed = time(NULL); + + Options opt; + + SET_NOISE_PARAMETERS; + + + opt = get_options("seed"); + if (opt.size()) + seed = opt[0][0]; + + +//--------------------------// +// Load Input Image Buffer // +//--------------------------// + + std::string input_location = argument[0]; + std::string output_location = argument[1]; + + Image::Observed::Buffer image(input_location); + +//------------// +// Add noise // +//------------// + + + gsl_rng* rand_gen = gsl_rng_alloc(gsl_rng_taus); + gsl_rng_set(rand_gen, seed); + + Image::Noise* noise = Image::Noise::factory(rand_gen, noise_type, noise_snr, noise_ref_signal); + + noise->noisify(image); + +//---------------------------// +// Add Properties to header // +//---------------------------// + + ADD_NOISE_PROPERTIES(image.properties()); + + image.properties()["seed"] = str(seed); + +//-------------// +// Save Image // +//-------------// + + image.save(output_location); + + +} + + diff --git a/cmd/offset_strands.cpp b/cmd/offset_strands.cpp new file mode 100644 index 0000000..22c1a78 --- /dev/null +++ b/cmd/offset_strands.cpp @@ -0,0 +1,109 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + +#include "bts/common.h" + +#include "bts/cmd.h" +#include "progressbar.h" + +#include "bts/fibre/track.h" +#include "bts/fibre/track/set.h" + + + + +#include "bts/inline_functions.h" + + +using namespace BTS; + +SET_VERSION_DEFAULT; +SET_AUTHOR ("Thomas G. Close"); +SET_COPYRIGHT (NULL); + +DESCRIPTION = { + "Trims paths to a sphere of specified radius.", + "The sections of paths that lie outside the radius of the sphere are removed and sections that reenter are split into new paths.", + NULL +}; + +ARGUMENTS = { + Argument ("input", "The tracks to be offset.").type_file (), + Argument ("output", "The returned offset tracks.").optional().type_file(), + Argument() +}; + + +OPTIONS = { + Option ("num_points", "The number of points that will be generated along the strand location") + + Argument ("num_points", "The number of points that will be generated along the strand location").type_integer (1, 100, 2000), + + Option ("offset", "Offset that will be applied to the tracks") + + Argument ("offset", "Offset that will be applied to the tracks"), + +Option() }; + + +EXECUTE { + + + std::string input_location = argument[0]; + std::string output_location; + + if (argument.size() > 1) + output_location = argument[1].c_str(); + else + output_location = input_location; + + size_t num_points = 0; + Triple offset = Triple::Zeros; + + Options opt = get_options("num_points"); + if (opt.size()) + num_points = opt[0][0]; + + opt = get_options("offset"); + if (opt.size()) + offset = parse_triple(std::string(opt[0][0])); + + BTS::Fibre::Track::Set tcks(input_location, num_points); + + + for (size_t tck_i = 0; tck_i < tcks.size(); tck_i++) + for (size_t point_i = 0; point_i < tcks[tck_i].size(); point_i++) + tcks[tck_i][point_i] += offset; + + tcks.set_extend_prop("origin offset", str(-offset)); + + tcks.save(output_location); + + //MR::ProgressBar::done(); +} + + + + + + + + + diff --git a/cmd/peel_fibres.cpp b/cmd/peel_fibres.cpp new file mode 100644 index 0000000..4f55fd2 --- /dev/null +++ b/cmd/peel_fibres.cpp @@ -0,0 +1,203 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + +#include "bts/cmd.h" + +#include "progressbar.h" + +#include "bts/common.h" + + +#include "bts/fibre/track/set.h" +#include "bts/fibre/strand/set.h" +#include "bts/fibre/tractlet/set.h" + + +#include "bts/inline_functions.h" + + +using namespace BTS; + +SET_VERSION_DEFAULT; +SET_AUTHOR ("Thomas G. Close"); +SET_COPYRIGHT (NULL); + +DESCRIPTION = { + "Peels fibres.", + "Removes all fibres that do not pass within an inner 'inclusion radius'.", + NULL +}; + +ARGUMENTS = { + Argument ("input", "The paths to be peeled.").type_file (), + Argument ("output", "The returned peeled paths.").optional().type_file(), + Argument() +}; + + +OPTIONS = { + Option ("distance", "The inner radius the paths must pass through to be included") + + Argument ("distance", "The inner radius the paths must pass through to be included").type_float (SMALL_FLOAT, 0.8, LARGE_FLOAT), + + Option ("num_length_sections", "The number of points that will be generated along the strand location if the loaded paths are strand descriptors") + + Argument ("num_length_sections", "").type_integer (1, 100, 2000), + + Option ("num_width_sections", "Number of width sections, only relevant for tractlet class.") + + Argument ("num_width_sections", "").type_integer (1, 3, 200), + + Option("cube", "Peel to cube instead of sphere."), + +Option() }; + + +EXECUTE { + + std::string input_location = argument[0]; + std::string output_location; + + if (argument.size() > 1) + output_location = argument[1].c_str(); + else + output_location = input_location; + + + double distance = 0.0; + bool cube = false; + size_t num_length_sections = 100; + size_t num_width_sections = 6; + + + Options opt = get_options("distance"); + if (opt.size()) + distance = opt[0][0]; + + opt = get_options("cube"); + if (opt.size()) + cube = true; + + opt = get_options("num_length_sections"); + if (opt.size()) + num_length_sections = opt[0][0]; + + + opt = get_options("num_width_sections"); + if (opt.size()) + num_width_sections = opt[0][0]; + + + if (File::extension(input_location) != File::extension(output_location)) + throw Exception ("Input ('" + input_location + "') and output_location ('" + output_location + "') extensions need to match."); + +//----------------------// +// Load original paths +//----------------------// + + if ( File::has_extension(input_location) || File::has_extension(input_location)) { + + Fibre::Track::Set all_tcks(input_location, num_length_sections); + + MR::ProgressBar progress_bar ("Removing tracks/strands that do not pass through centre of sphere..."); + + Fibre::Track::Set include_tcks; + + include_tcks = all_tcks.peel(distance, cube); + + include_tcks.save(output_location); + + //MR::ProgressBar::done(); + + } else if (File::has_extension(input_location)) { + + Fibre::Tractlet::Set all_tractlets(input_location); + + MR::ProgressBar progress_bar ("Removing tractlets that do not pass through centre of sphere..."); + + Fibre::Tractlet::Set include_tractlets; + + include_tractlets = all_tractlets.peel(distance, num_length_sections, num_width_sections, cube); + + include_tractlets.save(output_location); + + //MR::ProgressBar::done(); + + } else if (File::has_extension(input_location)) { + + Fibre::Strand::Set::Reader reader (input_location); + Fibre::Strand::Set::Writer writer (output_location, reader, reader.get_extend_props()); + + Fibre::Strand::Set all_strands; + std::map properties_row; + + MR::ProgressBar progress_bar ("Removing strands that do not pass through centre of sphere..."); + + while (reader.next(all_strands)) { + writer.append(all_strands.peel(distance, num_length_sections, cube)); + progress_bar++; + } + + reader.close(); + writer.close(); + + } else if (File::has_extension(input_location)) { + + Fibre::Tractlet::Set::Reader reader (input_location); + Fibre::Tractlet::Set::Writer writer (output_location, reader, reader.get_extend_props()); + + Fibre::Tractlet::Set all_tractlets; + std::map properties_row; + + MR::ProgressBar progress_bar ("Removing tractlets that do not pass through centre of sphere..."); + + while (reader.next(all_tractlets)) { + writer.append(all_tractlets.peel(distance, num_length_sections, num_width_sections, cube)); + progress_bar++; + } + + reader.close(); + writer.close(); + + } else if (File::has_extension(input_location)) { + + Fibre::Track::Set::Reader reader (input_location); + Fibre::Track::Set::Writer writer (output_location, reader, reader.get_extend_props()); + + Fibre::Track::Set all_tcks; + std::map properties_row; + + MR::ProgressBar progress_bar ("Removing tcks that do not pass through centre of sphere..."); + + while (reader.next(all_tcks)) { + writer.append(all_tcks.peel(distance, cube)); + progress_bar++; + } + + reader.close(); + writer.close(); + + } else + throw Exception ("Unrecognised extension '" + File::extension(input_location) + "'."); + +} + + + + diff --git a/cmd/perturb_fibres.cpp b/cmd/perturb_fibres.cpp new file mode 100644 index 0000000..681b13c --- /dev/null +++ b/cmd/perturb_fibres.cpp @@ -0,0 +1,226 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + +#include +#include + +#include "bts/cmd.h" +#include "progressbar.h" + +#include "bts/common.h" + + +#include "bts/fibre/strand/set.h" +#include "bts/fibre/tractlet/set.h" +#include "bts/mcmc/proposal/distribution/gaussian.h" + + + + +#include "bts/inline_functions.h" + + +using namespace BTS; + +SET_VERSION_DEFAULT; +SET_AUTHOR ("Thomas G. Close"); +SET_COPYRIGHT (NULL); + +DESCRIPTION = { + "Perturbs fibres, useful for debugging.", + "", + NULL +}; + +ARGUMENTS = { + Argument ("input", "The paths to be perturbed.").type_file (), + Argument ("output", "The output perturbed paths.").optional().type_file(), + Argument() +}; + + +OPTIONS = { + + Option ("stdev", "The base standard deviation the parameters will be perturbed by.") + + Argument ("stdev", "").type_float (SMALL_FLOAT, 0.05, LARGE_FLOAT), + + Option ("scales_location", "The relative scales of the perturbations.") + + Argument ("scales_location", "").type_file (), + + Option ("seed", "The random seed that is passed to the random generator") + + Argument ("seed", ""), + + Option("flat_position", "Use a flat distribution for a position parameters."), + +Option() }; + + +template void perturb_fibres(const std::string& input_location, + const std::string& output_location, + double stdev, + const std::string& scale_location, + gsl_rng* rand_gen, + const MR::Math::Vector& flat_mask); + +EXECUTE { + + + std::string input_location = argument[0]; + std::string output_location; + + if (argument.size() > 1) + output_location = argument[1].c_str(); + else + output_location = input_location; + + double stdev = 0.05; + std::string scales_location; + size_t seed = time(NULL); + bool flat_position = false; + + Options opt = get_options("stdev"); + if (opt.size()) + stdev = opt[0][0]; + + opt = get_options("scales_location"); + if (opt.size()) + scales_location = opt[0][0].c_str(); + + opt = get_options("seed"); + if (opt.size()) { + std::string seed_string = opt[0][0]; + seed = to(seed_string); + } else + std::cout << "No random seed supplied. Using timestamp: " << seed << std::endl; + + + opt = get_options("flat_position"); + if (opt.size()) + flat_position = true; + + +//-------------------------------// +// Setup Random number Generator // +//-------------------------------// + + + gsl_rng *rand_gen; + rand_gen = gsl_rng_alloc(gsl_rng_taus); + gsl_rng_set(rand_gen, seed); + + +//----------------------------------------------// +// Loop through paths and perturb parameters // +//----------------------------------------------// + + + if (File::has_extension(input_location)) { + + Fibre::Strand::Set mask (input_location); + + mask.zero(); + + if (flat_position) + for (size_t strand_i = 0; strand_i < mask.size(); ++strand_i) + mask[strand_i][0].set(1,1,1); + + MR::Math::Vector& vector_mask = mask; + + perturb_fibres(input_location, output_location, stdev, scales_location, rand_gen, vector_mask); + + } else if (File::has_extension(input_location)) { + + Fibre::Tractlet::Set mask (input_location); + + mask.zero(); + + if (flat_position) + for (size_t tract_i = 0; tract_i < mask.size(); ++tract_i) + mask[tract_i][0][0].set(1,1,1); + + MR::Math::Vector& vector_mask = mask; + + perturb_fibres(input_location, output_location, stdev, scales_location, rand_gen, vector_mask); + + } else + throw Exception ("Unrecognised extension '" + File::extension(input_location) + "'."); + +} + + +template void perturb_fibres(const std::string& input_location, + const std::string& output_location, + double stdev, + const std::string& scales_location, + gsl_rng* rand_gen, + const MR::Math::Vector& flat_mask) { + + typename T::Set fibres(input_location); + typename T::Set scales; + + if (scales_location.size()) { + + scales.load(scales_location); + + if (scales.size() == 1) { + T tmpl_scale = scales[0]; + scales = fibres; + + for (size_t fibre_i = 0; fibre_i < fibres.size(); ++fibre_i) + scales[fibre_i] = tmpl_scale; + + } else if (scales.size() != fibres.size()) + throw Exception ("scales' size do not match fibres."); + + } else { + + scales = fibres; + scales.set(1.0); + + } + + scales *= stdev; + + MR::Math::Vector& fibres_vector = fibres; + MR::Math::Vector& scales_vector = scales; + + if (fibres_vector.size() != scales_vector.size()) + throw Exception ("Scales vector does not match fibre vector."); + + MR::ProgressBar progress_bar ("Perturbing strands ...", fibres_vector.size()); + + for (size_t elem_i = 0; elem_i < fibres_vector.size(); elem_i++) { + if (flat_mask[elem_i]) + fibres_vector[elem_i] += (double)gsl_ran_flat(rand_gen, -scales_vector[elem_i], scales_vector[elem_i]); + else + fibres_vector[elem_i] += (double)gsl_ran_gaussian(rand_gen, scales_vector[elem_i]); + progress_bar++; + } + + + fibres.save(output_location); + + +} + + + diff --git a/cmd/project_strands.cpp b/cmd/project_strands.cpp new file mode 100644 index 0000000..9cc8cca --- /dev/null +++ b/cmd/project_strands.cpp @@ -0,0 +1,120 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + +#include "bts/cmd.h" + +#include "progressbar.h" + +#include "bts/common.h" + +#include "bts/fibre/strand/set.h" + + + + + +#include "bts/inline_functions.h" + + +using namespace BTS; + +SET_VERSION_DEFAULT; +SET_AUTHOR ("Thomas G. Close"); +SET_COPYRIGHT (NULL); + +DESCRIPTION = { + "Projects file locations to a sphere of supplied radius (defaults to 1.0).", + "Projects file locations to a sphere of supplied radius (defaults to 1.0).", + NULL +}; + +ARGUMENTS = { + Argument ("input", "The file locations to be projected.").type_file (), + Argument ("output", "The returned projected file locations.").optional().type_file(), + Argument() +}; + + +OPTIONS = { + Option ("sphere_radius", "The sphere radius the file locations will be projected onto") + + Argument ("sphere_radius", "The sphere radius the file locations will be projected onto").type_float (SMALL_FLOAT, 1.0, LARGE_FLOAT), + + + Option ("num_points", "The number of points that will be generated along the strand location") + + Argument ("points", "The number of points that will be generated along the strand location").type_integer (1, 100, 2000), + + Option ("degree", "The degree of the Strand coefficients used to describe the strands") + + Argument ("degree", "The degree of the outputted Strand coefficients").type_integer (1, 3, 200), + + + +Option() }; + + +EXECUTE { + + std::string input_location = argument[0]; + std::string output_location; + + if (argument.size() > 1) + output_location = argument[1].c_str(); + else + output_location = input_location; + + + double sphere_radius = 1.0; + size_t degree = 0; + size_t num_points = 0; + + Options opt = get_options("sphere_radius"); + if (opt.size()) + sphere_radius = opt[0][0]; + + opt = get_options("num_points"); + if (opt.size()) + num_points = opt[0][0]; + + opt = get_options("degree"); + if (opt.size()) + degree = opt[0][0]; + + + + +//----------------------// +// Load original file locations +//----------------------// + + + Fibre::Strand::Set strands(input_location, degree); + + MR::ProgressBar progress_bar ("Projecting strands onto a sphere of radius " + str (sphere_radius) + " ..."); + + strands.project_to_sphere(sphere_radius); + + strands.save(output_location, num_points); + + //MR::ProgressBar::done(); + + +} + diff --git a/cmd/random_fibres.cpp b/cmd/random_fibres.cpp new file mode 100644 index 0000000..1fb8764 --- /dev/null +++ b/cmd/random_fibres.cpp @@ -0,0 +1,175 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + + +extern "C" { +#include +#include +} + + + +#include "bts/common.h" + +#include "bts/cmd.h" +#include "progressbar.h" + + +#include "phantom/interface.h" + +#include "phantom/rand_init/rand_init.h" +#include "bts/fibre/track.h" +#include "bts/fibre/track/set.h" + + + + +#include "bts/inline_functions.h" + +const size_t DEGREE_DEFAULT = 3; +const double SPHERE_RADIUS_DEFAULT = 0.225; +const double BASE_WIDTH_DEFAULT = 0.1; +const double STRAND_RADIUS_LBOUND_DEFAULT = 0.12; +const double STRAND_RADIUS_UBOUND_DEFAULT = 0.3; +const double CONTROL_POINT_FREQUENCY_DEFAULT = 50.0; +const double STRAND_RADIUS_BUFFER_RATIO_DEFAULT = 1.12; + + +using namespace BTS; + +SET_VERSION_DEFAULT; +SET_AUTHOR ("Thomas G. Close"); +SET_COPYRIGHT (NULL); + +DESCRIPTION = { + "Trims paths to a sphere of specified radius.", + "The sections of paths that lie outside the radius of the sphere are removed and sections that reenter are split into new paths.", + NULL +}; + +ARGUMENTS = { + Argument ("output", "Random strands").type_file(), + Argument() +}; + + +OPTIONS = { + + Option ("degree", "Limit the degree of the Strand coefficients used to describe the strands to the first - degrees") + + Argument ("degree", "").type_integer (1, DEGREE_DEFAULT, 200), + + Option ("sphere_r", "The radius of the sphere the strands will be trimmed to") + + Argument ("sphere_r", "").type_float (SMALL_FLOAT, SPHERE_RADIUS_DEFAULT, LARGE_FLOAT), + + Option ("control_point_freq", "The frequency of the control-points generated between the strand's end-points") + + Argument ("control_point_freq", "").type_float (SMALL_FLOAT, CONTROL_POINT_FREQUENCY_DEFAULT, LARGE_FLOAT), + + Option ("strand_r_lbound", "The minimum strand radius") + + Argument ("strand_r_lbound", "The minimum strand radius").type_float (SMALL_FLOAT, STRAND_RADIUS_LBOUND_DEFAULT, LARGE_FLOAT), + + Option ("strand_r_ubound", "The maximum strand radius") + + Argument ("strand_r_ubound", "The maximum strand radius").type_float (SMALL_FLOAT, STRAND_RADIUS_UBOUND_DEFAULT, LARGE_FLOAT), + + Option ("strand_r_buffer_ratio", "Scales the 'buffer radius' around the endpoints of each strand that other strands cannot overlap.") + + Argument ("strand_r_buffer_ratio", "").type_float (SMALL_FLOAT, STRAND_RADIUS_BUFFER_RATIO_DEFAULT, LARGE_FLOAT), + + Option ("max_attempts", "Max. attempts to add another strand") + + Argument ("max_attempts", "").type_integer (1, 1000000, LARGE_INT), + + Option ("seed", "Seed for the random generation") + + Argument ("seed", ""), + + +Option() }; + + +EXECUTE { + + + std::string output_location = argument[0]; + + size_t degree = DEGREE_DEFAULT; + double sphere_r = SPHERE_RADIUS_DEFAULT; + double control_point_freq = CONTROL_POINT_FREQUENCY_DEFAULT; + double strand_r_lbound = STRAND_RADIUS_LBOUND_DEFAULT; + double strand_r_ubound = STRAND_RADIUS_UBOUND_DEFAULT; + double strand_r_buffer_ratio = STRAND_RADIUS_BUFFER_RATIO_DEFAULT; + size_t max_attempts = 1000000; + size_t seed = time(NULL); + + Options opt = get_options("degree"); + if (opt.size()) + degree = opt[0][0]; + + opt = get_options("sphere_r"); + if (opt.size()) + sphere_r = opt[0][0]; + + opt = get_options("control_point_freq"); + if (opt.size()) + control_point_freq = opt[0][0]; + + opt = get_options("strand_r_lbound"); + if (opt.size()) + strand_r_lbound = opt[0][0]; + + opt = get_options("strand_r_ubound"); + if (opt.size()) + strand_r_ubound = opt[0][0]; + + opt = get_options("strand_r_buffer_ratio"); + if (opt.size()) + strand_r_buffer_ratio = opt[0][0]; + + opt = get_options("max_attempts"); + if (opt.size()) + max_attempts = opt[0][0]; + + opt = get_options("seed"); + if (opt.size()) { + std::string seed_str = opt[0][0]; + seed = to(seed_str); + } + + gsl_rng* rand_gen = gsl_rng_alloc(gsl_rng_taus); + gsl_rng_set(rand_gen, seed); + + MR::ProgressBar progress_bar ("Generating random strands..."); + + Strand_collection c; + + rand_init_collection(&c, sphere_r, control_point_freq, strand_r_lbound, strand_r_ubound, strand_r_buffer_ratio, rand_gen, max_attempts, 0, NULL); + + BTS::Fibre::Track::Set tcks; + std::vector > pre_points; + std::vector > post_points; + + convert_nfg_to_mr(tcks, pre_points, post_points, &c); + + tcks.save(output_location, degree); + + //MR::ProgressBar::done(); + + std::cout << "Generated " + str(tcks.size()) + " strands." << std::endl; +} + + diff --git a/cmd/random_landscape.cpp b/cmd/random_landscape.cpp new file mode 100644 index 0000000..5a76f67 --- /dev/null +++ b/cmd/random_landscape.cpp @@ -0,0 +1,176 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, 10/09/2010. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + + +#include "bts/cmd.h" + +#include "bts/common.h" +#include "bts/prob/test/landscape.h" +#include "bts/inline_functions.h" + +using namespace BTS; + +SET_VERSION_DEFAULT; +SET_AUTHOR ("Thomas G. Close"); +SET_COPYRIGHT (NULL); + +DESCRIPTION = { + "random_peaks", + "Generates a random probability landscape", + NULL +}; + +ARGUMENTS = { + Argument ("output_location", "Location of the output file.").type_file (), + Argument() +}; + + +OPTIONS = { + + Option ("location", "") + + Argument ("location", ""), + + Option ("num_dims", "") + + Argument ("num_dims", "").type_integer (1, Prob::Test::Landscape::NUM_DIMS_DEFAULT, LARGE_INT), + + Option ("num_peaks", "") + + Argument ("num_peaks", "").type_integer (1, Prob::Test::Landscape::NUM_PEAKS_DEFAULT, LARGE_INT), + + Option ("width_mu", "") + + Argument ("width_mu", "").type_float (SMALL_FLOAT, Prob::Test::Landscape::WIDTH_MU_DEFAULT, LARGE_FLOAT), + + Option ("width_sigma", "") + + Argument ("width_sigma", "").type_float (SMALL_FLOAT, Prob::Test::Landscape::WIDTH_SIGMA_DEFAULT, LARGE_FLOAT), + + Option ("width_min", "") + + Argument ("width_min", "").type_float (SMALL_FLOAT, Prob::Test::Landscape::WIDTH_MIN_DEFAULT, LARGE_FLOAT), + + Option ("height_var", "") + + Argument ("height_var", "").type_float (SMALL_FLOAT, Prob::Test::Landscape::HEIGHT_VAR_DEFAULT, LARGE_FLOAT), + + Option ("roi_radius", "") + + Argument ("roi_radius", "").type_float (SMALL_FLOAT, Prob::Test::Landscape::ROI_RADIUS_DEFAULT, LARGE_FLOAT), + + Option ("fraction_pyramid", "") + + Argument ("fraction_pyramid", "").type_float (SMALL_FLOAT, Prob::Test::Landscape::FRACTION_PYRAMID_DEFAULT, LARGE_FLOAT), + + Option ("barrier_rate", "") + + Argument ("barrier_rate", "").type_float (SMALL_FLOAT, Prob::Test::Landscape::BARRIER_RATE_DEFAULT, LARGE_FLOAT), + + Option ("seed", "The random seed that is passed to the random generator") + + Argument ("seed", ""), + +Option() }; + + +EXECUTE { + + std::string output_location = argument[0]; + + size_t seed = time(NULL); + + Options opt; + + size_t num_dims = Prob::Test::Landscape::NUM_DIMS_DEFAULT; + size_t num_peaks = Prob::Test::Landscape::NUM_PEAKS_DEFAULT; + double width_mu = Prob::Test::Landscape::WIDTH_MU_DEFAULT; + double width_sigma = Prob::Test::Landscape::WIDTH_SIGMA_DEFAULT; + double width_min = Prob::Test::Landscape::WIDTH_MIN_DEFAULT; + double height_var = Prob::Test::Landscape::HEIGHT_VAR_DEFAULT; + double roi_radius = Prob::Test::Landscape::ROI_RADIUS_DEFAULT; + double fraction_pyramid = Prob::Test::Landscape::FRACTION_PYRAMID_DEFAULT; + double barrier_rate = Prob::Test::Landscape::BARRIER_RATE_DEFAULT; + + opt = get_options("num_dims"); + if (opt.size()) + num_dims = opt[0][0]; + + opt = get_options("num_peaks"); + if (opt.size()) + num_peaks = opt[0][0]; + + opt = get_options("width_mu"); + if (opt.size()) + width_mu = opt[0][0]; + + opt = get_options("width_sigma"); + if (opt.size()) + width_sigma = opt[0][0]; + + opt = get_options("width_min"); + if (opt.size()) + width_min = opt[0][0]; + + opt = get_options("height_var"); + if (opt.size()) + height_var = opt[0][0]; + + opt = get_options("roi_radius"); + if (opt.size()) + roi_radius = opt[0][0]; + + opt = get_options("fraction_pyramid"); + if (opt.size()) + fraction_pyramid = opt[0][0]; + + opt = get_options("barrier_rate"); + if (opt.size()) + barrier_rate = opt[0][0]; + + opt = get_options("seed"); + if (opt.size()) { + std::string seed_string = opt[0][0]; + seed = to(seed_string); + } else + std::cout << "No random seed supplied. Using timestamp: " << seed << std::endl; + + + std::map properties; + + properties["num_dims"] = str(num_dims); + properties["barrier_rate"] = str(barrier_rate); + properties["roi_radius"] = str(roi_radius); + properties["num_peaks"] = str(num_peaks); + properties["width_mu"] = str(width_mu); + properties["width_sigma"] = str(width_sigma); + properties["width_min"] = str(width_min); + properties["height_var"] = str(height_var); + properties["fraction_pyramid"] = str(fraction_pyramid); + + + + Prob::Test::Landscape peaks = Prob::Test::Landscape::randomly_generate( num_dims, + num_peaks, + width_mu, + width_sigma, + width_min, + height_var, + roi_radius, + fraction_pyramid, + barrier_rate, seed); + + peaks.save(output_location); + + std::cout << "Generated " << num_peaks << " peaks." << std::endl; + +} diff --git a/cmd/random_miscs.cpp b/cmd/random_miscs.cpp new file mode 100644 index 0000000..55bd5c3 --- /dev/null +++ b/cmd/random_miscs.cpp @@ -0,0 +1,246 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Written by Thomas G. Close, 04/03/2009. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + +*/ + + +extern "C" { +#include +#include +} + + +#include "bts/cmd.h" +#include "progressbar.h" + +#include "bts/common.h" + +#include "bts/fibre/base/writer.h" + + +#include "bts/coord.h" +#include "bts/fibre/tractlet/section.h" + + +#include "bts/mcmc/state.h" +//#include "bts/mcmc/state/writer.h" + +#include "bts/fibre/properties/extended.h" +#include "bts/fibre/strand.h" + + +#include "bts/inline_functions.h" + +using namespace BTS; + +SET_VERSION_DEFAULT; +SET_AUTHOR ("Thomas G. Close"); +SET_COPYRIGHT (NULL); + +DESCRIPTION = { + "Generates random triples and saves them to file.", + "", + NULL +}; + +ARGUMENTS = { + Argument ("output", "Random triples").type_file(), + Argument() +}; + + +OPTIONS = { + + Option ("number", "The number of triples to generate") + + Argument ("number", "").type_integer (1, 100, 1e6), + + Option ("max", "Maximum value of the triple elements.") + + Argument ("max", "").type_float (-1e9, 1.0, 1e9), + + Option ("min", "Minimum value of the triple elements.") + + Argument ("min", "").type_float (-1e9, 1.0, 1e9), + + Option ("state_size", "The size MCMC states to generate") + + Argument ("state_size", "").type_integer (1, 2, 1e6), + + Option ("seed", "Seed for the random generation") + + Argument ("seed", ""), + + + +Option() }; + + + +EXECUTE { + + + + std::string output_location = argument[0]; + + size_t number = 100; + double max_value = 1.0; + double min_value = 0.0; + size_t state_size = 2; + size_t seed = time(NULL); + + + + + Options opt = get_options("number"); + if (opt.size()) + number = opt[0][0]; + + opt = get_options("max_value"); + if (opt.size()) + max_value = opt[0][0]; + + opt = get_options("min_value"); + if (opt.size()) + min_value = opt[0][0]; + + opt = get_options("seed"); + if (opt.size()) { + std::string seed_str = opt[0][0]; + seed = to(seed_str); + } + opt = get_options("state_size"); + if (opt.size()) + state_size = opt[0][0]; + + + gsl_rng* rand_gen = gsl_rng_alloc(gsl_rng_taus); + gsl_rng_set(rand_gen, seed); + + + + + if (File::has_extension< Coord >(output_location)) { + + MR::ProgressBar progress_bar ("Randomly generating " + str(number) + " Coord's...", number); + + Coord::Writer writer(output_location); + + for (size_t trip_i = 0; trip_i < number; ++trip_i) { + + Coord triple; + + for (size_t dim_i = 0; dim_i < 3; ++dim_i) + triple[dim_i] = (double)gsl_ran_flat(rand_gen, min_value, max_value); + + writer.append(triple); + progress_bar++; + + } + + //MR::ProgressBar::done(); + + } else if (File::has_extension(output_location)) { + +#ifdef CODE_TESTING + MR::ProgressBar progress_bar ("Randomly generating " + str(number) + " Fibre::Strand::Section's...", number); + + std::vector header; + header.push_back("intensity"); + + Fibre::Base::Writer writer(output_location); + + for (size_t section_i = 0; section_i < number; ++section_i) { + + Fibre::Strand::Section section; + + for (size_t dim_i = 0; dim_i < 3; ++dim_i) { + section.position()[dim_i] = (double)gsl_ran_flat(rand_gen, min_value, max_value); + section.tangent()[dim_i] = (double)gsl_ran_flat(rand_gen, min_value, max_value); + } + + section.intensity() = (double)gsl_ran_flat(rand_gen, min_value, max_value); + + writer.append(section); + progress_bar++; + + } + + //MR::ProgressBar::done(); +#else + throw Exception ("Macro CODE_TESTING needs to be defined to generate random Fibre::Strand::Sections"); +#endif /* CODE_TESTING */ + + } else if (File::has_extension(output_location)) { + +#ifdef CODE_TESTING + MR::ProgressBar progress_bar ("Randomly generating " + str(number) + " Fibre::Tractlet::Section's...", number); + + std::vector header; + header.push_back("intensity"); + + Fibre::Base::Writer writer(output_location); + + for (size_t section_i = 0; section_i < number; ++section_i) { + + Fibre::Tractlet::Section section; + + + for (size_t dim_i = 0; dim_i < 3; ++dim_i) { + section.position()[dim_i] = (double)gsl_ran_flat(rand_gen, min_value, max_value); + section.tangent()[dim_i] = (double)gsl_ran_flat(rand_gen, min_value, max_value); + section.width1()[dim_i] = (double)gsl_ran_flat(rand_gen, min_value, max_value); + section.width2()[dim_i] = (double)gsl_ran_flat(rand_gen, min_value, max_value); + } + + section.intensity() = (double)gsl_ran_flat(rand_gen, min_value, max_value); + + writer.append(section); + progress_bar++; + + } + + //MR::ProgressBar::done(); +#else + throw Exception ("Macro CODE_TESTING needs to be defined to generate random Fibre::Tractlet::Sections"); +#endif /* CODE_TESTING */ + + } else if (File::has_extension(output_location)) { + + MR::ProgressBar progress_bar ("Randomly generating " + str(number) + " MCMC::State's of size " + str(state_size) + "...", number); + + MCMC::State::Writer writer(output_location); + + for (size_t state_i = 0; state_i < number; ++state_i) { + + MCMC::State state(state_size); + + for (size_t elem_i = 0; elem_i < state_size; elem_i++) + state[elem_i] = (double)gsl_ran_flat(rand_gen, min_value, max_value); + + writer.append(state); + progress_bar++; + + } + + //MR::ProgressBar::done(); + + + } else + throw Exception ("Unrecognised file extension '" + File::extension(output_location) + "', can be '" + Coord::FILE_EXTENSION + "', '" + Fibre::Strand::Section::FILE_EXTENSION + "', '" + Fibre::Tractlet::Section::FILE_EXTENSION + "' or '" + MCMC::State::FILE_EXTENSION + "'."); + + + +} diff --git a/cmd/random_short_strands.cpp b/cmd/random_short_strands.cpp new file mode 100644 index 0000000..56c16e7 --- /dev/null +++ b/cmd/random_short_strands.cpp @@ -0,0 +1,139 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + +extern "C" { +#include +#include +} + + +#include "bts/common.h" + +#include "bts/cmd.h" +#include "progressbar.h" + +#include "bts/fibre/strand/set.h" + + + + +#include "bts/inline_functions.h" + + +using namespace BTS; + +SET_VERSION_DEFAULT; +SET_AUTHOR ("Thomas G. Close"); +SET_COPYRIGHT (NULL); + +DESCRIPTION = { + "Trims paths to a sphere of specified radius.", + "The sections of paths that lie outside the radius of the sphere are removed and sections that reenter are split into new paths.", + NULL +}; + +ARGUMENTS = { + Argument ("output", "The returned trimmed paths.").type_file(), + Argument() +}; + + +OPTIONS = { + + Option ("degree", "Limit the degree of the Strand coefficients used to describe the strands to the first - degrees") + + Argument ("degree", "Limit the degree of the Strand coefficients used to describe the strands to the first - degrees").type_integer (1, 200, 3), + + Option ("sphere_r", "The radius of the sphere the strands will be trimmed to") + + Argument ("sphere_r", "").type_float (SMALL_FLOAT, 1.0, LARGE_FLOAT), + + Option ("num_strands", "The number of strands to be created") + + Argument ("num_strands", "").type_integer(1, 10, LARGE_INT), + + Option ("strand_length", "The length of the short strands") + + Argument ("strand_length", "").type_float (SMALL_FLOAT, 0.01, LARGE_FLOAT), + + Option ("num_points", "The number of points that will be generated along the strand location") + + Argument ("points", "The number of points that will be generated along the strand location").type_integer (1, 100, 2000), + +Option() }; + + +EXECUTE { + + + std::string output_location = argument[0];; + + + + size_t degree = 3; + double sphere_radius = 1.0; + size_t num_strands = 0.05; + double strand_length = 0.01; + size_t num_points = 0; + + + Options opt = get_options(0); + if (opt.size()) + degree = opt[0][0]; + + opt = get_options("sphere_radius"); + if (opt.size()) + sphere_radius = opt[0][0]; + + opt = get_options("num_strands"); + if (opt.size()) + num_strands = opt[0][0]; + + opt = get_options("strand_length"); + if (opt.size()) + strand_length = opt[0][0]; + + opt = get_options("num_points"); + if (opt.size()) + num_points = opt[0][0]; + + if (degree < 2) + throw Exception( "DegreeVector (" + str(degree) + ") must be greater than 2."); + + gsl_rng* rand_gen = gsl_rng_alloc(gsl_rng_taus); + gsl_rng_set(rand_gen, time(NULL)); + + Fibre::Strand::Set strands; + + MR::ProgressBar progress_bar ("Generating " + str(num_strands) + " short strands on sphere_surface..."); + + for (size_t strand_i = 0; strand_i < num_strands; strand_i++) { + Fibre::Strand strand(degree, 0.0); + + strand[0] = Triple((double)gsl_ran_gaussian(rand_gen, 1.0), (double)gsl_ran_gaussian(rand_gen, 1.0), (double)gsl_ran_gaussian(rand_gen, 1.0)).normalise() * sphere_radius; + + strand[1] = strand[0].cross(strand[0].min_axis()).normalise() * strand_length; + + strands.push_back(strand); + } + + strands.save(output_location, num_points); + + //MR::ProgressBar::done(); +} + + diff --git a/cmd/redegree_fibres.cpp b/cmd/redegree_fibres.cpp new file mode 100644 index 0000000..05fccee --- /dev/null +++ b/cmd/redegree_fibres.cpp @@ -0,0 +1,154 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, Jul 26, 2010. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + + +#include "bts/cmd.h" + +#include "bts/common.h" + +#include "bts/fibre/strand/set.h" +#include "bts/fibre/tractlet/set.h" + +#include "bts/file.h" + +#include "bts/math/svd.h" + + + +#include "bts/inline_functions.h" + +using namespace BTS; + +const size_t DEGREE_DEFAULT = 3; + +SET_VERSION_DEFAULT; +SET_AUTHOR ("Thomas G. Close"); +SET_COPYRIGHT (NULL); + + +DESCRIPTION = { + "redegree_fibres", + "Changes the degree of the fibres", + NULL +}; + +ARGUMENTS = { + Argument ("input location","").type_file (), + Argument ("output location","").optional().type_file (), + Argument() +}; + + +OPTIONS = { + + Option("degree", "The degree of the output fibres..") + + Argument("degree","").type_integer(0,DEGREE_DEFAULT,LARGE_INT), + +Option() }; + + +EXECUTE { + + + std::string input_location = argument[0]; + std::string output_location = input_location; + + if (argument.size() == 2) + output_location = argument[1].c_str(); + + size_t degree = DEGREE_DEFAULT; + + Options opt = get_options("degree"); + if (opt.size()) + degree = opt[0][0]; + + MR::ProgressBar progress_bar ("Redegreeing fibres to a degree of " + str(degree) + " ..."); + + if (File::has_extension(input_location)) { + + Fibre::Strand::Set strands (input_location); + + for (size_t strand_i = 0; strand_i < strands.size(); ++strand_i) + strands[strand_i].resize(degree,0.0); + + strands.save(output_location); + + } else if (File::has_extension(input_location)) { + + Fibre::Tractlet::Set tractlets (input_location); + + for (size_t tract_i = 0; tract_i < tractlets.size(); ++tract_i) + tractlets[tract_i].redegree(degree,0.0); + + tractlets.save(output_location); + + } else + throw Exception ("Unrecognised extension '" + File::extension(input_location) + "'."); + + +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cmd/remove_fibres.cpp b/cmd/remove_fibres.cpp new file mode 100644 index 0000000..b3e054a --- /dev/null +++ b/cmd/remove_fibres.cpp @@ -0,0 +1,175 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + +extern "C" { +#include +#include +} + + +#include "bts/common.h" + +#include "bts/cmd.h" +#include "progressbar.h" + +#include "bts/fibre/track/set.h" +#include "bts/fibre/strand/set.h" +#include "bts/fibre/tractlet/set.h" + + + +#include "bts/inline_functions.h" + + +using namespace BTS; + +SET_VERSION_DEFAULT; +SET_AUTHOR ("Thomas G. Close"); +SET_COPYRIGHT (NULL); + +DESCRIPTION = { + "Trims paths to a sphere of specified radius.", + "The sections of paths that lie outside the radius of the sphere are removed and sections that reenter are split into new paths.", + NULL +}; + +ARGUMENTS = { + Argument ("input", "The input fibres.").type_file(), + Argument ("output", "The output fibres.").optional().type_file(), + Argument() +}; + + +OPTIONS = { + + Option ("degree", "Limit the degree of the Strand coefficients used to describe the strands to the first - degrees") + + Argument ("degree", "Limit the degree of the Strand coefficients used to describe the strands to the first - degrees").type_integer (1, 200, 3), + + Option ("min_length", "The length of the short strands") + + Argument ("min_length", "").type_float (-1, -1, LARGE_FLOAT), + + Option ("min_acs", "The minimum tract volume.") + + Argument ("min_acs", "").type_float (-1, -1, LARGE_FLOAT), + + Option ("num_length_sections", "The number of points that will be generated along the strand location") + + Argument ("points", "").type_integer (1, 100, 2000), + + Option ("num_width_sections", "The number of points that will be generated along the strand location") + + Argument ("points", "").type_integer (1, 100, 2000), + +Option() }; + + +EXECUTE { + + std::string input_location = argument[0]; + std::string output_location = input_location; + + if (argument.size() > 1) + output_location = argument[1].c_str(); + + +// size_t degree = 3; + double min_length = -1; + double min_acs = -1; +// size_t num_length_sections = 100; +// size_t num_width_sections = 6; + + Options opt = get_options("min_length"); + if (opt.size()) + min_length = opt[0][0]; + + opt = get_options("min_acs"); + if (opt.size()) + min_acs = opt[0][0]; + +// opt = get_options("degree"); +// if (opt.size()) +// degree = opt[0][0]; +// opt = get_options("num_length_sections"); +// if (opt.size()) +// num_length_sections = opt[0][0]; +// opt = get_options("num_width_sections"); +// if (opt.size()) +// num_width_sections = opt[0][0]; + + + if ((File::has_extension(input_location) || File::has_extension(input_location)) && (min_length > 0) ) { + Fibre::Track::Set in(input_location); + Fibre::Track::Set out(in.get_extend_props()); + out.add_extend_elem_props(in); + + MR::ProgressBar progress_bar("Removing short strands/tracks...."); + + for (size_t tck_i = 0; tck_i < in.size(); ++tck_i) { + + Fibre::Track tck = in[tck_i]; + + double length = 0.0; + + for (size_t point_i = 1; point_i < tck.size(); ++point_i) { + length += (tck[point_i] - tck[point_i - 1]).norm(); + } + + if (length > min_length) + out.push_back(tck, in.get_extend_elem_prop_row(tck_i)); + + ++progress_bar; + + } + + in = out; + + out.save(output_location); + + } + + + if (File::has_extension(input_location) && (min_acs > 0)) { + + Fibre::Tractlet::Set in(input_location); + Fibre::Tractlet::Set out(in.get_extend_props()); + out.add_extend_elem_props(in); + + + MR::ProgressBar progress_bar("Removing thin tractlets...."); + + for (size_t tract_i = 0; tract_i < in.size(); ++tract_i) { + + if (in[tract_i].acs() > min_acs) + out.push_back(in[tract_i], in.get_extend_elem_prop_row(tract_i)); + + ++progress_bar; + + } + + in = out; + + out.save(output_location); + + } + + + +} + + diff --git a/cmd/remove_isotropic.cpp b/cmd/remove_isotropic.cpp new file mode 100644 index 0000000..8b6847d --- /dev/null +++ b/cmd/remove_isotropic.cpp @@ -0,0 +1,106 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + + +extern "C" { +#include +#include +} + + +#include "bts/cmd.h" +#include "progressbar.h" + +#include "bts/common.h" +#include "bts/image/expected/buffer.h" +#include "bts/image/observed/buffer.h" + +#include "bts/image/noise.h" +#include "bts/image/noise/gaussian.h" + + + +#include "bts/inline_functions.h" + +using namespace BTS; + +SET_VERSION_DEFAULT; +SET_AUTHOR ("Thomas G. Close"); +SET_COPYRIGHT (NULL); + +DESCRIPTION = { + "Subtracts the isotropic components from the image.", + "", + NULL +}; + +ARGUMENTS = { + Argument ("initial", "The initial image the second image will be subtracted from.").type_file(), + + Argument ("output_image", "The resulting image").optional().type_file (), + + Argument() +}; + + +OPTIONS = { + + Option ("dims", "The number of voxels along each dimension") + + Argument ("dims", "").type_text ("[3,3,3]"), + + Option ("offsets", "The offset of the centre of the image from the origin (0,0,0).") + + Argument ("offsets", "").type_text ("auto"), + + +Option() + +}; + + + +EXECUTE { + + std::string input_location = argument[0]; + std::string output_location = input_location; + + if (argument.size() > 1) + output_location = argument[1].c_str(); + + Image::Observed::Buffer image(input_location); + + MR::ProgressBar progress_bar ("Removing isotropic components from image..."); + + image.remove_isotropic(); + + image.properties()["istropic_removed"] = "1"; + + +//-------------// +// Save Image // +//-------------// + + image.save(output_location); + + +} + + diff --git a/cmd/remove_short_tracks.cpp b/cmd/remove_short_tracks.cpp new file mode 100644 index 0000000..4ac3553 --- /dev/null +++ b/cmd/remove_short_tracks.cpp @@ -0,0 +1,94 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, Sep 27, 2010. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + + +#include "bts/cmd.h" + +#include "bts/common.h" + +#include "bts/inline_functions.h" +#include "bts/fibre/track/set.h" + +using namespace BTS; + + +SET_VERSION_DEFAULT; +SET_AUTHOR ("Thomas G. Close"); +SET_COPYRIGHT (NULL); + +const size_t NUM_LENGTH_SECTIONS_DEFAULT = 4; + +DESCRIPTION = { + "remove_short_tracks", + "", + NULL +}; + +ARGUMENTS = { + Argument ("input_location","").type_file (), + Argument ("output_location", "").optional().type_file (), + Argument() +}; + + +OPTIONS = { + + Option("num_points","The number of points below which a track will be removed.") + + Argument("num_points","").type_integer(0,NUM_LENGTH_SECTIONS_DEFAULT,LARGE_INT), + +Option() }; + + +EXECUTE { + + + std::string input_location = argument[0]; + std::string output_location; + + if (argument.size() == 2) + output_location = argument[1].c_str(); + else + output_location = input_location; + + size_t num_points = NUM_LENGTH_SECTIONS_DEFAULT; + + + Options opt; + + opt = get_options("num_points"); + if (opt.size()) + num_points = opt[0][0]; + + + Fibre::Track::Set in_tracks(input_location); + Fibre::Track::Set out_tracks(in_tracks.get_extend_props()); + out_tracks.add_extend_elem_props(in_tracks); + + for (size_t tck_i = 0; tck_i < in_tracks.size(); ++tck_i) + if (in_tracks[tck_i].size() >= num_points) + out_tracks.push_back(in_tracks[tck_i], in_tracks.get_extend_elem_prop_row(tck_i)); + + out_tracks.save(output_location); + + + +} diff --git a/cmd/resample_tcks.cpp b/cmd/resample_tcks.cpp new file mode 100644 index 0000000..418b23d --- /dev/null +++ b/cmd/resample_tcks.cpp @@ -0,0 +1,173 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + +#include "bts/cmd.h" +#include "progressbar.h" + +#include "bts/common.h" + +#include "bts/fibre/track/set.h" + +#include "phantom/interface.h" + +#include "phantom/shared/strand_collection.h" +#include "phantom/resample/resample.h" + + + + +#include "bts/inline_functions.h" + + +using namespace BTS; + +SET_VERSION_DEFAULT; +SET_AUTHOR ("Thomas G. Close"); +SET_COPYRIGHT (NULL); + +DESCRIPTION = { + "Resamples control points along tracks.", + "", + NULL +}; + +ARGUMENTS = { + Argument ("input", "The tracks to be resampled.").type_file (), + Argument ("output", "The returned resampled tracks.").optional().type_file(), + Argument() +}; + + +OPTIONS = { + + Option ("resample_length", "Defines the length of the new inter control-point intervals") + + Argument ("resample_length", "").type_float (0.00001, 0.02, 10000.0), + + Option ("double_back_angle_threshold", "The angle between successive segments above which the second segment is considered to have doubled back on itself") + + Argument ("double_back_angle_threshold", "").type_float (90.0, 150.0, 180.0), + + Option ("forward_angle_threshold", "The angle after a double back has been detected above which the subsequent segment is considered to have travelled back in a forward direction again.") + + Argument ("forward_angle_threshold","").type_float (5.0, 80.0, 180.0), + + Option ("num_points", "The number of points that will be generated along the strand path if the loaded tracks are fourier descriptors") + + Argument ("num_points", "").type_integer (1, 100, 2000), + + Option ("degree", "The degree of the Fourier coefficients used to describe the ") + + Argument ("degree", "").type_integer (1, 8, 200), + +Option() }; + + +EXECUTE { + + + std::string input_path = argument[0]; + std::string output_path; + + if (argument.size() > 1) + output_path = argument[1].c_str(); + else + output_path = input_path; + + + double resample_length = 0.02; + double double_back_angle_threshold = 150.0; + double forward_angle_threshold = 80.0; + size_t num_points = 0; + size_t degree = 0; + + + Options opt = get_options("resample_length"); + if (opt.size()) + resample_length = opt[0][0]; + + opt = get_options("double_back_angle_threshold"); + if (opt.size()) + double_back_angle_threshold = opt[0][0]; + + opt = get_options("forward_angle_threshold"); + if (opt.size()) + forward_angle_threshold = opt[0][0]; + + opt = get_options("num_points"); + if (opt.size()) + num_points = opt[0][0]; + + opt = get_options("degree"); + if (opt.size()) + degree = opt[0][0]; + + + BTS::Fibre::Track::Set tcks(input_path, num_points); + BTS::Fibre::Track::Set resampled_tcks(tcks.get_extend_props()); + + std::vector > pre_points; + std::vector > post_points; + + Strand_collection c, resampled_c; + + generate_pre_points(tcks, pre_points); + + generate_post_points(tcks, post_points); + + convert_mr_to_nfg(&c, tcks, pre_points, post_points); + + MR::ProgressBar progress_bar ("Resampling tracks..."); + resample_collection(&c, &resampled_c, resample_length, double_back_angle_threshold, forward_angle_threshold); + //MR::ProgressBar::done(); + + convert_nfg_to_mr(resampled_tcks, pre_points, post_points, &resampled_c); + + resampled_tcks.save(output_path, degree); + +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cmd/reset_indices.cpp b/cmd/reset_indices.cpp new file mode 100644 index 0000000..dfce128 --- /dev/null +++ b/cmd/reset_indices.cpp @@ -0,0 +1,132 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by J-Donald Tournier, 27/06/08. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + + +#include "bts/cmd.h" +#include "bts/common.h" + +#include "bts/fibre/strand/set.h" +#include "bts/fibre/tractlet/set.h" +#include "bts/fibre/track/set.h" + + +#include "bts/inline_functions.h" + +using namespace BTS; + +template void reset_indices(T& input_location); + +SET_VERSION_DEFAULT; +SET_AUTHOR ("Thomas G. Close"); +SET_COPYRIGHT (NULL); + +DESCRIPTION = { + "Resets bundle indices to a consecutive range", + "", + NULL +}; + +ARGUMENTS = { + Argument ("input file", "The input fibres file location.").type_file (), + Argument ("output file", "The output fibres file location.").optional().type_file (), + Argument() +}; + + +OPTIONS = { + + Option() +}; + +EXECUTE { + + std::string input_location = argument[0]; + std::string output_location = input_location; + + if (argument.size() > 1) + output_location = argument[1].c_str(); + + + if (File::has_extension(input_location)) { + + Fibre::Strand::Set strands (input_location); + + reset_indices(strands); + + strands.save(output_location); + + + } else if (File::has_extension(input_location)) { + + Fibre::Tractlet::Set tractlets (input_location); + + reset_indices(tractlets); + + tractlets.save(output_location); + + + } else if (File::has_extension(input_location)) { + + Fibre::Track::Set tcks (input_location); + + reset_indices(tcks); + + tcks.save(output_location); + + + } else + throw Exception ("Unrecognised extension of input file '" + input_location + "'."); + +} + + + +template void reset_indices(T& fibres) { + + + if (!fibres.has_extend_elem_prop(Fibre::Track::BUNDLE_INDEX_EPROP)) + fibres.add_extend_elem_prop(Fibre::Track::BUNDLE_INDEX_EPROP, "-1"); + + + std::map indices; + + size_t bundle_count = 0; + + for (size_t strand_i = 0; strand_i < fibres.size(); ++strand_i) { + + std::string bundle_index = fibres.get_extend_elem_prop(Fibre::Track::BUNDLE_INDEX_EPROP, strand_i); + + if (!indices.count(bundle_index)) + indices[bundle_index] = bundle_count++; + + } + + + for (size_t strand_i = 0; strand_i < fibres.size(); ++strand_i) { + + size_t reset_bundle_index = indices[fibres.get_extend_elem_prop(Fibre::Track::BUNDLE_INDEX_EPROP, strand_i)]; + + fibres.set_extend_elem_prop(Fibre::Track::BUNDLE_INDEX_EPROP, str(reset_bundle_index), strand_i); + + } + +} diff --git a/cmd/riemannian.cpp b/cmd/riemannian.cpp new file mode 100644 index 0000000..1a05018 --- /dev/null +++ b/cmd/riemannian.cpp @@ -0,0 +1,588 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + + + +extern "C" { +#include +#include +} + + +#include + +#include "bts/cmd.h" + +#include "math/matrix.h" + +#include "progressbar.h" + + +#include "bts/common.h" +#include "bts/file.h" + + +#include "bts/fibre/tractlet/set.h" +#include "bts/fibre/strand/set.h" + + + + +#include "bts/diffusion/model.h" +#include "bts/image/expected/trilinear/buffer.h" +#include "bts/image/expected/gaussian/buffer.h" +#include "bts/image/expected/quartic/buffer.h" + +#include "bts/image/observed/buffer.h" + +#include "bts/prob/uniform.h" +#include "bts/prob/prior.h" + + + + + +#include "bts/prob/likelihood.h" +#include "bts/prob/likelihood.h" +#include "bts/prob/likelihood/one_sided_gaussian.h" +#include "bts/prob/likelihood/gaussian.h" + +#include "bts/fibre/strand/set/momentum.h" +#include "bts/fibre/tractlet/set/momentum.h" +#include "bts/mcmc/proposal/distribution.h" +#include "bts/mcmc/proposal/distribution/gaussian.h" +#include "bts/mcmc/proposal/momentum/weighted.h" + + +#include "bts/mcmc/riemannian.h" + +#include "bts/file.h" +#include "bts/math/common.h" + +#include "bts/fibre/base/tensor_writer.cpp.h" +#include "bts/prob/likelihood.cpp.h" +#include "bts/prob/likelihood/gaussian.cpp.h" + +#include "bts/inline_functions.h" + + +using namespace BTS; + + +SET_VERSION_DEFAULT; +SET_AUTHOR ("Thomas G. Close"); +SET_COPYRIGHT (NULL); + +DESCRIPTION = { + "Runs Riemannian MCMC sampling on a given image from a given starting configuration of tractlets or strands.", + "", + NULL +}; + +ARGUMENTS = { + Argument ("input_image", "The image the tractlets will be fit against.").type_image_in(), + + Argument ("inital tractlets", "A starting point for the MCMC algorithm.").type_file (), + + Argument ("samples location", "The location where the samples will be saved.").type_file (), + + Argument() +}; + + +OPTIONS = { + + + Option ("num_samples", "The Number of MCMC iterations to take of the prob distribution over the tractlets") + + Argument ("num_samples", "").type_integer (1, MCMC::Riemannian::NUM_SAMPLES_DEFAULT, LARGE_INT), + + Option ("num_leapfrog_steps", "The number of MCMC iterations that will be performed before a sample is saved") + + Argument ("num_leapfrog_steps", "").type_integer (1, MCMC::Riemannian::NUM_LEAPFROG_STEPS_DEFAULT, LARGE_INT), + + Option ("num_newton_steps", "The number steps to take in the Newton solution of the nonseparable Hamiltonian.") + + Argument ("num_newton_steps", "").type_integer (1, MCMC::Riemannian::NUM_NEWTON_STEPS_DEFAULT, LARGE_INT), + + Option ("burn_num_samples", "The Number of MCMC iterations to take as part of the Burn-in.") + + Argument ("burn_num_samples", "").type_integer (0, MCMC::Riemannian::BURN_NUM_SAMPLES_DEFAULT, LARGE_INT), + + Option ("burn_num_leapfrog_steps", "The number of MCMC iterations that will be performed before a sample is saved in the Burn-in.") + + Argument ("burn_num_leapfrog_steps", "").type_integer (1, MCMC::Riemannian::BURN_NUM_LEAPFROG_STEPS_DEFAULT, LARGE_INT), + + Option ("burn_num_newton_steps", "The number steps to take in the Newton solution of the nonseparable Hamiltonian in the burn-in.") + + Argument ("burn_num_newton_steps", "").type_integer (1, MCMC::Riemannian::BURN_NUM_NEWTON_STEPS_DEFAULT, LARGE_INT), + + Option ("burn_snr", "The Signal-to-noise ratio assumed for the burn-in period.") + + Argument ("burn_snr", "").type_float (SMALL_FLOAT, MCMC::Riemannian::BURN_SNR_DEFAULT, LARGE_FLOAT), + + Option ("precondition", "Preconditioning increment added to diagonal of Fisher Information matrix for stability of its inverse.") + + Argument ("precondition", "").type_float (0.0, MCMC::Riemannian::PRECONDITION_DEFAULT, LARGE_FLOAT), + + Option ("seed", "The random seed that is passed to the random generator") + + Argument ("seed", ""), + + Option ("prior_only", "Only sample from the prior distribution."), + + Option ("save_iterations", "Save all iterations not just samples."), + + DIFFUSION_PARAMETERS, + + EXPECTED_IMAGE_PARAMETERS, + + LIKELIHOOD_PARAMETERS, + + PRIOR_PARAMETERS, + + PROPOSAL_DISTRIBUTION_PARAMETERS, + + PROPOSAL_MOMENTUM_PARAMETERS, + + COMMON_PARAMETERS, + +Option() }; + + +EXECUTE { + + +//-----------------// +// Load Arguments // +//-----------------// + + std::string obs_image_location = argument[0]; + std::string initial_location = argument[1]; + std::string samples_location = argument[2]; + std::string burn_samples_location = File::strip_extension (samples_location) + ".burn." + File::extension(samples_location); + + MR::Image::Header header (argument[0]); + + if (header.ndim() != 4) + throw Exception ("dwi image should contain 4 dimensions"); + + + +//----------------------------------// +// Get and Set Optional Parameters // +//----------------------------------// + + + size_t num_samples = MCMC::Riemannian::NUM_SAMPLES_DEFAULT; + size_t num_leapfrog_steps = MCMC::Riemannian::NUM_LEAPFROG_STEPS_DEFAULT; + size_t num_newton_steps = MCMC::Riemannian::NUM_NEWTON_STEPS_DEFAULT; + size_t burn_num_samples = MCMC::Riemannian::BURN_NUM_SAMPLES_DEFAULT; + size_t burn_num_leapfrog_steps = MCMC::Riemannian::BURN_NUM_LEAPFROG_STEPS_DEFAULT; + size_t burn_num_newton_steps = MCMC::Riemannian::BURN_NUM_NEWTON_STEPS_DEFAULT; + double burn_snr = MCMC::Riemannian::BURN_SNR_DEFAULT; + double precondition = MCMC::Riemannian::PRECONDITION_DEFAULT; + size_t seed = time(NULL); + bool prior_only = false; + bool save_iterations = true; + + + + + Options opt = get_options("num_samples"); + if (opt.size()) + num_samples = opt[0][0]; + + opt = get_options("num_leapfrog_steps"); + if (opt.size()) + num_leapfrog_steps = opt[0][0]; + + opt = get_options("num_newton_steps"); + if (opt.size()) + num_newton_steps = opt[0][0]; + + opt = get_options("burn_num_samples"); + if (opt.size()) + burn_num_samples = opt[0][0]; + + opt = get_options("burn_num_leapfrog_steps"); + if (opt.size()) + burn_num_leapfrog_steps = opt[0][0]; + + opt = get_options("burn_num_newton_steps"); + if (opt.size()) + burn_num_newton_steps = opt[0][0]; + + opt = get_options("burn_snr"); + if (opt.size()) + burn_snr = opt[0][0]; + + opt = get_options("precondition"); + if (opt.size()) + precondition = opt[0][0]; + + opt = get_options("seed"); + if (opt.size()) { + std::string seed_string = opt[0][0]; + seed = to(seed_string); + } else + std::cout << "No random seed supplied. Using timestamp: " << seed << std::endl; + + opt = get_options("prior_only"); + if (opt.size()) + prior_only = true; + + opt = get_options("save_iterations"); + if (opt.size()) + save_iterations = true; + + // Loads parameters to construct Diffusion::Model ('diff_' prefix) + SET_DIFFUSION_PARAMETERS; + + // Loads parameters to construct Image::Expected::*::Buffer ('img_' prefix) + SET_EXPECTED_IMAGE_PARAMETERS; + + // Loads parameters to construct Prob::Likelihood ('like_' prefix) + SET_LIKELIHOOD_PARAMETERS; + + // Loads parameters to construct Prob::Prior ('prior_' prefix) + SET_PRIOR_PARAMETERS; + + // Loads parameters to construct Proposal::Distribution (any variables with 'prop_' prefix) + SET_PROPOSAL_DISTRIBUTION_PARAMETERS; + + // Loads parameters to construct Proposal::Distribution ('prop_' prefix) + SET_PROPOSAL_MOMENTUM_PARAMETERS(initial_location); + + // Loads parameters that are common to all commands. + SET_COMMON_PARAMETERS; + + + //--------------------------------// + // Set up reference image buffer // + //--------------------------------// + + + Image::Observed::Buffer obs_image(obs_image_location, Diffusion::Encoding::Set(diff_encodings)); + + + //If gradient scheme is included in reference image header, use that instead of default (NB: Will override any gradients passed to '-diff_encodings' option). + if (header.get_DW_scheme().rows()) { + diff_encodings = header.get_DW_scheme(); + diff_encodings_location = "from observed image"; + } + + if ((header.count("diff_response_SH")) && (Math::matlab_str(diff_response_SH) != header["diff_response_SH"])) + std::cout << std::endl << "Warning! Diffusion response function harmonics (" << Math::matlab_str(diff_response_SH) << ") do not match reference image (" << header["diff_response_SH"] + ")!" << std::endl; + + + //----------------------------// + // Initialize Expected Image // + //----------------------------// + + + + Diffusion::Model diffusion_model = Diffusion::Model::factory (diff_encodings, + diff_response_SH, + diff_adc, + diff_fa, + diff_isotropic); + + Image::Expected::Buffer* exp_image = Image::Expected::Buffer::factory(exp_type, + obs_image, + diffusion_model, + exp_num_length_sections, + exp_num_width_sections, + exp_interp_extent, + exp_enforce_bounds, + exp_half_width); + + + + //----------------------------------------------------------------// + // Auto-generate base intensity initial value/b_intens_gauss_mean // + //----------------------------------------------------------------// + + if (exp_base_intensity < 0) + exp_base_intensity = exp_image->base_intensity_default(obs_image, initial_location); + + + //-----------------------// + // Initialize Likelihood // + //-----------------------// + + Prob::Likelihood::Gaussian likelihood (obs_image, exp_image, like_snr, like_b0_include, like_outside_scale, like_ref_b0, like_ref_signal); + + //----------------------------------// + // Initialize Proposal Distribution // + //----------------------------------// + + gsl_rng* rand_gen = gsl_rng_alloc(gsl_rng_taus); + gsl_rng_set(rand_gen, seed); + + MCMC::Proposal::Distribution* proposal_distribution = MCMC::Proposal::Distribution::factory(prop_distr_type, rand_gen); + + + +// Proposal::Intensity* intensity_proposer = Proposal::Intensity::factory(prop_intens_type, proposal_distribution, prop_intens_scale); +// +// Proposal::BaseIntensity* base_intensity_proposer = Proposal::BaseIntensity::factory(prop_base_intens_type, proposal_distribution, prop_base_intens_scale); + + + + //-------------------------// + // Set Output Properties // + //-------------------------// + + std::map run_properties; + + run_properties["Method"] = "riemannian"; + run_properties["num_newton_steps"] = str(num_newton_steps); + run_properties["num_leapfrog_steps"] = str(num_leapfrog_steps); + run_properties["seed"] = str(seed); + run_properties["num_samples"] = str(num_samples); + run_properties["burn_num_leapfrog_steps"] = str(burn_num_leapfrog_steps); + run_properties["burn_num_newton_steps"] = str(burn_num_newton_steps); + run_properties["burn_num_samples"] = str(burn_num_samples); + run_properties["burn_snr"] = str(burn_snr); + run_properties["precondition"] = str(precondition); + run_properties["obs_image"] = obs_image_location; + run_properties["initial_state"] = Fibre::Base::Object::load_matlab_str(initial_location); + run_properties["initial_state_location"]= initial_location; + + run_properties["prior_only"] = str(prior_only); + + ADD_DIFFUSION_PROPERTIES(run_properties); + + ADD_LIKELIHOOD_PROPERTIES(run_properties); + + ADD_EXPECTED_IMAGE_PROPERTIES(run_properties); + + ADD_PRIOR_PROPERTIES(run_properties); + + ADD_PROPOSAL_DISTRIBUTION_PROPERTIES(run_properties); + + ADD_PROPOSAL_MOMENTUM_PROPERTIES(run_properties); + + ADD_COMMON_PROPERTIES(run_properties); + + //-------------------------// + // Sampling from Strands // + //-------------------------// + + Prob::Prior prior (prior_scale, + prior_mag_scale, + prior_mag_aux_scale, + prior_hook_scale, + prior_hook_num_points, + prior_density_high_scale, + prior_density_low_scale, + prior_density_num_points, + prior_acs_scale, + prior_acs_mean, + prior_length_scale, + prior_length_mean); + + if (File::has_extension(initial_location)) { + + + //------------------------// + // Load Initial Strands // + //------------------------// + + Fibre::Strand::Set strands (initial_location); + + strands.set_base_intensity(exp_base_intensity); +// strands[0].acs = 1.0; + + + //--------------------// + // Initialize Prior // + //--------------------// + + + //---------------------// + // Initialize Momentum // + //---------------------// + + MCMC::Proposal::Momentum::Weighted::NonSeparable momentum = MCMC::Proposal::Momentum::Weighted::NonSeparable::factory( strands, + momen_step_scale, + momen_step_location, + proposal_distribution, + num_newton_steps); + + + //------------------// + // Perform sampling // + //------------------// + + Fibre::Strand::Set burnt_strands; + + + + if (burn_num_samples) { + + likelihood.set_assumed_snr(burn_snr, like_ref_b0, like_ref_signal); + + burnt_strands = MCMC::riemannian ( + strands, + likelihood, + prior, + momentum, + burn_samples_location, + run_properties, + burn_num_samples, + burn_num_leapfrog_steps, + burn_num_newton_steps, + rand_gen, + precondition, + prior_only, + save_iterations + ); + + likelihood.set_assumed_snr(like_snr, like_ref_b0, like_ref_signal); + + } else + burnt_strands = strands; + + + MCMC::riemannian ( + burnt_strands, + likelihood, + prior, + momentum, + samples_location, + run_properties, + num_samples, + num_leapfrog_steps, + num_newton_steps, + rand_gen, + precondition, + prior_only, + save_iterations + ); + + + + //------------------------// + // Sampling from Tractlets // + //------------------------// + + + } else if (File::has_extension(initial_location)) { + + + //-------------// + // Load Tractlets // + //-------------// + + Fibre::Tractlet::Set tractlets (initial_location); + + tractlets.set_base_intensity(exp_base_intensity); + + + //------------------// + // Initialize Prior // + //------------------// + + //---------------------// + // Initialize Proposer // + //---------------------// + + + MCMC::Proposal::Momentum::Weighted::NonSeparable momentum = MCMC::Proposal::Momentum::Weighted::NonSeparable::factory ( tractlets, + momen_step_scale, + momen_step_location, + proposal_distribution, + num_newton_steps); + + + + + //------------------// + // Perform sampling // + //------------------// + + Fibre::Tractlet::Set burnt_tractlets; + + if (burn_num_samples) { + + likelihood.set_assumed_snr(burn_snr, like_ref_b0, like_ref_signal); + + burnt_tractlets = MCMC::riemannian ( + + tractlets, + likelihood, + prior, + momentum, + burn_samples_location, + run_properties, + burn_num_samples, + burn_num_leapfrog_steps, + burn_num_newton_steps, + rand_gen, + precondition, + prior_only, + save_iterations + ); + + likelihood.set_assumed_snr(like_snr, like_ref_b0, like_ref_signal); + + } else + burnt_tractlets = tractlets; + + + + MCMC::riemannian ( + + burnt_tractlets, + likelihood, + prior, + momentum, + samples_location, + run_properties, + num_samples, + num_leapfrog_steps, + num_newton_steps, + rand_gen, + precondition, + prior_only, + save_iterations + ); + + + } else + throw Exception ("Unrecognised extension of initial state location, '" + initial_location + "'."); + + + std::cout << "MATLAB plot commands:\n\nplot_fibres " << samples_location << "\nscan.py " << samples_location << std::endl; + + + gsl_rng_free(rand_gen); + + delete exp_image; + delete proposal_distribution; + + +} + + + diff --git a/cmd/rotate_strand.cpp b/cmd/rotate_strand.cpp new file mode 100644 index 0000000..68c4e9d --- /dev/null +++ b/cmd/rotate_strand.cpp @@ -0,0 +1,165 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, Jan 25, 2011. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + + +#include "bts/cmd.h" + +#include "bts/common.h" + +#include "bts/fibre/strand.h" +#include "bts/fibre/strand/set.h" + +#include "bts/inline_functions.h" + +using namespace BTS; + + +SET_VERSION_DEFAULT; +SET_AUTHOR ("Thomas G. Close"); +SET_COPYRIGHT (NULL); + + +const size_t NUM_STEPS_DEFAULT = 100; +const float ANGLE_DEFAULT = M_PI / 2.0; +const std::string AXIS_DEFAULT = "x"; + +DESCRIPTION = { + "rotate_strand", + "", + NULL +}; + +ARGUMENTS = { + Argument ("input_strand","").type_file (), + Argument ("output strand set","").type_file (), + Argument() +}; + + +OPTIONS = { + + Option("num_steps","") + + Argument("num_steps").type_integer(0,LARGE_INT,NUM_STEPS_DEFAULT), + + Option("angle","") + + Argument("angle").type_float(0, 2.0 * M_PI, ANGLE_DEFAULT), + + Option("axis","") + + Argument("axis").type_text(AXIS_DEFAULT.c_str()), + +Option() }; + + +EXECUTE { + + std::string input_location = argument[0]; + std::string output_location = argument[1]; + + size_t num_steps = NUM_STEPS_DEFAULT; + float angle = ANGLE_DEFAULT; + std::string axis = AXIS_DEFAULT; + + Options opt; + + opt = get_options("num_steps"); + if (opt.size()) + num_steps = opt[0][0]; + + opt = get_options("angle"); + if (opt.size()) + angle = opt[0][0]; + + opt = get_options("axis"); + if (opt.size()) + axis = opt[0][0].c_str(); + + Fibre::Strand::Set strands (input_location); + Fibre::Strand::Set rotated_strands(strands); + + std::map file_props; + file_props["method"] = "rotated_strand"; + + Fibre::Strand::Set::Writer writer(output_location, strands, file_props); + + MR::Math::Matrix rotation_matrix(3,3); + + MR::ProgressBar progress_bar ("Generating rotated strands...", num_steps); + + for (size_t step_i = 0; step_i < num_steps; ++step_i) { + + double current_angle = ((double)step_i / (double)(num_steps-1)) * angle; + double cos_angle = MR::Math::cos(current_angle); + double sin_angle = MR::Math::sin(current_angle); + + rotation_matrix = 0.0; + + if ((axis == "x") || (axis == "X")) { + + rotation_matrix(X,X) = 1.0; + rotation_matrix(Y,Y) = rotation_matrix(Z,Z) = cos_angle; + rotation_matrix(Y,Z) = -sin_angle; + rotation_matrix(Z,Y) = sin_angle; + + } else if ((axis == "y") || (axis == "Y")) { + + rotation_matrix(Y,Y) = 1.0; + rotation_matrix(X,X) = rotation_matrix(Z,Z) = cos_angle; + rotation_matrix(X,Z) = sin_angle; + rotation_matrix(Z,X) = -sin_angle; + + } else if ((axis == "z") || (axis == "Z")) { + + rotation_matrix(Z,Z) = 1.0; + rotation_matrix(Y,Y) = rotation_matrix(X,X) = cos_angle; + rotation_matrix(Y,X) = -sin_angle; + rotation_matrix(X,Y) = sin_angle; + + } else + throw Exception ("Value for axis (" + axis + ") is not valid (x, y or z)"); + + for (size_t strand_i = 0; strand_i < strands.size(); ++strand_i) { + + MR::Math::Vector vector(3), rotated_vector(3); + Fibre::Strand rotated_strand(3); + + vector[X] = strands[strand_i][1][X]; + vector[Y] = strands[strand_i][1][Y]; + vector[Z] = strands[strand_i][1][Z]; + + MR::Math::mult(rotated_vector, rotation_matrix, vector); + + rotated_strands[strand_i][1][X] = rotated_vector[X]; + rotated_strands[strand_i][1][Y] = rotated_vector[Y]; + rotated_strands[strand_i][1][Z] = rotated_vector[Z]; + + + } + + + writer.append(rotated_strands); + ++progress_bar; + + } + + + +} diff --git a/cmd/scale_fibres.cpp b/cmd/scale_fibres.cpp new file mode 100644 index 0000000..fe51ddc --- /dev/null +++ b/cmd/scale_fibres.cpp @@ -0,0 +1,151 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Written by Thomas G. Close, 04/03/2009. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + + +#include "bts/cmd.h" + +#include "bts/common.h" + + +#include "bts/fibre/strand/set.h" + + +#include "bts/fibre/strand/set.h" +#include "bts/fibre/track/set.h" +#include "bts/fibre/tractlet/set.h" +#include "bts/fibre/base/set_reader.h" +#include "bts/fibre/base/set_writer.h" + + +#include "bts/inline_functions.h" + +using namespace BTS; + +const double SCALE_DEFAULT=1.0; + +SET_VERSION_DEFAULT; +SET_AUTHOR ("Thomas G. Close"); +SET_COPYRIGHT (NULL); + +DESCRIPTION = { + "Scale the size of all fibres", + "", + NULL +}; + + +ARGUMENTS = { + Argument ("input", "The fibres to be trimmed.").type_file (), + Argument ("output", "The returned trimmed fibres.").optional().type_file(), + Argument() +}; + + +OPTIONS = { + + Option ("scale", "The scalar the fibres will be multiplied by.") + + Argument ("scale", "").type_float (SMALL_FLOAT, SCALE_DEFAULT, LARGE_FLOAT), + + Option ("include_acs", "Scale the acs and base intensities as well as the rest of the strand."), + +Option() }; + + +EXECUTE { + + + std::string input_location = argument[0]; + std::string output_location; + + if (argument.size() > 1) + output_location = argument[1].c_str(); + else + output_location = input_location; + + + double scale = SCALE_DEFAULT; + bool include_acs = false; + + Options opt = get_options("scale"); + if (opt.size()) + scale = opt[0][0]; + + opt = get_options("include_acs"); + if (opt.size()) + include_acs = true; + + + if (File::has_extension(input_location)) { + + Fibre::Strand::Set strands(input_location); + + Fibre::Strand::Set output = strands * scale; + + if (!include_acs) { + + output.set_base_intensity(strands.base_intensity()); + + for (size_t strand_i = 0; strand_i < strands.size(); ++strand_i) + output[strand_i].set_acs(strands[strand_i].acs()); + + } + + output.save(output_location); + + } else if (File::has_extension(input_location)) { + + Fibre::Track::Set tcks(input_location); + + Fibre::Track::Set output = tcks * scale; + + if (!include_acs) { + + output.set_base_intensity(tcks.base_intensity()); + + for (size_t tck_i = 0; tck_i < tcks.size(); ++tck_i) + output[tck_i].set_acs(tcks[tck_i].acs()); + + } + + output.save(output_location); + + } else if (File::has_extension(input_location)) { + + Fibre::Tractlet::Set tracts(input_location); + + Fibre::Tractlet::Set output = tracts * scale; + + if (!include_acs) { + + output.set_base_intensity(tracts.base_intensity()); + + for (size_t tract_i = 0; tract_i < tracts.size(); ++tract_i) + output[tract_i].set_acs(tracts[tract_i].acs()); + + } + + output.save(output_location); + + } else + throw Exception ("Unrecognised file extension of input file '" + input_location + "'."); + +} diff --git a/cmd/scan.cpp b/cmd/scan.cpp new file mode 100644 index 0000000..d704959 --- /dev/null +++ b/cmd/scan.cpp @@ -0,0 +1,907 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + + + + +#include + +#include "bts/cmd.h" + +#include "math/matrix.h" + +#include "progressbar.h" + + +#include "bts/common.h" + +#include "bts/fibre/tractlet/set.h" +#include "bts/fibre/strand/set.h" + + +#include "bts/diffusion/model.h" +#include "bts/image/expected/trilinear/buffer.h" +#include "bts/image/expected/gaussian/buffer.h" +#include "bts/image/expected/quartic/buffer.h" + +#include "bts/image/observed/buffer.h" + +#include "bts/prob/uniform.h" +#include "bts/prob/prior.h" + + + + + +#include "bts/prob/likelihood.h" +#include "bts/prob/likelihood.h" +#include "bts/prob/likelihood/one_sided_gaussian.h" +#include "bts/prob/likelihood/gaussian.h" +#include "bts/analysis/scan.h" + +#include "bts/file.h" + +#include "bts/math/common.h" + + +#include "bts/inline_functions.h" + + +extern "C" { +#include +#include +} + +using namespace BTS; + +double NUM_STEPS_DEFAULT = 30; + +double AXIS_SCALE_DEFAULT = 1.0; + + +SET_VERSION_DEFAULT; +SET_AUTHOR ("Thomas G. Close"); +SET_COPYRIGHT (NULL); + +DESCRIPTION = { + "Runs Metropolis-Hastings sampling on a given image from a given starting configuration of tractlets or strands.", + "", + NULL +}; + +ARGUMENTS = { + + Argument ("start_fibres", "The starting point of the scan.").type_file (), + + Argument ("end_fibres", "The ending point of the scan.").optional().type_file (), + + Argument ("second_end_fibres", "The ending point of the scan.").optional().type_file (), + + Argument ("third_end_fibres", "The ending point of the scan.").optional().type_file (), + + Argument ("output", "The output file containing the function scan. Will be either a text file if it is a linear scan or an image file if it is multi-dimension scan.").optional().type_file (), + + Argument() +}; + + +OPTIONS = { + + + Option ("num_steps", "Number of taken along axis.") + + Argument ("num_steps", "").type_integer (1, NUM_STEPS_DEFAULT, LARGE_INT), + + + Option ("num_steps2", "Number of taken along second axis.") + + Argument ("num_steps", "").type_integer (1, NUM_STEPS_DEFAULT, LARGE_INT), + + + Option ("num_steps3", "Number of taken along third axis.") + + Argument ("num_steps", "").type_integer (1, NUM_STEPS_DEFAULT, LARGE_INT), + + + Option ("centred", "For 1D case (multi-D cases are automatically centred) first set is interpreted as origin of image second set is interpreted as a perturbation axes."), + + + Option ("axis1_scale", "Scale applied to axis1, used to quickly scale binary masks.") + + Argument ("axis1_scale", "").type_float (SMALL_FLOAT, AXIS_SCALE_DEFAULT, LARGE_FLOAT), + + + Option ("axis2_scale", "Scale applied to axis2, used to quickly scale binary masks.") + + Argument ("axis2_scale", "").type_float (SMALL_FLOAT, AXIS_SCALE_DEFAULT, LARGE_FLOAT), + + + Option ("axis3_scale", "Scale applied to axis3, used to quickly scale binary masks.") + + Argument ("axis3_scale", "").type_float (SMALL_FLOAT, AXIS_SCALE_DEFAULT, LARGE_FLOAT), + + + Option ("only_prob", "Only use the following probability (sets the rest to Prob::Uniform).") + + Argument("only_prob", "").type_text(), + + + Option ("no_prob", "Don't caculate probability, used to create a range of states."), + + Option ("save_gradient", "Save the gradient as well as the log probability for single axis scan."), + + Option ("only_first", "Use the first fibre in the input files instead of the whole set."), + + Option ("no_map", "Don't map the set to its smallest permutation before the scale."), + + DIFFUSION_PARAMETERS, + + IMAGE_PARAMETERS, + + EXPECTED_IMAGE_PARAMETERS, + + LIKELIHOOD_PARAMETERS, + + PRIOR_PARAMETERS, + + COMMON_PARAMETERS, + +// Option ("num_ref_sections", "Number of sections used to generate the reference images") +// + Argument ("num_ref_sections", "").type_integer (1, LARGE_INT, 1000), + + Option ("obs_image", "The location of the reference image that is to be set") + + Argument ("obs_image", "").type_image_in(), + +Option() }; + + + + + + +EXECUTE { + +//-----------------// +// Load Arguments // +//-----------------// + + std::string origin_location = argument[0]; + + std::string output_location, output_gradient_location, output_hessian_location; + std::string axis1_location, axis2_location, axis3_location; + + + int num_axes; + + if (argument.size() == 1) + num_axes = 0; + + else if (argument.size() == 2) { + num_axes = -1; + output_location = argument[1].c_str(); + + if (File::extension(origin_location) != File::extension(output_location)) + throw Exception ("Output location extension must match origin location extension (and must be a 'set' extension) when only two arguments are provided."); + + } else + num_axes = argument.size() - 2; + + if (num_axes > 3) + throw Exception ("Max number of axes is 3, " + str(num_axes) + " supplied."); + + if (num_axes >= 1) { + + axis1_location = argument[1].c_str(); + + output_location = argument[num_axes+1].c_str(); + output_gradient_location = File::strip_extension(output_location) + ".gradient." + File::extension(output_location); + + if (File::extension(origin_location) != File::extension(axis1_location)) + throw Exception ("Extension of axis1 location (2nd argument), '" + File::extension(axis1_location) + "', does not match extension of origin location (1st argument), '" + File::extension(origin_location) + "'."); + } + + if (num_axes >= 2) { + axis2_location = argument[2].c_str(); + + if (File::extension(origin_location) != File::extension(axis2_location)) + throw Exception ("Extension of second axis location (3rd argument), '" + File::extension(axis2_location) + "', does not match extension of origin location (1st argument), '" + File::extension(origin_location) + "'."); + } + + if (num_axes == 3) { + axis3_location = argument[3].c_str(); + + if (File::extension(origin_location) != File::extension(axis3_location)) + throw Exception ("Extension of third axis location (4th argument), '" + File::extension(axis3_location) + "', does not match extension of origin location (1st argument), '" + File::extension(origin_location) + "'."); + + } + + if ( (num_axes > 1) && !File::has_extension(output_location)) + throw Exception ("Output file must be a mrtrix image ('mif' extension) for more scans with multiple axes."); + + +//----------------------------------// +// Get and Set Optional Parameters // +//----------------------------------// + + + size_t num_steps = NUM_STEPS_DEFAULT; + size_t num_steps2; + size_t num_steps3; + bool centred = false; + double axis1_scale = AXIS_SCALE_DEFAULT; + double axis2_scale; + double axis3_scale; + std::string only_prob = ""; + bool no_prob = false; + bool save_gradient = false; + bool only_first = false; + std::string prior_b_intens_gauss_mean_type; + std::string obs_image_name; + bool no_map = false; + + + + + Options opt = get_options("num_steps"); + if (opt.size()) + num_steps = opt[0][0]; + + opt = get_options("num_steps2"); + if (opt.size()) + num_steps2 = opt[0][0]; + else + num_steps2 = num_steps; + + opt = get_options("num_steps3"); + if (opt.size()) + num_steps3 = opt[0][0]; + else + num_steps3 = num_steps; + + opt = get_options("centred"); + if (opt.size()) + centred = true; + + opt = get_options("axis1_scale"); + if (opt.size()) + axis1_scale = opt[0][0]; + + opt = get_options("axis2_scale"); + if (opt.size()) + axis2_scale = opt[0][0]; + else + axis2_scale = axis1_scale; + + opt = get_options("axis3_scale"); + if (opt.size()) + axis3_scale = opt[0][0]; + else + axis3_scale = axis1_scale; + + opt = get_options("only_prob"); + if (opt.size()) + only_prob = opt[0][0].c_str(); + + opt = get_options("no_prob"); + if (opt.size()) + no_prob = true; + + opt = get_options("save_gradient"); + if (opt.size()) + save_gradient = true; + + opt = get_options("only_first"); + if (opt.size()) + only_first = true; + + opt = get_options("no_map"); + if (opt.size()) + no_map = true; + + // Loads parameters to construct Diffusion::Model ('diff_' prefix) + SET_DIFFUSION_PARAMETERS; + + // Loads parameters to construct Image::Expected::*::Buffer that are inherited from Image::Observed::Buffer ('img_' prefix) + SET_IMAGE_PARAMETERS; + + // Loads parameters to construct Image::Expected::*::Buffer ('img_' prefix) + SET_EXPECTED_IMAGE_PARAMETERS; + + // Loads parameters to construct Prob::Likelihood ('like_' prefix) + SET_LIKELIHOOD_PARAMETERS; + + // Loads parameters to construct Prob::Prior ('prior_' prefix) + SET_PRIOR_PARAMETERS; + + // Loads parameters that are common to all commands. + SET_COMMON_PARAMETERS; + + +// size_t num_ref_sections = exp_num_length_sections; + +// opt = get_options("num_ref_sections"); +// if (opt.size()) +// num_ref_sections = opt[0][0]; + + + + if (num_axes > 1) { + + if (centred) + std::cout << "Warning: option '-centred' is not required with used with multi-dimension scans as non-centred scans are not available."; + + if (no_prob) + throw Exception ("The '-no_prob' option is meant to be used to generate a sequence of states can can't be used with multi-dimension scans."); + + } + + +//----------------------// +// Load observed image // +//----------------------// + + Image::Observed::Buffer obs_image; + + opt = get_options("obs_image"); + if (opt.size()) { + obs_image_name = opt[0][0].c_str(); + obs_image.load(obs_image_name); + + if (obs_image.properties().count("diff_response_SH")) { + + if (Math::matlab_str(diff_response_SH) != obs_image.properties()["diff_response_SH"]) + std::cout << std::endl << "Warning! Diffusion response function harmonics (" << Math::matlab_str(diff_response_SH) << ") do not match reference image (" << obs_image.properties()["diff_response_SH"] + ")!" << std::endl; + + } + + } + + + //----------------------------// + // Initialize Expected Image // + //----------------------------// + + + Diffusion::Model diffusion_model = Diffusion::Model::factory (diff_encodings, + diff_response_SH, + diff_adc, + diff_fa, + diff_isotropic); + + Image::Expected::Buffer* exp_image = Image::Expected::Buffer::factory(exp_type, + img_dims, + img_vox_lengths, + diffusion_model, + exp_num_length_sections, + exp_num_width_sections, + exp_interp_extent, + img_offsets, + exp_enforce_bounds, + exp_half_width); + + +//----------------------------------------------------------------// +// Auto-generate base intensity initial value/b_intens_gauss_mean // +//----------------------------------------------------------------// + + if ((exp_base_intensity < 0) && !no_prob && (!only_prob.size() || only_prob.substr(0,16) == "Prob::Likelihood")) + exp_base_intensity = exp_image->base_intensity_default(obs_image, origin_location); + + +//-----------------------// +// Initialize Likelihood // +//-----------------------// + + if (no_prob || (only_prob.size() && only_prob.substr(0,16) != "Prob::Likelihood")) + like_snr = 0.0; + + Prob::Likelihood* likelihood = Prob::Likelihood::factory(like_type, obs_image, exp_image, like_snr, like_b0_include, like_outside_scale, like_ref_b0, like_ref_signal); + + + +//------------------// +// Initialize Prior // +//------------------// + + if (no_prob || only_prob == "Prob::Likelihood") + prior_scale = 0.0; + + Prob::Prior prior (prior_scale, + prior_mag_scale, + prior_mag_aux_scale, + prior_hook_scale, + prior_hook_num_points, + prior_density_high_scale, + prior_density_low_scale, + prior_density_num_points, + prior_acs_scale, + prior_acs_mean, + prior_length_scale, + prior_length_mean); + +//----------------// +// Set Properties // +//----------------// + + std::map properties; + + + properties["method"] = "scan"; + properties["obs_image"] = obs_image_name; + if (num_axes != -1) + properties["origin"] = Fibre::Base::Object::load_matlab_str(origin_location); + properties["origin_location"] = origin_location; + + if (num_axes >= 1) { + properties["axis1"] = Fibre::Base::Object::load_matlab_str(axis1_location, axis1_scale); + properties["axis1_scale"] = str(axis1_scale); + properties["axis1_location"] = axis1_location; + properties["num_steps"] = str(num_steps); + } + + if (num_axes >= 2) { + properties["axis2"] = Fibre::Base::Object::load_matlab_str(axis2_location, axis2_scale); + properties["axis2_scale"] = str(axis2_scale); + properties["axis2_location"] = axis2_location; + properties["num_steps"] = str(num_steps); + } + + if (num_axes == 3) { + properties["axis3"] = Fibre::Base::Object::load_matlab_str(axis3_location, axis3_scale); + properties["axis3_scale"] = str(axis3_scale); + properties["axis3_location"] = axis3_location; + properties["num_steps"] = str(num_steps); + } + + properties["centred"] = str(centred); + properties["only_first"] = str(only_first); + + + if (no_prob) + properties["no_prob"] = str(no_prob); + + else { + + properties["only_prob"] = only_prob; + + ADD_DIFFUSION_PROPERTIES(properties); + + if (!obs_image.dim(X)) { + ADD_IMAGE_PROPERTIES(properties); + } + + ADD_EXPECTED_IMAGE_PROPERTIES(properties); + + ADD_LIKELIHOOD_PROPERTIES(properties); + + ADD_PRIOR_PROPERTIES(properties); + + ADD_COMMON_PROPERTIES(properties); + + } + + + +//----------------------------// +// Actually Perform the scans // +//----------------------------// + + + if (only_first) { + + if (File::has_extension(origin_location)) { + + Fibre::Strand::Set origin_set(origin_location); + Fibre::Strand origin(origin_set[0]); + + if (num_axes == 0) { + + Fibre::Strand prior_gradient; + prior_gradient = origin; + + double total_prior = prior.log_prob(origin, prior_gradient); + + std::cout << "Total Prior: " << total_prior << std::endl; + std::cout << "Total Prior Gradient:" << prior_gradient << std::endl << std::endl; + + std::map component_values = prior.get_component_values(origin); + + for (std::map::const_iterator comp_it = component_values.begin(); comp_it != component_values.end(); ++comp_it) + std::cout << "Prior " << comp_it->first << ": " << comp_it->second << std::endl; + + std::cout << std::endl; + + + + } else if (num_axes == 1) { + + Fibre::Strand::Set axis1_set(axis1_location); + Fibre::Strand axis1(axis1_set[0]); + + //Convert the 'start' and 'finish' sets into an origin and perturbation around this origin. + if (!centred) { + + Fibre::Strand::Set start_set(origin_location), end_set(axis1_location); + Fibre::Strand start(start_set[0]), end(end_set[0]); + + if (!no_map) + end = end.smallest_distance_set(start); + + axis1 = (end - start) / 2.0; + origin = start + axis1; + } + + axis1 *= axis1_scale; + + Analysis::scan(*likelihood, prior, origin, axis1, num_steps, output_location, properties, save_gradient); + + + } else if (num_axes == 2) { + + Fibre::Strand::Set axis1_set(axis1_location), axis2_set(axis2_location); + Fibre::Strand axis1(axis1_set[0]), axis2(axis2_set[0]); + + axis1 *= axis1_scale; + axis2 *= axis2_scale; + + + Analysis::scan(*likelihood, prior, origin, axis1, axis2, num_steps, num_steps2, output_location, properties); + + + } else if (num_axes == 3) { + + + Fibre::Strand::Set axis1_set(axis1_location), axis2_set(axis2_location), axis3_set(axis3_location); + Fibre::Strand axis1(axis1_set[0]),axis2(axis2_set[0]), axis3(axis3_set[0]); + + axis1 *= axis1_scale; + axis2 *= axis2_scale; + axis3 *= axis3_scale; + + Analysis::scan(*likelihood, prior, origin, axis1, axis2, axis3, num_steps, num_steps2, num_steps3, output_location, properties); + + + + } else if (num_axes == -1) + throw Exception ("Can't do pre-generated set (implied by 2 input arguments) for individual set."); + + + } else if (File::has_extension(origin_location)) { + + Fibre::Tractlet::Set origin_set(origin_location); + + Fibre::Tractlet origin(origin_set[0]); + + if (num_axes == 0) { + + + Fibre::Tractlet prior_gradient(origin); + + double total_prior = prior.log_prob(origin, prior_gradient); + + + std::cout << "Total Prior: " << total_prior << std::endl; + std::cout << "Total Prior Gradient:" << prior_gradient << std::endl << std::endl; + + std::map component_values = prior.get_component_values(origin); + + for (std::map::const_iterator comp_it = component_values.begin(); comp_it != component_values.end(); ++comp_it) + std::cout << "Prior " << comp_it->first << ": " << comp_it->second << std::endl; + + std::cout << std::endl; + + + + } else if (num_axes == 1) { + + Fibre::Tractlet::Set axis1_set(axis1_location); + Fibre::Tractlet axis1(axis1_set[0]); + + //Convert the 'start' and 'finish' sets into an origin and perturbation around this origin. + if (!centred) { + + Fibre::Tractlet::Set start_set(origin_location), end_set(axis1_location); + Fibre::Tractlet start(start_set[0]), end(end_set[0]); + + if (!no_map) + end = end.smallest_distance_set(start); + + axis1 = (end - start) / 2.0; + origin = start + axis1; + } + + axis1 *= axis1_scale; + + Analysis::scan(*likelihood, prior, origin, axis1, num_steps, output_location, properties, save_gradient); + + + } else if (num_axes == 2) { + + Fibre::Tractlet::Set axis1_set(axis1_location), axis2_set(axis2_location); + Fibre::Tractlet axis1(axis1_set[0]), axis2(axis2_set[0]); + + axis1 *= axis1_scale; + axis2 *= axis2_scale; + + Analysis::scan(*likelihood, prior, origin, axis1, axis2, num_steps, num_steps2, output_location, properties); + + + } else if (num_axes == 3) { + + + Fibre::Tractlet::Set axis1_set(axis1_location), axis2_set(axis2_location), axis3_set(axis3_location); + Fibre::Tractlet axis1(axis1_set[0]), axis2(axis2_set[0]), axis3(axis3_set[0]); + + axis1 *= axis1_scale; + axis2 *= axis2_scale; + axis3 *= axis3_scale; + + Analysis::scan(*likelihood, prior, origin, axis1, axis2, axis3, num_steps, num_steps2, num_steps3, output_location, properties); + + + + } else if (num_axes == -1) + throw Exception ("Can't do pre-generated set (implied by 2 input arguments) for individual set."); + + } else + throw Exception ("Unrecognised extension '" + File::extension(origin_location)); + + + +//******************************************** +// End only first +//********************************************* + + + + } else { + + if (File::has_extension(origin_location)) { + + Fibre::Strand::Set origin(origin_location); + + if (num_axes == 0) { + + + Fibre::Strand::Set prior_gradient(origin), likelihood_gradient(origin), gradient(origin); + Fibre::Strand::Set::Tensor likelihood_fisher(origin); //, prior_hessian(origin); + std::vector< MR::Math::Matrix > likelihood_fisher_gradient; + + double total_prior; + double likelihood_px; + + if (save_gradient) { + total_prior = prior.log_prob(origin, prior_gradient);//, prior_hessian); + likelihood_px = likelihood->log_prob_and_fisher(origin, likelihood_gradient, likelihood_fisher); + + gradient = prior_gradient; + gradient += likelihood_gradient; + + gradient.save(File::strip_extension(origin_location) + ".gradient." + File::extension(origin_location)); + prior_gradient.save(File::strip_extension(origin_location) + ".prior_gradient." + File::extension(origin_location)); + likelihood_gradient.save(File::strip_extension(origin_location) + ".likelihood_gradient." + File::extension(origin_location)); + likelihood_fisher.save(File::strip_extension(origin_location) + ".likelihood_hessian." + File::extension(origin_location) + ".tnr"); + + } else { + total_prior = prior.log_prob(origin);//, prior_hessian); + likelihood_px = likelihood->log_prob(origin); + } + + std::cout << "Total Prior: " << total_prior << std::endl; + std::cout << "Likelihood: " << likelihood_px << std::endl; + + std::map component_values = prior.get_component_values(origin); + + for (std::map::const_iterator comp_it = component_values.begin(); comp_it != component_values.end(); ++comp_it) + std::cout << "Prior " << comp_it->first << ": " << comp_it->second << std::endl; + + std::cout << std::endl; + + + std::cout << "Total Prior Gradient:" << prior_gradient << std::endl << std::endl; + + } else if (num_axes == 1) { + + + Fibre::Strand::Set axis1(axis1_location); + + //Convert the 'start' and 'finish' sets into an origin and perturbation around this origin. + if (!centred) { + + Fibre::Strand::Set start(origin_location), end(axis1_location); + + if (!no_map) + end = end.smallest_distance_set(start); + + axis1 = (end - start) / 2.0; + + origin = start + axis1; + } + + axis1 *= axis1_scale; + + Analysis::scan(*likelihood, prior, origin, axis1, num_steps, output_location, properties, save_gradient); + + + } else if (num_axes == 2) { + + Fibre::Strand::Set axis1(axis1_location), axis2(axis2_location); + + axis1 *= axis1_scale; + axis2 *= axis2_scale; + + Analysis::scan(*likelihood, prior, origin, axis1, axis2, num_steps, num_steps2, output_location, properties); + + } else if (num_axes == 3) { + + Fibre::Strand::Set axis1(axis1_location), axis2(axis2_location), axis3(axis3_location); + + axis1 *= axis1_scale; + axis2 *= axis2_scale; + axis3 *= axis3_scale; + + Analysis::scan(*likelihood, prior, origin, axis1, axis2, axis3, num_steps, num_steps2, num_steps3, output_location, properties); + + + } else if (num_axes == -1) + throw Exception ("Can't do pre-generated set (implied by 2 input arguments) for individual set."); + + + } else if (File::has_extension(origin_location)) { + + Fibre::Tractlet::Set origin(origin_location); + + if (num_axes == 0) { + + + Fibre::Tractlet::Set prior_gradient(origin), likelihood_gradient(origin), gradient(origin); + Fibre::Tractlet::Set::Tensor likelihood_fisher(origin); //prior_hessian(origin); + + double total_prior; + double likelihood_px; + + if (save_gradient) { + total_prior = prior.log_prob(origin, prior_gradient);//, prior_hessian); + likelihood_px = likelihood->log_prob_and_fisher(origin, likelihood_gradient, likelihood_fisher); + + gradient = prior_gradient; + gradient += likelihood_gradient; + + gradient.save(File::strip_extension(origin_location) + ".gradient." + File::extension(origin_location)); + prior_gradient.save(File::strip_extension(origin_location) + ".prior_gradient." + File::extension(origin_location)); + likelihood_gradient.save(File::strip_extension(origin_location) + ".likelihood_gradient." + File::extension(origin_location)); + likelihood_fisher.save(File::strip_extension(origin_location) + ".likelihood_hessian." + File::extension(origin_location) + ".tnr"); + + } else { + total_prior = prior.log_prob(origin);//, prior_hessian); + likelihood_px = likelihood->log_prob(origin); + } + + std::cout << "Total Prior: " << total_prior << std::endl; + std::cout << "Likelihood: " << likelihood_px << std::endl; + + std::map component_values = prior.get_component_values(origin); + + for (std::map::const_iterator comp_it = component_values.begin(); comp_it != component_values.end(); ++comp_it) + std::cout << "Prior " << comp_it->first << ": " << comp_it->second << std::endl; + + std::cout << std::endl; + + } else if (num_axes == 1) { + + Fibre::Tractlet::Set axis1(axis1_location); + + //Convert the 'start' and 'finish' sets into an origin and perturbation around this origin. + if (!centred) { + + Fibre::Tractlet::Set start(origin_location), end(axis1_location); + + if (!no_map) + end = end.smallest_distance_set(start); + + axis1 = (end - start) / 2.0; + origin = start + axis1; + } + + axis1 *= axis1_scale; + + Analysis::scan(*likelihood, prior, origin, axis1, num_steps, output_location, properties, save_gradient); + + + } else if (num_axes == 2) { + + Fibre::Tractlet::Set axis1(axis1_location), axis2(axis2_location); + + axis1 *= axis1_scale; + axis2 *= axis2_scale; + + Analysis::scan(*likelihood, prior, origin, axis1, axis2, num_steps, num_steps2, output_location, properties); + + } else if (num_axes == 3) { + + Fibre::Tractlet::Set axis1(axis1_location), axis2(axis2_location), axis3(axis3_location); + + axis1 *= axis1_scale; + axis2 *= axis2_scale; + axis3 *= axis3_scale; + + Analysis::scan(*likelihood, prior, origin, axis1, axis2, axis3, num_steps, num_steps2, num_steps3, output_location, properties); + + } else if (num_axes == -1) + throw Exception ("Can't do pre-generated set (implied by 2 input arguments) for individual set."); + + } else if (File::has_extension(origin_location)) { + + //Special case where the origin is actually a precalculated set of fibres + if (num_axes != -1) + throw Exception ("Set origin only allowed when exactly two arguments are provided."); + + +// Fibre::Strand::Set true_strands ("/home/tclose/data/fibre/strand/single/z.str"); + + std::vector writer_header; + writer_header.push_back("px"); + + Fibre::Strand::Set::Reader reader(origin_location); + Fibre::Strand::Set::Writer writer(output_location, reader, writer_header); + + Fibre::Strand::Set strands; + + MR::ProgressBar progress_bar ("Scanning through strand sets...", to(reader.get_extend_props()["count"])); + + while (reader.next(strands)) { + + strands.set_extend_prop("px", str(likelihood->log_prob(strands) + prior.log_prob(strands))); + writer.append(strands); + ++progress_bar; + } + + } else if (File::has_extension(origin_location)) { + + //Special case where the origin is actually a precalculated set of fibres + if (num_axes != -1) + throw Exception ("Set origin only allowed when exactly two arguments are provided."); + + std::vector writer_header; + writer_header.push_back("px"); + + Fibre::Tractlet::Set::Reader reader(origin_location); + Fibre::Tractlet::Set::Writer writer(output_location, reader, writer_header); + + Fibre::Tractlet::Set tractlets; + + MR::ProgressBar progress_bar ("Scanning through tractlet sets...", to(reader.get_extend_props()["count"])); + + while (reader.next(tractlets)) { + + tractlets.set_extend_prop("px", str(likelihood->log_prob(tractlets) + prior.log_prob(tractlets))); + writer.append(tractlets); + + ++progress_bar; + } + + + } else + throw Exception ("Unrecognised extension '" + File::extension(origin_location)); + + + } + + delete likelihood; + delete exp_image; + + +} + diff --git a/cmd/select_fibres.cpp b/cmd/select_fibres.cpp new file mode 100644 index 0000000..ac9da17 --- /dev/null +++ b/cmd/select_fibres.cpp @@ -0,0 +1,679 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Written by Thomas G. Close, 04/03/2009. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + +#include "bts/cmd.h" +#include "point.h" +#include "progressbar.h" + +#include "bts/common.h" +#include "bts/file.h" + +#include "bts/fibre/strand/set.h" +#include "bts/fibre/track/set.h" +#include "bts/fibre/tractlet/set.h" +#include "bts/fibre/properties/extended.h" + +#include "bts/fibre/base/writer.h" + + + +#include "bts/image/expected/buffer.h" + + +#include "bts/inline_functions.h" + + +#define ONE_TO_ONE(From,To) \ + (File::has_or_txt_extension(output_location)) { \ + one_to_one(input, input_location, output_location, include, degree, num_length_sections, num_tractlets, width_of_tractlet, strands_per_acs, num_width_sections); \ + } \ + +#define ONE_TO_SET(From,To) \ + (File::has_extension(output_location)) { \ + Fibre::To::Set::Writer writer(output_location, input); \ + one_to_set(input, input_location, output_location, writer, include, degree, num_length_sections, num_tractlets, width_of_tractlet, strands_per_acs, num_width_sections, separate_sets); \ + } + +#define ONE_TO_TXT_SET(From,To) \ + (File::has_txt_extension(output_location)) { \ + Fibre::Base::SetTextWriter writer(output_location, input); \ + one_to_set >(input, input_location, output_location, writer, include, degree, num_length_sections, num_tractlets, width_of_tractlet, strands_per_acs, num_width_sections, separate_sets); \ + } + +#define SET_TO_SET(From,To) \ + (File::has_extension(output_location)) { \ + add_extra_element_properties(elem_header); \ + Fibre::To::Set::Writer writer(output_location, reader, reader.extend_prop_keys(), elem_header, reader.get_extend_props()); \ + set_to_set(input_location, output_location, reader, writer, include, degree, num_length_sections, num_tractlets, width_of_tractlet, strands_per_acs, num_width_sections); \ + } + +#define SET_TO_ONE(From,To) \ + (File::has_or_txt_extension(output_location)) { \ + set_to_one(input_location, output_location, reader, include, degree, num_length_sections, num_tractlets, width_of_tractlet, strands_per_acs, num_width_sections); \ + } \ + +#define SET_TO_TXT_SET(From,To) \ + (File::has_txt_extension(output_location)) { \ + add_extra_element_properties(elem_header); \ + Fibre::Base::SetTextWriter writer(output_location, reader, reader.extend_prop_keys(), elem_header, reader.get_extend_props()); \ + set_to_set >(input_location, output_location, reader, writer, include, degree, num_length_sections, num_tractlets, width_of_tractlet, strands_per_acs, num_width_sections); \ + } + +#define TXT_SET_TO_ONE(From,To) \ + (File::has_or_txt_extension(output_location)) { \ + set_to_one >(input_location, output_location, reader, include, degree, num_length_sections, num_tractlets, width_of_tractlet, strands_per_acs, num_width_sections); \ + } + +#define TXT_SET_TO_SET(From,To) \ + (File::has_extension(output_location)) { \ + add_extra_element_properties(elem_header); \ + Fibre::To::Set::Writer writer(output_location, reader, reader.extend_prop_keys(), elem_header, reader.get_extend_props()); \ + set_to_set , Fibre::To::Set::Writer>(input_location, output_location, reader, writer, include, degree, num_length_sections, num_tractlets, width_of_tractlet, strands_per_acs, num_width_sections); \ + } + +#define TXT_SET_TO_TXT_SET(From,To) \ + (File::has_txt_extension(output_location)) { \ + add_extra_element_properties(elem_header); \ + Fibre::Base::SetTextWriter writer(output_location, reader, reader.extend_prop_keys(), elem_header, reader.get_extend_props()); \ + set_to_set , Fibre::Base::SetTextWriter >(input_location, output_location, reader, writer, include, degree, num_length_sections, num_tractlets, width_of_tractlet, strands_per_acs, num_width_sections); \ + } + +#define ONE_CONVERSIONS(From) \ + (File::has_or_txt_extension(input_location)) { \ + Fibre::From::Set input(input_location); \ +\ + if \ + ONE_TO_ONE(From,Strand) \ + else if \ + ONE_TO_ONE(From,Tractlet) \ + else if \ + ONE_TO_ONE(From,Track) \ + else if \ + ONE_TO_SET(From,Strand) \ + else if \ + ONE_TO_SET(From,Tractlet) \ + else if \ + ONE_TO_SET(From,Track) \ + else if \ + ONE_TO_TXT_SET(From,Strand) \ + else if \ + ONE_TO_TXT_SET(From,Tractlet) \ + else if \ + ONE_TO_TXT_SET(From,Track) \ + else \ + throw Exception ("Unsupported conversion from '" + File::extension(input_location) + "' to '" + File::extension(output_location) + "'."); \ + } + +#define SET_CONVERSIONS(From) \ + (File::has_extension(input_location)) { \ + Fibre::From::Set::Reader reader(input_location); \ + std::vector elem_header = reader.extend_elem_prop_keys(); \ +\ + if \ + SET_TO_ONE(From,Strand) \ + else if \ + SET_TO_ONE(From,Tractlet) \ + else if \ + SET_TO_ONE(From,Track) \ + else if \ + SET_TO_SET(From,Strand) \ + else if \ + SET_TO_SET(From,Tractlet) \ + else if \ + SET_TO_SET(From,Track) \ + else if \ + SET_TO_TXT_SET(From,Strand) \ + else if \ + SET_TO_TXT_SET(From,Tractlet) \ + else if \ + SET_TO_TXT_SET(From,Track) \ + else \ + throw Exception ("Unsupported conversion from '" + File::extension(input_location) + "' to '" + File::extension(output_location) + "'."); \ + } + +#define TXT_SET_CONVERSIONS(From) \ + (File::has_txt_extension(input_location)) { \ + Fibre::Base::SetTextReader reader(input_location); \ + std::vector elem_header = reader.extend_elem_prop_keys(); \ +\ + if \ + TXT_SET_TO_ONE(From,Strand) \ + else if \ + TXT_SET_TO_ONE(From,Tractlet) \ + else if \ + TXT_SET_TO_ONE(From,Track) \ + else if \ + TXT_SET_TO_SET(From,Strand) \ + else if \ + TXT_SET_TO_SET(From,Tractlet) \ + else if \ + TXT_SET_TO_SET(From,Track) \ + else if \ + TXT_SET_TO_TXT_SET(From,Strand) \ + else if \ + TXT_SET_TO_TXT_SET(From,Tractlet) \ + else if \ + TXT_SET_TO_TXT_SET(From,Track) \ + else \ + throw Exception ("Unsupported conversion from '" + File::extension(input_location) + "' to '" + File::extension(output_location) + "'."); \ + } + +using namespace BTS; + + +SET_VERSION_DEFAULT; +SET_AUTHOR ("Thomas G. Close"); +SET_COPYRIGHT (NULL); + +DESCRIPTION = { + "Select a subset of strands", + "", + NULL +}; + +ARGUMENTS = { + Argument ("input", "The strands to be selected from.").type_file (), + Argument ("output", "The selected strands.").type_file (), + Argument() +}; + + +OPTIONS = { + + Option ("include","The indices of the strands to include") + + Argument ("include","").type_text(), + + Option ("bundle_include","The indices of the strands to bundle_include") + + Argument ("bundle_include","").type_text(), + + Option ("num_length_sections", "Number of samples to take along the strand path") + + Argument ("num_length_sections", "").type_integer (1, 100, 2000), + + Option ("degree", "The degree of the Strand coefficients used to describe the strands") + + Argument ("degree", "").type_integer (1, Fibre::Strand::DEFAULT_DEGREE, LARGE_INT), + + Option ("num_tractlets", "Used when converting between strands and tractlets when the strands are to first clustered into bundles then converted tractlets.") + + Argument ("num_tractlets", "").type_integer (0, -1.0, LARGE_INT), + + Option ("width_of_tractlet","Used when converting between strands and tractlets when the strands are to represent the backbone of the converted tractlets.") + + Argument ("","").type_float (-1, -1, LARGE_FLOAT), + + Option ("strands_per_acs","Basewidth of the imported tractlets.") + + Argument ("","").type_float (-1, Fibre::Tractlet::STRANDS_PER_AREA_DEFAULT, LARGE_FLOAT), + + Option ("num_width_sections","Number of samples across the tractlet radius.") + + Argument ("num_width_sections","").type_integer (0, Image::Expected::Buffer::NUM_WIDTH_SECTIONS_DEFAULT, LARGE_INT), + + Option ("separate_sets","Separate selected strands into separate sets."), + + + + +Option() }; + +//FIXME: Move this into file.h once all the dependencies have been sorted out. + + std::string class_name(const std::string& location) { + + std::string name; + + if (File::has_or_txt_extension(location)) + name = "tractlet"; + else if (File::has_or_txt_extension(location)) + name = "strand"; + else if (File::has_or_txt_extension(location)) + name = "track"; + else if (File::has_or_txt_extension(location)) + name = "tractlet set"; + else if (File::has_or_txt_extension(location)) + name = "strand set"; + else if (File::has_or_txt_extension(location)) + name = "track set"; + else + throw Exception ("Unknown extension of file '" + location + "'."); + + return name; + + } + + +template OutputType& convert(const InputType& input, OutputType& output, size_t degree, size_t num_length_sections, size_t num_tractlets, double width_of_tractlet, double strands_per_acs, size_t num_width_sections); + + +template void add_extra_element_properties(std::vector& elem_header); + + +template <> Fibre::Strand::Set& convert(const Fibre::Track::Set& input, Fibre::Strand::Set& output, size_t degree, size_t num_length_sections, size_t num_tractlets, double width_of_tractlet, double strands_per_acs, size_t num_width_sections) { + + return output = input.to_strands(degree); + +} + +template <> Fibre::Track::Set& convert(const Fibre::Strand::Set& input, Fibre::Track::Set& output, size_t degree, size_t num_length_sections, size_t num_tractlets, double width_of_tractlet, double strands_per_acs, size_t num_width_sections) { + + return output = input.to_tracks(num_length_sections); + +} + +template <> Fibre::Tractlet::Set& convert(const Fibre::Strand::Set& input, Fibre::Tractlet::Set& output, size_t degree, size_t num_length_sections, size_t num_tractlets, double width_of_tractlet, double strands_per_acs, size_t num_width_sections) { + + if (num_tractlets) + output = input.to_tractlets(num_tractlets); + //Requires bundle index property to be present in strand set. + else if (width_of_tractlet > 0) + output = input.to_tractlets(width_of_tractlet); + //Each strand is treated as the primary strand of a tractlet with base width 'width_of_tractlet'. + else + output = input.to_tractlets(); + + + return output; + +} + +template <> Fibre::Strand::Set& convert(const Fibre::Tractlet::Set& input, Fibre::Strand::Set& output, size_t degree, size_t num_length_sections, size_t num_tractlets, double width_of_tractlet, double strands_per_acs, size_t num_width_sections) { + + if (strands_per_acs > 0) + output = input.to_strands(strands_per_acs); + else if (num_width_sections > 0) + output = input.to_strands(num_width_sections); + else + throw Exception ("either strands_per_acs or num_width_sections needs to be set."); + + return output; + +} + +template <> Fibre::Track::Set& convert(const Fibre::Tractlet::Set& input, Fibre::Track::Set& output, size_t degree, size_t num_length_sections, size_t num_tractlets, double width_of_tractlet, double strands_per_acs, size_t num_width_sections) { + + Fibre::Strand::Set strands; + + if (strands_per_acs > 0) + strands = input.to_strands(strands_per_acs); + else if (num_width_sections > 0) + strands = input.to_strands(num_width_sections); + else + throw Exception ("either strands_per_acs or num_width_sections needs to be set."); + + return output = strands.to_tracks(num_length_sections); + +} + +template <> Fibre::Tractlet::Set& convert(const Fibre::Track::Set& input, Fibre::Tractlet::Set& output, size_t degree, size_t num_length_sections, size_t num_tractlets, double width_of_tractlet, double strands_per_acs, size_t num_width_sections) { + + + if (num_tractlets) + output = input.to_tractlets(degree,num_tractlets); + //Requires bundle index property to be present in strand set. + else if (width_of_tractlet > 0) + output = input.to_tractlets(degree, width_of_tractlet); + //Each strand is treated as the primary strand of a tractlet with base width 'width_of_tractlet'. + else + output = input.to_tractlets(degree); + + return output; + +} + +template OutputType& convert(const InputType& input, OutputType& output, size_t degree, size_t num_length_sections, size_t num_tractlets, double width_of_tractlet, double strands_per_acs, size_t num_width_sections) { + + return output = OutputType(input); + +} + + + +template <> void add_extra_element_properties(std::vector& header) { + + if (std::find(header.begin(), header.end(), Fibre::Track::BUNDLE_INDEX_EPROP) == header.end()) + header.push_back(Fibre::Track::BUNDLE_INDEX_EPROP); + + std::vector::iterator prop_it = std::find(header.begin(), header.end(), str("tract_volume")); + + if (prop_it != header.end()) + header.erase(prop_it); + +} + + +template <> void add_extra_element_properties(std::vector& header) { + + if (std::find(header.begin(), header.end(), Fibre::Track::BUNDLE_INDEX_EPROP) == header.end()) + header.push_back(Fibre::Track::BUNDLE_INDEX_EPROP); + + std::vector::iterator prop_it = std::find(header.begin(), header.end(), str("tract_volume")); + + if (prop_it != header.end()) + header.erase(prop_it); + + + +} + +template void add_extra_element_properties(std::vector& elem_header) { /* do nothing */ } + + + +template + void one_to_one( + const typename InputType::Set& input, + const std::string& input_location, + const std::string& output_location, + std::vector& include, + size_t degree, + size_t num_length_sections, + size_t num_tractlets, + double width_of_tractlet, + double strands_per_acs, + size_t num_width_sections) { + + typename InputType::Set selected; + typename OutputType::Set output(input.get_extend_props()); + + if (include.size()) + input.select(selected, include); + else + selected = input; + + MR::ProgressBar progress_bar("Selecting from " + class_name(input_location) + " set and outputting to " + class_name(output_location) + " set..."); + + convert(selected, output, degree, num_length_sections, num_tractlets, width_of_tractlet, strands_per_acs, num_width_sections); + + output.save(output_location); + +} + +template + void set_to_set( const std::string& input_location, + const std::string& output_location, + ReaderType& reader, + WriterType& writer, + std::vector& include, + size_t degree, + size_t num_length_sections, + size_t num_tractlets, + double width_of_tractlet, + double strands_per_acs, + size_t num_width_sections) { + + InputType input_set; + + size_t index = 0; + + size_t num_included_sets; + + if (include.size()) + num_included_sets = include.size(); + else + num_included_sets = to(reader.get_extend_props()["count"]); + + MR::ProgressBar progress_bar("Selecting from set of " + class_name(input_location) + "s and outputting to set of " + class_name(output_location) + "s...", num_included_sets); + + while (reader.next(input_set)) { + + if (!include.size() || std::find(include.begin(), include.end(), index) != include.end()) { + + OutputType output_set; + + convert(input_set, output_set, degree, num_length_sections, num_tractlets, width_of_tractlet, strands_per_acs, num_width_sections); + + writer.append(output_set); + + progress_bar++; + } + + ++index; + } + +} + +template + void set_to_one( const std::string& input_location, + const std::string& output_location, + ReaderType& reader, + std::vector& include, + size_t degree, + size_t num_length_sections, + size_t num_tractlets, + double width_of_tractlet, + double strands_per_acs, + size_t num_width_sections) { + + InputType input_set; + + + if (!reader.next(input_set)) + throw Exception ("No sets found in file '" + input_location + "'."); + + reader.rewind(); + + std::map props = input_set.get_extend_props(); + + props["base_intensity"] = "1.0"; + + std::vector header; + + //Add extra element properties that might be generated in the conversion process. + add_extra_element_properties< typename InputType::Element, OutputType>(header); + + + Fibre::Base::Writer writer (output_location, Fibre::Base::Object::select_props(reader.elem_prop_keys()), header); + + size_t index = 0; + + size_t num_included_sets; + + if (include.size()) + num_included_sets = include.size(); + else + num_included_sets = to(reader.get_extend_props()["count"]); + + MR::ProgressBar progress_bar("Selecting from set of " + class_name(input_location) + "s and outputting to " + class_name(output_location) + " set...", num_included_sets); + + while (reader.next(input_set)) { + + if (!include.size() || std::find(include.begin(), include.end(), index) != include.end()) { + + typename OutputType::Set output_set; + + convert(input_set, output_set, degree, num_length_sections, num_tractlets, width_of_tractlet, strands_per_acs, num_width_sections); + + for (size_t fibre_i = 0; fibre_i < output_set.size(); ++fibre_i) + writer.append(output_set[fibre_i], output_set.get_extend_elem_prop_row(fibre_i)); + + progress_bar++; + } + + ++index; + } + +} + +template + void one_to_set( const typename InputType::Set& input, + const std::string& input_location, + const std::string& output_location, + WriterType& writer, + std::vector& include, + size_t degree, + size_t num_length_sections, + size_t num_tractlets, + double width_of_tractlet, + double strands_per_acs, + size_t num_width_sections, + bool separate_sets) { + + typename InputType::Set selected; + OutputType converted; + + if (include.size()) + input.select(selected, include); + else + selected = input; + + convert(selected, converted, degree, num_length_sections, num_tractlets, width_of_tractlet, strands_per_acs, num_width_sections); + + if (separate_sets) { + + MR::ProgressBar progress_bar("Selecting from " + class_name(input_location) + " set and outputting into set of " + class_name(output_location) + "s, with one fibre per set...",selected.size()); + + for (size_t elem_i = 0; elem_i < converted.size(); ++elem_i) { + + OutputType output_set; + + output_set.push_back(converted[elem_i]); + + writer.append(output_set); + + ++progress_bar; + + } + + } else { + + MR::ProgressBar progress_bar("Selecting from " + class_name(input_location) + " set and outputting into a singleton set of " + class_name(output_location) + "s..."); + + writer.append(converted); + + } +} + + +EXECUTE { + + std::string input_location = argument[0]; + std::string output_location = argument[1]; + + std::vector include; + std::vector bundle_include; + size_t degree = Fibre::Strand::DEFAULT_DEGREE; + size_t num_length_sections = Fibre::Track::NUM_LENGTH_SECTIONS_DEFAULT; + size_t num_tractlets = 0; + double width_of_tractlet = -1; + double strands_per_acs = Fibre::Tractlet::STRANDS_PER_AREA_DEFAULT; + size_t num_width_sections = 0; //Image::Expected::Buffer::NUM_WIDTH_SECTIONS_DEFAULT; + bool separate_sets = false; + + Options opt = get_options("include"); + if (opt.size()) + include = parse_sequence (opt[0][0]); + + opt = get_options("bundle_include"); + if (opt.size()) + bundle_include = parse_sequence (opt[0][0]); + + opt = get_options("num_length_sections"); + if (opt.size()) + num_length_sections = opt[0][0]; + + opt = get_options("degree"); + if (opt.size()) + degree = opt[0][0]; + + opt = get_options("num_tractlets"); + if (opt.size()) + num_tractlets = opt[0][0]; + + opt = get_options("width_of_tractlet"); + if (opt.size()) + width_of_tractlet = opt[0][0]; + + opt = get_options("num_width_sections"); + if (opt.size()) { + num_width_sections = opt[0][0]; + strands_per_acs = -1.0; + } + + opt = get_options("strands_per_acs"); + if (opt.size()) + strands_per_acs = opt[0][0]; + + opt = get_options("separate_sets"); + if (opt.size()) + separate_sets = true; + + + if (include.size() && bundle_include.size()) + throw Exception ("'-include' and '-bundle_include' cannot be used simultaneously."); + + //If bundle_include option provided get bundle_index property and map to individual fibres. + if (bundle_include.size()) { + if (File::has_or_txt_extension(input_location) || File::has_or_txt_extension(input_location)) { + + //Although the input could also be a Track set, they can be loaded temporarily as strands first. + Fibre::Strand::Set strands (input_location,(size_t)1); + + if (!strands.has_extend_elem_prop(Fibre::Track::BUNDLE_INDEX_EPROP)) + throw Exception ("'" + Fibre::Track::BUNDLE_INDEX_EPROP + "' was not found in input strand set."); + + for (size_t strand_i = 0; strand_i < strands.size(); ++strand_i) { + + size_t bundle_index = to(strands.get_extend_elem_prop(Fibre::Track::BUNDLE_INDEX_EPROP, strand_i)); + + if (std::find(bundle_include.begin(), bundle_include.end(), bundle_index) != bundle_include.end()) + include.push_back(strand_i); + + } + + } + + } + + if ((strands_per_acs > 0) && num_width_sections) + throw Exception ("'-num_width_sections' and '-strands_per_acs' option cannot be used in conjunction."); + + else if ((strands_per_acs <= 0.0) && !num_width_sections && (File::has_txt_or_set_extension(input_location) && (File::has_txt_or_set_extension(output_location) || File::has_txt_or_set_extension(output_location)))) + throw Exception ("Either '-num_width_sections' and '-strands_per_acs' must be supplied for conversion from tractlet to strand/track classes."); + + + + MR::ProgressBar progress_bar ("Selecting fibres ..."); + + if + ONE_CONVERSIONS(Strand) + else if + ONE_CONVERSIONS(Tractlet) + else if + ONE_CONVERSIONS(Track) + else if + SET_CONVERSIONS(Strand) + else if + SET_CONVERSIONS(Tractlet) + else if + SET_CONVERSIONS(Track) + else if + TXT_SET_CONVERSIONS(Strand) + else if + TXT_SET_CONVERSIONS(Tractlet) + else if + TXT_SET_CONVERSIONS(Track) + else + throw Exception ("Unsupported input file '" + File::extension(input_location) + "'."); + + } + + + + + + + diff --git a/cmd/select_image.cpp b/cmd/select_image.cpp new file mode 100644 index 0000000..a5607eb --- /dev/null +++ b/cmd/select_image.cpp @@ -0,0 +1,125 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + + +extern "C" { +#include +#include +} + + +#include "bts/cmd.h" +#include "progressbar.h" + +#include "bts/common.h" +#include "bts/image/expected/buffer.h" +#include "bts/image/observed/buffer.h" + +#include "bts/image/noise.h" +#include "bts/image/noise/gaussian.h" + + + +#include "bts/inline_functions.h" + +using namespace BTS; + +SET_VERSION_DEFAULT; +SET_AUTHOR ("Thomas G. Close"); +SET_COPYRIGHT (NULL); + +DESCRIPTION = { + "Selects a rectangular region of interest from a larger image.", + "", + NULL +}; + +ARGUMENTS = { + Argument ("initial", "The initial image the second image will be subtracted from.").type_file(), + + Argument ("output_image", "The resulting image").type_file (), + + Argument() +}; + + +OPTIONS = { + + Option ("dims", "The number of voxels along each dimension") + + Argument ("dims", "").type_text ("[3,3,3]"), + + Option ("offsets", "The offset of the centre of the image from the origin (0,0,0).") + + Argument ("offsets", "").type_text ("auto"), + + +Option() + +}; + + + +EXECUTE { + + + Triple dims (3,3,3); + Triple offsets (0,0,0); + + Options opt = get_options("dims"); + if (opt.size()) + dims = parse_triple(std::string(opt[0][0])); + + opt = get_options("offsets"); + if (opt.size()) + offsets = parse_triple(std::string(opt[0][0])); + + + std::string input_location = argument[0]; + std::string output_location = argument[1]; + + Image::Observed::Buffer in(input_location); + + + Triple spatial_offset = in.vox_lengths() * offsets + in.offsets(); + + Image::Observed::Buffer out(dims, in.vox_lengths(), spatial_offset, in.get_encodings()); + + + for (size_t x = 0; x < dims[X]; ++x) + for (size_t y = 0; y < dims[Y]; ++y) + for (size_t z = 0; z < dims[Z]; ++z) + out(x,y,z) = in(x + offsets[X], y + offsets[Y], z + offsets[Z]); + + + out.properties()["original_image"] = input_location; + out.properties()["offsets"] = str(offsets); + + +//-------------// +// Save Image // +//-------------// + + out.save(output_location); + + +} + + diff --git a/cmd/set_properties.cpp b/cmd/set_properties.cpp new file mode 100644 index 0000000..550331a --- /dev/null +++ b/cmd/set_properties.cpp @@ -0,0 +1,166 @@ +/* + Copyright 2010 Brain Research Institute, Melbourne, Australia + + Written by Thomas G. Close, Apr 21, 2010. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + + +#include "bts/cmd.h" + +#include "bts/file.h" + +#include "progressbar.h" + +#include "bts/fibre/strand/set.h" +#include "bts/fibre/tractlet/set.h" +#include "bts/fibre/track/set.h" +#include "bts/fibre/base/set_reader.h" +#include "bts/fibre/base/set_writer.h" + + +#include "bts/inline_functions.h" + +using namespace BTS; + +SET_VERSION_DEFAULT; +SET_AUTHOR ("Thomas G. Close"); +SET_COPYRIGHT (NULL); + +DESCRIPTION = { + "set_extend_elem_prop.cpp", + "", + NULL +}; + +ARGUMENTS = { + + Argument ("input", "Input file location").type_file (), + Argument ("output", "Output file location").optional().type_file (), + +Argument()}; + + +OPTIONS = { + + Option ("set", "Set a property to a new value").allow_multiple() + + Argument ("name", "Name of property") + + Argument ("value", "Value the property will be set to."), + +Option() }; + + +template void set_properties(const std::string& input_location, const std::string& output_location, App::Options& opt) { + + typename T::Set fibres (input_location); + + for (size_t prop_i = 0; prop_i < opt.size(); ++prop_i) { + + std::string property_name = opt[prop_i][0]; + std::string property_value = opt[prop_i][1]; + + if (property_name == "base_intensity") + fibres.set_base_intensity(to(property_value)); + else + fibres.set_extend_prop(property_name, property_value); + + } + + fibres.save(output_location); + + +} + + + +template void set_set_properties(const std::string& input_location, const std::string& output_location, App::Options& opt) { + + if (input_location == output_location) + throw Exception ("Input and output locations cannot be the same for fibre sets."); + + typename T::Reader reader (input_location); + + std::map properties = reader.get_extend_props(); + + for (size_t prop_i = 0; prop_i < opt.size(); ++prop_i) { + + std::string property_name = opt[prop_i][0]; + std::string property_value = opt[prop_i][1]; + + properties[property_name] = property_value; + + } + + typename T::Writer writer(output_location, reader, properties); + + T strands; + + while (reader.next(strands)) + writer.append(strands); + +} + + +EXECUTE { + + std::string input_location = argument[0]; + std::string output_location; + + if (argument.size() > 1) + output_location = argument[1].c_str(); + else + output_location = input_location; + + MR::ProgressBar progress_bar ("Setting properties..."); + + Options opt = get_options("set"); + + if (File::has_or_txt_extension(input_location)) { + + set_properties(input_location, output_location, opt); + + } else if (File::has_or_txt_extension(input_location)) { + + set_properties(input_location, output_location, opt); + + } else if (File::has_or_txt_extension(input_location)) { + + set_properties(input_location, output_location, opt); + + } else if (File::has_extension(input_location)) { + + set_set_properties(input_location, output_location, opt); + + } else if (File::has_extension(input_location)) { + + set_set_properties(input_location, output_location, opt); + + } else if (File::has_extension(input_location)) { + + set_set_properties(input_location, output_location, opt); + + } else + throw Exception ("Unrecognised extension '" + File::extension(input_location) + "'."); + + //MR::ProgressBar::done(); + } + + + + + diff --git a/cmd/shortest_distance.cpp b/cmd/shortest_distance.cpp new file mode 100644 index 0000000..e0945a9 --- /dev/null +++ b/cmd/shortest_distance.cpp @@ -0,0 +1,132 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, Mar 14, 2011. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + + +#include "bts/cmd.h" + +#include "bts/common.h" + +#include "bts/fibre/tractlet/set.h" +#include "bts/fibre/strand/set.h" +#include "bts/fibre/track/set.h" + +#include "bts/inline_functions.h" + +using namespace BTS; + +SET_VERSION_DEFAULT; +SET_AUTHOR ("Thomas G. Close"); +SET_COPYRIGHT (NULL); + + +DESCRIPTION = { + "Map colours to reference set by switching bundle indices to closest match.", + "", + NULL +}; + +ARGUMENTS = { + Argument ("reference","Reference fibres the match fibres will be mapped to.").type_file (), + Argument ("samples","Fibre samples that stats will collected from.").type_file (), + Argument ("output","Output filename, if not provided will be same as samples with 'stat' extension.").optional().type_file (), + Argument() +}; + + +OPTIONS = { + +Option() }; + + +EXECUTE { + + std::string reference_location = argument[0]; + std::string samples_location = argument[1]; + std::string output_location = File::strip_extension(samples_location) + ".shrt." + File::extension(samples_location); + + if (argument.size() == 3) + output_location = argument[2].c_str(); + + + if (File::has_extension(reference_location)) { + + if (!File::has_extension(samples_location)) + throw Exception ("Samples location ('" + samples_location + "') does not match reference location ('" + reference_location + "')."); + + Fibre::Strand::Set reference(reference_location); + + Fibre::Strand::Set strands; + + Fibre::Strand::Set::Reader reader(samples_location); + Fibre::Strand::Set::Writer writer(output_location, reader, reader.get_extend_props()); + + MR::ProgressBar progress_bar("Calculating shortest distances...", to(reader.get_extend_props()["count"])); + + size_t count = 0; + while (reader.next(strands)) { + + if (strands.size() != reference.size()) + throw Exception ("Size of tractlet set " + str(count) + " (" + str(strands.size()) + ") does not match that of 'reference' set (" + str(reference.size()) + ")"); + + Fibre::Strand::Set shortest_dist = strands.smallest_distance_set(reference); + writer.append(shortest_dist); + + ++count; + ++progress_bar; + + } + + + } else if (File::has_extension(reference_location)) { + + if (!File::has_extension(samples_location)) + throw Exception ("Samples location ('" + samples_location + "') does not match reference location ('" + reference_location + "')."); + + Fibre::Tractlet::Set reference(reference_location); + + Fibre::Tractlet::Set tractlets; + + Fibre::Tractlet::Set::Reader reader(samples_location); + Fibre::Tractlet::Set::Writer writer(output_location, reader, reader.get_extend_props()); + + MR::ProgressBar progress_bar("Calculating shortest distances...", to(reader.get_extend_props()["count"])); + + size_t count = 0; + while (reader.next(tractlets)) { + + if (tractlets.size() != reference.size()) + throw Exception ("Size of tractlet set " + str(count) + " (" + str(tractlets.size()) + ") does not match that of 'reference' set (" + str(reference.size()) + ")"); + + Fibre::Tractlet::Set shortest_dist = tractlets.smallest_distance_set(reference); + writer.append(shortest_dist); + + ++count; + ++progress_bar; + + } + + + } else + throw Exception ("Usupported output file type ('" + output_location + "') for match of type tractlet."); + + +} diff --git a/cmd/simple_phantoms.cpp b/cmd/simple_phantoms.cpp new file mode 100644 index 0000000..be66e76 --- /dev/null +++ b/cmd/simple_phantoms.cpp @@ -0,0 +1,318 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Written by Thomas G. Close, 04/03/2009. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + +*/ + +extern "C" { +#include +#include +} + + +#include "bts/cmd.h" + +#include "bts/common.h" + +#include "bts/fibre/strand/set.h" +#include "bts/fibre/track/set.h" + + + +#include "bts/mcmc/proposal/distribution.h" +#include "bts/mcmc/proposal/distribution/gaussian.h" + +#include "bts/image/buffer.h" +#include "bts/image/expected/buffer.h" +#include "bts/diffusion/model.h" + + + +#include "bts/inline_functions.h" + +using namespace BTS; + +SET_VERSION_DEFAULT; +SET_AUTHOR ("Thomas G. Close"); +SET_COPYRIGHT (NULL); + +DESCRIPTION = { + "Generates a particular set of basic phantom configurations", + "", + NULL +}; + +ARGUMENTS = { + Argument ("", "").optional(), + Argument ("", "").optional(), + Argument() +}; + + +OPTIONS = { + + Option ("type", "Type of the basic configuration to generate. (0 - crossing, 1 - branching, 2 - kissing).") + + Argument ("type", "").type_integer (0, 2, 0), + + Option ("degree", "degree of the strands.") + + Argument ("degree", "").type_integer (1, 2000, 100), + + Option ("curve", "curve of the bends.") + + Argument ("curve", "").type_float (1e-9, INFINITY, 0.1), + + Option ("num_layers", "number of layers.") + + Argument ("num_layers", "").type_integer (1, 2000, 100), + + Option ("num_voxels", "number of voxels.") + + Argument ("num_voxels", "").type_integer (1, 2000, 100), + + Option ("voxel_size", "Size of the voxels.") + + Argument ("voxel_size", "").type_float (1e-9, INFINITY, 0.1), + + Option ("angle", "Angle of the branch (in degrees)") + + Argument ("angle", "").type_float (1e-9, INFINITY, 0.1), + + Option ("curv_angle", "Angle of the branch (in degrees)") + + Argument ("curv_angle", "").type_float (1e-9, INFINITY, 0.1), + +Option() }; + + + +EXECUTE { + + + const size_t CROSSING = 0; + const size_t BRANCHING = 1; + const size_t KISSING = 2; + + size_t type = CROSSING; + + size_t degree = 3; + double curve = 0.1; + size_t num_layers = 6; + double vox_size = 0.15; + size_t num_voxels = 3; + double angle = 30; + double curv_angle = 30; + + + + + Options opt = get_options("type"); + if (opt.size()) + type = opt[0][0]; + + opt = get_options("degree"); + if (opt.size()) + degree = opt[0][0]; + + + opt = get_options("curve"); + if (opt.size()) + curve = opt[0][0]; + + + opt = get_options("num_layers"); + if (opt.size()) + num_layers = opt[0][0]; + + + opt = get_options("num_voxels"); + if (opt.size()) + num_voxels = opt[0][0]; + + + opt = get_options("vox_size"); + if (opt.size()) + vox_size = opt[0][0]; + + + opt = get_options("angle"); + if (opt.size()) + angle = opt[0][0]; + + + opt = get_options("curv_angle"); + if (opt.size()) + curv_angle = opt[0][0]; + + + switch (type) { + + case CROSSING: { + + double extent = vox_size * (double)num_voxels / 2.0; + + double strand_diameter = 2.0 * extent / (double)num_layers; + + + Fibre::Strand straight (degree, 0.0); + + straight[1][1] = M_SQRT2 * extent; + + Fibre::Strand curved (degree, 0.0); + + curved[1][0] = M_SQRT2 * extent; + curved[2][1] = curve; + curved[0][1] = ((double)curve); + + Fibre::Strand::Set ismrm; + + ismrm.add_extend_elem_prop("bundle_index", "0"); + + + double layer_offset = - extent + strand_diameter/ 2.0; + double col_offset = - extent + strand_diameter/ 2.0; + + for (size_t layer_i = 0; layer_i < num_layers/2; layer_i++) { + + for (size_t col_i = 0; col_i < num_layers; col_i++) { + + Fibre::Strand straight_offset = straight; + Fibre::Strand curved_offset = curved; + + straight_offset[0][0] += strand_diameter * (double) col_i + col_offset; + straight_offset[0][2] += 2.0 * strand_diameter * (double) layer_i + layer_offset; + + curved_offset[0][1] += strand_diameter * (double) col_i + col_offset; + curved_offset[0][2] += 2.0 * strand_diameter * (double) layer_i + layer_offset + strand_diameter; + + ismrm.push_back(straight_offset); + ismrm.set_extend_elem_prop("bundle_index", "0", ismrm.size()-1); + + ismrm.push_back(curved_offset); + ismrm.set_extend_elem_prop("bundle_index", "1", ismrm.size()-1); + + } + + } + + ismrm.add_extend_elem_prop("track_radius", str(strand_diameter/2.0)); + + ismrm.save(PARAM_DIRECTORY + "ismrm_abstractlet/ismrm-crossing.frr"); + + break; + + } case BRANCHING: { + + + double extent = vox_size * (double)num_voxels / 2.0; + + double strand_diameter = 2.0 * extent / (double)num_layers; + + Fibre::Strand curve1 (degree, 0.0); + + double rad_angle = 2.0 * M_PI * (angle / 360.0); + + double curve_rad_angle = 2.0 * M_PI * (curv_angle / 360.0); + + + curve1[0][0] = -curve * cos(curve_rad_angle); + curve1[0][1] = 2*curve * sin(curve_rad_angle); + + curve1[1][0] = M_SQRT2 * extent * sin(rad_angle)*2; + curve1[1][1] = M_SQRT2 * extent * cos(rad_angle)*2; + + curve1[2][0] = curve * cos(curve_rad_angle); + curve1[2][1] = curve * sin(curve_rad_angle); + + Fibre::Strand curve2 = curve1; + for (size_t degree_i = 0; degree_i < degree; degree_i++) { + curve2[degree_i][1] *= -1; + + } + + + + std::cout << curve1 << std::endl; + std::cout << curve2 << std::endl; + + + Fibre::Strand::Set ismrm; + + ismrm.add_extend_elem_prop("bundle_index", "0"); + + + double layer_offset = - extent + strand_diameter/ 2.0; + double col_offset = - extent + strand_diameter/ 2.0; + + for (size_t layer_i = 0; layer_i < num_layers/2; layer_i++) { + + for (size_t col_i = 0; col_i < num_layers; col_i++) { + + Fibre::Strand curve2_offset = curve2; + Fibre::Strand curve1_offset = curve1; + + curve1_offset[0][0] += (strand_diameter * (double) col_i + col_offset) * sin(rad_angle); + curve1_offset[0][1] += -(strand_diameter * (double) col_i + col_offset) * cos(rad_angle); + + curve1_offset[0][2] += 2.0 * strand_diameter * (double) layer_i + layer_offset + strand_diameter; + + + curve2_offset[0][0] += (strand_diameter * (double) col_i + col_offset) * sin(rad_angle); + curve2_offset[0][1] += (strand_diameter * (double) col_i + col_offset) * cos(rad_angle); + + curve2_offset[0][2] += 2.0 * strand_diameter * (double) layer_i + layer_offset; + + + ismrm.push_back(curve2_offset); + ismrm.set_extend_elem_prop("bundle_index", "0", ismrm.size()-1); + + ismrm.push_back(curve1_offset); + ismrm.set_extend_elem_prop("bundle_index", "1", ismrm.size()-1); + + } + + } + + ismrm.add_extend_elem_prop("track_radius", str(strand_diameter/2.0)); + + ismrm.save(PARAM_DIRECTORY + "ismrm_abstractlet/ismrm-branching.frr"); + break; + + + } case KISSING: { + + break; + } + + } + + +} + + + + + + + + + + + + + + + + + + + diff --git a/cmd/stats_fibres.cpp b/cmd/stats_fibres.cpp new file mode 100644 index 0000000..a8f6087 --- /dev/null +++ b/cmd/stats_fibres.cpp @@ -0,0 +1,290 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, Mar 14, 2011. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + + +#include "bts/cmd.h" + +#include "bts/common.h" + +#include "bts/fibre/tractlet/set.h" +#include "bts/fibre/strand/set.h" +#include "bts/fibre/track/set.h" + +#include "bts/inline_functions.h" + +using namespace BTS; + +SET_VERSION_DEFAULT; +SET_AUTHOR ("Thomas G. Close"); +SET_COPYRIGHT (NULL); + + +DESCRIPTION = { + "Map colours to reference set by switching bundle indices to closest match.", + "", + NULL +}; + +ARGUMENTS = { + Argument ("reference","Reference fibres the match fibres will be mapped to.").type_file (), + Argument ("samples","Fibre samples that stats will collected from.").type_file (), + Argument ("output","Output filename, if not provided will be same as samples with 'stat' extension.").optional().type_file (), + Argument() +}; + + +OPTIONS = { + +Option() }; + + +EXECUTE { + + std::string reference_location = argument[0]; + std::string samples_location = argument[1]; + std::string output_location = samples_location; + + if (argument.size() == 3) + output_location = argument[2].c_str(); + + + if (File::has_extension(reference_location)) { + + if (!File::has_extension(samples_location)) + throw Exception ("Samples location ('" + samples_location + "') does not match reference location ('" + reference_location + "')."); + + Fibre::Strand::Set reference(reference_location); + + Fibre::Strand::Set strands; + + Fibre::Strand::Set::Reader reader(samples_location); + + size_t count = 0; + + Fibre::Strand::Set average(reference); + + average.zero(); + + MR::ProgressBar progress_bar("Calculating average...", to(reader.get_extend_props()["count"])); + + std::ofstream all_out((File::strip_extension(output_location) + ".dist.txt").c_str()); + std::ofstream strand_out((File::strip_extension(output_location) + ".strdist.txt").c_str()); + std::ofstream pos_out((File::strip_extension(output_location) + ".pos.txt").c_str()); + std::ofstream orient_out((File::strip_extension(output_location) + ".orient.txt").c_str()); + std::ofstream len_out((File::strip_extension(output_location) + ".len.txt").c_str()); + std::ofstream curv_out((File::strip_extension(output_location) + ".curv.txt").c_str()); + + + while (reader.next(strands)) { + + if (strands.size() != reference.size()) + throw Exception ("Size of tractlet set " + str(count) + " (" + str(strands.size()) + ") does not match that of 'reference' set (" + str(reference.size()) + ")"); + + strands = strands.smallest_distance_set(reference); + + average += strands; + + all_out << strands.distance(reference) << std::endl; + + for (size_t strand_i = 0; strand_i < strands.size(); ++ strand_i) { + + strand_out << strands[strand_i].distance(reference[strand_i]) << " "; + pos_out << (strands[strand_i][0] - reference[strand_i][0]).norm() << " "; + orient_out << strands[strand_i][1].angle(reference[strand_i][1]) << " "; + len_out << strands[strand_i][1].norm() - reference[strand_i][1].norm() << " "; + curv_out << (strands[strand_i][2] - reference[strand_i][2]).norm() * SQRT_2 << " "; + + + + } + + strand_out << std::endl; + pos_out << std::endl; + orient_out << std::endl; + len_out << std::endl; + curv_out << std::endl; + + + ++count; + ++progress_bar; + + } + + + average /= (double)count; + + average.save(File::strip_extension(output_location) + ".avg.str"); + + Fibre::Strand::Set variance(reference); + + variance.zero(); + + count = 0; + + reader.rewind(); + + while (reader.next(strands)) { + + if (strands.size() != reference.size()) + throw Exception ("Size of tractlet set " + str(count) + " (" + str(strands.size()) + ") does not match that of 'reference' set (" + str(reference.size()) + ")"); + + Fibre::Strand::Set deviation = strands.smallest_distance_set(reference); + + deviation -= average; + + deviation *= deviation; + + variance += deviation; + + ++count; + ++progress_bar; + + } + + variance /= (double)count; + + variance.save(File::strip_extension(output_location) + ".var.str"); + + } else if (File::has_extension(reference_location)) { + + if (!File::has_extension(samples_location)) + throw Exception ("Samples location ('" + samples_location + "') does not match reference location ('" + reference_location + "')."); + + Fibre::Tractlet::Set reference(reference_location); + + Fibre::Tractlet::Set tractlets; + + Fibre::Tractlet::Set::Reader reader(samples_location); + + size_t count = 0; + + Fibre::Tractlet::Set average(reference); + + average.zero(); + + MR::ProgressBar progress_bar("Calculating average...", to(reader.get_extend_props()["count"])); + + std::ofstream all_out((File::strip_extension(output_location) + ".dist.txt").c_str()); + std::ofstream tractlet_out((File::strip_extension(output_location) + ".tctdist.txt").c_str()); + std::ofstream pos_out((File::strip_extension(output_location) + ".pos.txt").c_str()); + std::ofstream perp_out((File::strip_extension(output_location) + ".perp.txt").c_str()); + std::ofstream orient_out((File::strip_extension(output_location) + ".orient.txt").c_str()); + std::ofstream len_out((File::strip_extension(output_location) + ".len.txt").c_str()); + std::ofstream curv_out((File::strip_extension(output_location) + ".curv.txt").c_str()); + + std::ofstream width1_out((File::strip_extension(output_location) + ".width1.txt").c_str()); + std::ofstream width2_out((File::strip_extension(output_location) + ".width2.txt").c_str()); + + std::ofstream acs_out((File::strip_extension(output_location) + ".area.txt").c_str()); + + std::ofstream rot_out((File::strip_extension(output_location) + ".rot.txt").c_str()); + + while (reader.next(tractlets)) { + + if (tractlets.size() != reference.size()) + throw Exception ("Size of tractlet set " + str(count) + " (" + str(tractlets.size()) + ") does not match that of 'reference' set (" + str(reference.size()) + ")"); + + tractlets = tractlets.smallest_distance_set(reference); + + average += tractlets; + + all_out << tractlets.distance(reference) << std::endl; + + for (size_t tractlet_i = 0; tractlet_i < tractlets.size(); ++ tractlet_i) { + + tractlet_out << tractlets[tractlet_i].distance(reference[tractlet_i]) << " "; + + pos_out << (tractlets[tractlet_i][0][0] - reference[tractlet_i][0][0]).norm() << " "; + perp_out << (tractlets[tractlet_i][0][0] - tractlets[tractlet_i][0][0].dot(tractlets[tractlet_i][0][1])/tractlets[tractlet_i][0][1].norm() + - reference[tractlet_i][0][0] + reference[tractlet_i][0][0].dot(reference[tractlet_i][0][1])/reference[tractlet_i][0][1].norm()).norm() << " "; + orient_out << tractlets[tractlet_i][0][1].angle(reference[tractlet_i][0][1]) << " "; + len_out << tractlets[tractlet_i][0][1].norm() - reference[tractlet_i][0][1].norm() << " "; + curv_out << (tractlets[tractlet_i][0][2] - reference[tractlet_i][0][2]).norm() * SQRT_2 << " "; + + width1_out << (tractlets[tractlet_i][1][0] - reference[tractlet_i][1][0]).norm() * SQRT_2 << " "; + width2_out << (tractlets[tractlet_i][2][0] - reference[tractlet_i][2][0]).norm() * SQRT_2 << " "; + + acs_out << tractlets[tractlet_i].acs() - reference[tractlet_i].acs() << " "; + + rot_out << tractlets[tractlet_i].rotation() << " "; + + } + + tractlet_out << std::endl; + pos_out << std::endl; + perp_out << std::endl; + orient_out << std::endl; + len_out << std::endl; + curv_out << std::endl; + + width1_out << std::endl; + width2_out << std::endl; + acs_out << std::endl; + + rot_out << std::endl; + + + ++count; + ++progress_bar; + + } + + + average /= (double)count; + + average.save(File::strip_extension(output_location) + ".avg.tct"); + + Fibre::Tractlet::Set variance(reference); + + variance.zero(); + + count = 0; + + reader.rewind(); + + while (reader.next(tractlets)) { + + if (tractlets.size() != reference.size()) + throw Exception ("Size of tractlet set " + str(count) + " (" + str(tractlets.size()) + ") does not match that of 'reference' set (" + str(reference.size()) + ")"); + + Fibre::Tractlet::Set deviation = tractlets.smallest_distance_set(reference); + + deviation -= average; + + deviation *= deviation; + + variance += deviation; + + ++count; + ++progress_bar; + + } + + variance /= (double)count; + + variance.save(File::strip_extension(output_location) + ".var.tct"); + + } else + throw Exception ("Usupported output file type ('" + output_location + "') for match of type tractlet."); + + +} diff --git a/cmd/stress_tester.cpp b/cmd/stress_tester.cpp new file mode 100644 index 0000000..f6af452 --- /dev/null +++ b/cmd/stress_tester.cpp @@ -0,0 +1,717 @@ + + +extern "C" { +#include +#include +} + +#include "math/matrix.h" +#include "exception.h" + +#include "bts/cmd.h" +#include "bts/common.h" +#include "bts/file.h" + +#include "bts/fibre/base/set.h" +#include "bts/fibre/track/set.h" + + +using namespace BTS; + + +std::vector< std::vector > recreate_objects(const std::vector& elem_props) { + + std::vector< std::vector > objects(10); + + for (size_t size_i = 0; size_i < 10; ++size_i) { + objects[size_i]; + for (size_t value_i = 0; value_i < 10; ++value_i) { + objects[size_i].push_back(Fibre::Base::Object(size_i, 3, elem_props)); + objects[size_i][value_i].set(value_i+1001); + } + } + + return objects; + +} + +std::vector< std::map > recreate_prop_row_maps(const std::vector& elem_props) { + + std::vector< std::map > prop_row_maps(10); + + for (size_t value_i = 0; value_i < 10; ++value_i) { + for (size_t key_i = 0; key_i < elem_props.size(); ++key_i) + prop_row_maps[value_i][elem_props[key_i]] = (double)(value_i+1) * 0.01 + (double)(key_i+1) * 0.1 + 0.001; + } + + return prop_row_maps; + +} + +std::vector< std::vector > recreate_prop_rows(const std::vector& elem_props) { + + std::vector< std::vector > prop_rows(10); + + for (size_t value_i = 0; value_i < 10; ++value_i) { + for (size_t key_i = 0; key_i < elem_props.size(); ++key_i) + prop_rows[value_i].push_back((double)(value_i+1) * 0.01 + (double)(key_i+1) * 0.1 + 0.001); + } + + return prop_rows; + +} + + +std::vector< std::map > create_ext_prop_row_maps() { + + std::vector< std::map > prop_rows(10); + + for (size_t value_i = 0; value_i < 10; ++value_i) { + for (size_t key_i = 1; key_i < 11; ++key_i) + prop_rows[value_i]["EXT_ELEM_PROP_" +str(key_i)] = str((double)(value_i+1) * 0.01 + (double)key_i * 1.1 + 0.001); + } + + return prop_rows; + +} + +void recreate_elem_prop_objects(const std::vector& elem_props, std::vector >& objects, std::vector< std::map >& prop_row_maps, std::vector< std::vector >& prop_rows) { + + objects = recreate_objects(elem_props); + prop_row_maps = recreate_prop_row_maps(elem_props); + prop_rows = recreate_prop_rows(elem_props); + +} + +SET_VERSION_DEFAULT; +SET_AUTHOR ("Thomas G. Close"); +SET_COPYRIGHT (NULL); + +DESCRIPTION = { + "Tests a random sequence of Fibre::Base::Set operations against those performed on a Python version.", + "", + NULL +}; + +ARGUMENTS = { + + + Argument() +}; + + +OPTIONS = { + +Option() }; + + +EXECUTE { + + size_t SET_SIZE = 5; + size_t OBJECT_SIZE = 5; + + const char* PROP_1 = "PROP_1"; + const char* PROP_2 = "PROP_2"; + const char* PROP_3 = "PROP_3"; + const char* PROP_4 = "PROP_4"; + const char* PROP_5 = "PROP_5"; + const char* PROP_6 = "PROP_6"; + const char* PROP_7 = "PROP_7"; + const char* PROP_8 = "PROP_8"; + const char* PROP_9 = "PROP_9"; + const char* PROP_10 = "PROP_10"; + + const char* ELEM_PROP_1 = "ELEM_PROP_1"; + const char* ELEM_PROP_2 = "ELEM_PROP_2"; + const char* ELEM_PROP_3 = "ELEM_PROP_3"; + const char* ELEM_PROP_4 = "ELEM_PROP_4"; + const char* ELEM_PROP_5 = "ELEM_PROP_5"; + const char* ELEM_PROP_6 = "ELEM_PROP_6"; + const char* ELEM_PROP_7 = "ELEM_PROP_7"; + const char* ELEM_PROP_8 = "ELEM_PROP_8"; + const char* ELEM_PROP_9 = "ELEM_PROP_9"; + const char* ELEM_PROP_10 = "ELEM_PROP_10"; + + std::string EXT_ELEM_PROP_1 = "EXT_ELEM_PROP_1"; + std::string EXT_ELEM_PROP_2 = "EXT_ELEM_PROP_2"; + std::string EXT_ELEM_PROP_3 = "EXT_ELEM_PROP_3"; + std::string EXT_ELEM_PROP_4 = "EXT_ELEM_PROP_4"; + std::string EXT_ELEM_PROP_5 = "EXT_ELEM_PROP_5"; + std::string EXT_ELEM_PROP_6 = "EXT_ELEM_PROP_6"; + std::string EXT_ELEM_PROP_7 = "EXT_ELEM_PROP_7"; + std::string EXT_ELEM_PROP_8 = "EXT_ELEM_PROP_8"; + std::string EXT_ELEM_PROP_9 = "EXT_ELEM_PROP_9"; + std::string EXT_ELEM_PROP_10 = "EXT_ELEM_PROP_10"; + + std::vector props; + + props.push_back(PROP_1); + props.push_back(PROP_2); + props.push_back(PROP_3); + props.push_back(PROP_4); + props.push_back(PROP_5); + + std::vector elem_props; + + elem_props.push_back(ELEM_PROP_1); + elem_props.push_back(ELEM_PROP_2); + elem_props.push_back(ELEM_PROP_3); + elem_props.push_back(ELEM_PROP_4); + elem_props.push_back(ELEM_PROP_5); + + + std::vector< std::vector > objects = recreate_objects(elem_props); + std::vector > prop_rows = recreate_prop_rows(elem_props); + std::vector< std::map > prop_row_maps = recreate_prop_row_maps(elem_props); + + std::vector< std::map > ext_prop_row_maps = create_ext_prop_row_maps(); + + + //Iniate set + Fibre::Base::Set set(SET_SIZE, OBJECT_SIZE, 3, props, elem_props); + + for (size_t elem_i = 0; elem_i < SET_SIZE; ++elem_i) { + Fibre::Base::Object ob = set[elem_i]; + for (size_t elem_elem_i = 0; elem_elem_i < OBJECT_SIZE; ++elem_elem_i) { + Coord t = ob[elem_elem_i]; + for (size_t elem_elem_elem_i = 0; elem_elem_elem_i < 3; ++elem_elem_elem_i) + t[elem_elem_elem_i] = elem_i * 100 + elem_elem_i * 10 + elem_elem_elem_i +1; + } + + for (size_t prop_i = 0; prop_i < 5; ++prop_i) + ob.prop(prop_i) = (double)elem_i * 100.0 + (double)(prop_i+1) * .1 + 0.001; + } + + for (size_t prop_i = 0; prop_i < 5; ++prop_i) + set.prop(prop_i) = (double)(prop_i+1) * 1.1 + 0.001; + + for (size_t eprop_i = 1; eprop_i < 6; ++eprop_i) { + set.add_extend_elem_prop("EXT_ELEM_PROP_" + str(eprop_i),"NaN"); + for (size_t row_i = 0; row_i < set.size(); ++row_i) + set.set_extend_elem_prop("EXT_ELEM_PROP_" + str(eprop_i), "Ooogle " + str(eprop_i) + "-" + str(row_i), row_i); + } + + + //Iniate set + Fibre::Base::Set set2(SET_SIZE, OBJECT_SIZE, 3, props, elem_props); + + for (size_t elem_i = 0; elem_i < SET_SIZE; ++elem_i) { + Fibre::Base::Object ob = set2[elem_i]; + for (size_t elem_elem_i = 0; elem_elem_i < OBJECT_SIZE; ++elem_elem_i) { + Coord t = ob[elem_elem_i]; + for (size_t elem_elem_elem_i = 0; elem_elem_elem_i < 3; ++elem_elem_elem_i) + t[elem_elem_elem_i] = -(double)(elem_i * 100 + elem_elem_i * 10 + elem_elem_elem_i + 1); + } + + for (size_t prop_i = 0; prop_i < 5; ++prop_i) + ob.prop(prop_i) = -(double)elem_i * 100.0 - (double)(prop_i+1) * .1 - 0.001; + } + + for (size_t prop_i = 0; prop_i < 5; ++prop_i) + set2.prop(prop_i) = -(double)(prop_i+1) * 1.1 - 0.001; + + for (size_t eprop_i = 6; eprop_i < 11; ++eprop_i) { + set2.add_extend_elem_prop("EXT_ELEM_PROP_" + str(eprop_i),"NaN"); + for (size_t row_i = 0; row_i < set2.size(); ++row_i) + set2.set_extend_elem_prop("EXT_ELEM_PROP_" + str(eprop_i), "Boogle " + str(eprop_i) + "-" + str(row_i), row_i); + } + + std::ofstream out; + + out.open("/home/tclose/Code/Tractography/python/fibre/base/test/output/cpp_output.txt"); + + +// +// //==================================================================================================================== +// // Test functions start here +// //==================================================================================================================== +// +// out << "\n\n-------------------------------------\n INITIAL SET \n-------------------------------------\n\n" << set << "\n\n"; +// out << "\n\n-------------------------------------\n SECOND SET \n-------------------------------------\n\n" << set2 << "\n\n"; +// set.insert(objects[5][8],1); +// out << "set.num_elem_props(): " << set.num_elem_props() << std::endl; +// out << "set.elem_prop_index(ELEM_PROP_4): " << set.elem_prop_index(ELEM_PROP_4) << std::endl; +// set.add_elem_prop(ELEM_PROP_2,669); +// elem_props = set.get_elem_prop_header(); recreate_elem_prop_objects(elem_props,objects,prop_row_maps,prop_rows); +// out << "set.has_extend_elem_prop(EXT_ELEM_PROP_7): " << set.has_extend_elem_prop(EXT_ELEM_PROP_7) << std::endl; +// set.add_prop(PROP_6,984); +// out << "set.num_props(): " << set.num_props() << std::endl; +// set.free_elem_degree(); +// set.remove_prop(PROP_3); +// out << "\n\n-------------------------------------\n 5 MODFICATIONS \n-------------------------------------\n\n" << set << "\n\n"; +// set.add_elem_prop(ELEM_PROP_4,463); +// elem_props = set.get_elem_prop_header(); recreate_elem_prop_objects(elem_props,objects,prop_row_maps,prop_rows); +// out << "set.bsize(): " << set.bsize() << std::endl; +// set.copy_extend_elem_prop_row(set2,3,2); +// set.copy_extend_elem_prop_row(set2,1,1); +// out << "set.size(): " << set.size() << std::endl; +// set.add_prop(PROP_9,419); +// out << "set.num_extend_elem_props(): " << set.num_extend_elem_props() << std::endl; +// out << "set.prop(PROP_9): " << set.prop(PROP_9) << std::endl; +// out << "set.elem_prop_keys(): " << set.elem_prop_keys() << std::endl; +// set.add_elem_prop(ELEM_PROP_5,661); +// out << "\n\n-------------------------------------\n 10 MODFICATIONS \n-------------------------------------\n\n" << set << "\n\n"; +// elem_props = set.get_elem_prop_header(); recreate_elem_prop_objects(elem_props,objects,prop_row_maps,prop_rows); +// set.push_back(objects[9][0], ext_prop_row_maps[3]); +// out << "set.prop_index(PROP_2): " << set.prop_index(PROP_2) << std::endl; +// out << "set.vsize(): " << set.vsize() << std::endl; +// out << "set.num_props(): " << set.num_props() << std::endl; +// set.erase(1); +// set.add_elem_prop(ELEM_PROP_4,815); +// elem_props = set.get_elem_prop_header(); recreate_elem_prop_objects(elem_props,objects,prop_row_maps,prop_rows); +// out << "set.num_extend_elem_props(): " << set.num_extend_elem_props() << std::endl; +// out << "set.prop_index(PROP_2): " << set.prop_index(PROP_2) << std::endl; +// set.add_prop(PROP_7,434); +// set.insert(objects[5][8],1); +// out << "\n\n-------------------------------------\n 15 MODFICATIONS \n-------------------------------------\n\n" << set << "\n\n"; +// out << "set.get_extend_elem_prop_header(): " << set.get_extend_elem_prop_header() << std::endl; +// out << "set.prop_keys(): " << set.prop_keys() << std::endl; +// set.free_elem_degree(); +// set.set_extend_elem_prop_row(ext_prop_row_maps[1],4); +// out << "set.prop_keys(): " << set.prop_keys() << std::endl; +// out << "set.elem_prop_keys(): " << set.elem_prop_keys() << std::endl; +// set.set_extend_elem_prop_row(ext_prop_row_maps[3],4); +// set.push_back(objects[5][6], ext_prop_row_maps[7]); +// set.erase(2); +// out << "\n\n-------------------------------------\n 20 MODFICATIONS \n-------------------------------------\n\n" << set << "\n\n"; +// set.insert(objects[1][5],5); +// set.push_back(objects[6][1]); +// out << "set.elem_prop_index(ELEM_PROP_4): " << set.elem_prop_index(ELEM_PROP_4) << std::endl; +// out << "set.elem_prop_index(ELEM_PROP_4): " << set.elem_prop_index(ELEM_PROP_4) << std::endl; +// set.resize(1,574,0); +// set.push_back(objects[0][2]); +// set.elem_resize(7,511); +// out << "\n\n-------------------------------------\n 25 MODFICATIONS \n-------------------------------------\n\n" << set << "\n\n"; +// set.push_back(objects[7][8]); +// out << "set.prop(PROP_4): " << set.prop(PROP_4) << std::endl; +// set.get_extend_elem_prop_row(1); +// set.elem_resize(8,886); +// set.add_extend_elem_props(set2); +// set.add_elem_prop(ELEM_PROP_4,734); +// out << "\n\n-------------------------------------\n 30 MODFICATIONS \n-------------------------------------\n\n" << set << "\n\n"; +// elem_props = set.get_elem_prop_header(); recreate_elem_prop_objects(elem_props,objects,prop_row_maps,prop_rows); +// out << "set.num_extend_elem_props(): " << set.num_extend_elem_props() << std::endl; +// set.freeze_elem_degree(); +// elem_props = set.get_elem_prop_header(); recreate_elem_prop_objects(elem_props,objects,prop_row_maps,prop_rows); +// out << "set.num_props(): " << set.num_props() << std::endl; +// set.insert(objects[8][4],1); +// set.remove_elem_prop(ELEM_PROP_3); +// elem_props = set.get_elem_prop_header(); recreate_elem_prop_objects(elem_props,objects,prop_row_maps,prop_rows); +// set.insert(objects[8][5],1); +// out << "set.num_extend_elem_props(): " << set.num_extend_elem_props() << std::endl; +// set.set_extend_elem_prop(EXT_ELEM_PROP_3,"733",0); +// out << "\n\n-------------------------------------\n 35 MODFICATIONS \n-------------------------------------\n\n" << set << "\n\n"; +// set.erase(2); +// set.erase(0); +// set.erase(1); +// out << "set.prop(PROP_7): " << set.prop(PROP_7) << std::endl; +// set.freeze_elem_degree(); +// elem_props = set.get_elem_prop_header(); recreate_elem_prop_objects(elem_props,objects,prop_row_maps,prop_rows); +// set.add_extend_elem_prop(EXT_ELEM_PROP_10,"-99"); +// out << "\n\n-------------------------------------\n 40 MODFICATIONS \n-------------------------------------\n\n" << set << "\n\n"; +// set.remove_extend_elem_prop(EXT_ELEM_PROP_1); +// set.free_elem_degree(); +// out << "set.num_props(): " << set.num_props() << std::endl; +// out << "set.get_extend_elem_prop(EXT_ELEM_PROP_9,0): " << set.get_extend_elem_prop(EXT_ELEM_PROP_9,0) << std::endl; +// out << "set.has_elem_prop(ELEM_PROP_9): " << set.has_elem_prop(ELEM_PROP_9) << std::endl; +// set.elem_resize(8,975); +// set.remove_elem_prop(ELEM_PROP_5); +// elem_props = set.get_elem_prop_header(); recreate_elem_prop_objects(elem_props,objects,prop_row_maps,prop_rows); +// set.remove_extend_elem_prop(EXT_ELEM_PROP_6); +// out << "\n\n-------------------------------------\n 45 MODFICATIONS \n-------------------------------------\n\n" << set << "\n\n"; +// out << "set.vsize(): " << set.vsize() << std::endl; +// set.remove_elem_prop(ELEM_PROP_1); +// elem_props = set.get_elem_prop_header(); recreate_elem_prop_objects(elem_props,objects,prop_row_maps,prop_rows); +// out << "set.elem_prop_index(ELEM_PROP_4): " << set.elem_prop_index(ELEM_PROP_4) << std::endl; +// out << "set.vsize(): " << set.vsize() << std::endl; +// set.prop_key(6); +// set.push_back(objects[8][7]); +// set.remove_extend_elem_prop(EXT_ELEM_PROP_2); +// set.remove_extend_elem_prop(EXT_ELEM_PROP_8); +// out << "\n\n-------------------------------------\n 50 MODFICATIONS \n-------------------------------------\n\n" << set << "\n\n"; +// set.add_elem_prop(ELEM_PROP_4,776); +// elem_props = set.get_elem_prop_header(); recreate_elem_prop_objects(elem_props,objects,prop_row_maps,prop_rows); +// set.copy_extend_elem_prop_row(set2,1,1); +// set.erase(2); +// set.push_back(objects[8][8], ext_prop_row_maps[2]); +// set.elem_resize(2,480); +// out << "\n\n-------------------------------------\n 55 MODFICATIONS \n-------------------------------------\n\n" << set << "\n\n"; +// set.add_extend_elem_prop(EXT_ELEM_PROP_8,"-99"); +// out << "set.size(): " << set.size() << std::endl; +// out << "set.num_props(): " << set.num_props() << std::endl; +// out << "set.num_extend_elem_props(): " << set.num_extend_elem_props() << std::endl; +// set.insert(objects[2][4],0); +// out << "set.has_elem_prop(ELEM_PROP_7): " << set.has_elem_prop(ELEM_PROP_7) << std::endl; +// set.set_extend_elem_prop_row(ext_prop_row_maps[0],0); +// set.freeze_elem_degree(); +// elem_props = set.get_elem_prop_header(); recreate_elem_prop_objects(elem_props,objects,prop_row_maps,prop_rows); +// set.push_back(objects[2][2]); +// out << "\n\n-------------------------------------\n 60 MODFICATIONS \n-------------------------------------\n\n" << set << "\n\n"; +// set.copy_extend_elem_prop_row(set2,0,2); +// out << "set.get_extend_elem_prop(EXT_ELEM_PROP_3,3): " << set.get_extend_elem_prop(EXT_ELEM_PROP_3,3) << std::endl; +// out << "set.num_elem_props(): " << set.num_elem_props() << std::endl; +// set.add_extend_elem_prop(EXT_ELEM_PROP_4,"-99"); +// set.remove_elem_prop(ELEM_PROP_2); +// elem_props = set.get_elem_prop_header(); recreate_elem_prop_objects(elem_props,objects,prop_row_maps,prop_rows); +// out << "set.vsize(): " << set.vsize() << std::endl; +// set.prop_key(2); +// set.remove_elem_prop(ELEM_PROP_4); +// out << "\n\n-------------------------------------\n 65 MODFICATIONS \n-------------------------------------\n\n" << set << "\n\n"; +// elem_props = set.get_elem_prop_header(); recreate_elem_prop_objects(elem_props,objects,prop_row_maps,prop_rows); +// out << "set.get_extend_elem_prop_header(): " << set.get_extend_elem_prop_header() << std::endl; +// set.set_extend_elem_prop_row(ext_prop_row_maps[0],1); +// set.prop_key(2); +// out << "set.prop_index(PROP_4): " << set.prop_index(PROP_4) << std::endl; +// out << "set.num_elem_props(): " << set.num_elem_props() << std::endl; +// out << "set.bsize(): " << set.bsize() << std::endl; +// out << "set.has_extend_elem_prop(EXT_ELEM_PROP_3): " << set.has_extend_elem_prop(EXT_ELEM_PROP_3) << std::endl; +// set.free_elem_degree(); +// set.remove_extend_elem_prop(EXT_ELEM_PROP_7); +// out << "set.num_extend_elem_props(): " << set.num_extend_elem_props() << std::endl; +// out << "set.num_props(): " << set.num_props() << std::endl; +// set.free_elem_degree(); +// out << "\n\n-------------------------------------\n 70 MODFICATIONS \n-------------------------------------\n\n" << set << "\n\n"; +// out << "set.has_extend_elem_prop(EXT_ELEM_PROP_8): " << set.has_extend_elem_prop(EXT_ELEM_PROP_8) << std::endl; +// set.add_extend_elem_props(set2); +// set.insert(objects[6][7],2); +// out << "set.vsize(): " << set.vsize() << std::endl; +// set.copy_extend_elem_prop_row(set2,3,5); +// set.copy_extend_elem_prop_row(set2,4,2); +// set.get_extend_elem_prop_row(4); +// out << "\n\n-------------------------------------\n 75 MODFICATIONS \n-------------------------------------\n\n" << set << "\n\n"; +// out << "set.num_props(): " << set.num_props() << std::endl; +// set.add_prop(PROP_8,140); +// set.set_extend_elem_prop(EXT_ELEM_PROP_4,"138",2); +// set.get_extend_elem_prop_row(3); +// set.get_extend_elem_prop_row(2); +// set.set_extend_elem_prop_row(ext_prop_row_maps[5],5); +// out << "\n\n-------------------------------------\n 80 MODFICATIONS \n-------------------------------------\n\n" << set << "\n\n"; +// out << "set.get_extend_elem_prop_header(): " << set.get_extend_elem_prop_header() << std::endl; +// set.set_extend_elem_prop(EXT_ELEM_PROP_5,"667",2); +// set.add_extend_elem_prop(EXT_ELEM_PROP_2,"-99"); +// set.insert(objects[1][2],2); +// set.add_extend_elem_prop(EXT_ELEM_PROP_8,"-99"); +// set.remove_prop(PROP_5); +// out << "\n\n-------------------------------------\n 85 MODFICATIONS \n-------------------------------------\n\n" << set << "\n\n"; +// set.remove_extend_elem_prop(EXT_ELEM_PROP_6); +// set.insert(objects[8][9],3); +// set.resize(1,277,5); +// out << "set.num_extend_elem_props(): " << set.num_extend_elem_props() << std::endl; +// set.add_extend_elem_prop(EXT_ELEM_PROP_6,"-99"); +// set.prop_key(0); +// out << "\n\n-------------------------------------\n 90 MODFICATIONS \n-------------------------------------\n\n" << set << "\n\n"; +// set.erase(0); +// set.prop_key(3); +// out << "set.elem_prop_keys(): " << set.elem_prop_keys() << std::endl; +// set.elem_resize(8,926); +// out << "set.get_extend_elem_prop_header(): " << set.get_extend_elem_prop_header() << std::endl; +// set.remove_extend_elem_prop(EXT_ELEM_PROP_9); +// set.remove_prop(PROP_4); +// out << "\n\n-------------------------------------\n 95 MODFICATIONS \n-------------------------------------\n\n" << set << "\n\n"; +// set.remove_extend_elem_prop(EXT_ELEM_PROP_5); +// set.add_prop(PROP_5,902); +// out << "set.num_extend_elem_props(): " << set.num_extend_elem_props() << std::endl; +// set.add_prop(PROP_10,182); +// set.push_back(objects[8][0], ext_prop_row_maps[2]); +// out << "set.vsize(): " << set.vsize() << std::endl; +// out << "set.prop_index(PROP_9): " << set.prop_index(PROP_9) << std::endl; +// out << "set.num_extend_elem_props(): " << set.num_extend_elem_props() << std::endl; +// set.add_prop(PROP_4,779); +// out << "\n\n-------------------------------------\n 100 MODFICATIONS \n-------------------------------------\n\n" << set << "\n\n"; +// out << "set.prop_keys(): " << set.prop_keys() << std::endl; +// out << "set.has_extend_elem_prop(EXT_ELEM_PROP_2): " << set.has_extend_elem_prop(EXT_ELEM_PROP_2) << std::endl; +// set.add_prop(PROP_3,22); +// set.resize(3,137,0); +// out << "set.num_elem_props(): " << set.num_elem_props() << std::endl; +// out << "set.has_extend_elem_prop(EXT_ELEM_PROP_10): " << set.has_extend_elem_prop(EXT_ELEM_PROP_10) << std::endl; +// set.set_extend_elem_prop(EXT_ELEM_PROP_8,"308",0); +// out << "set.num_props(): " << set.num_props() << std::endl; +// out << "set.get_extend_elem_prop(EXT_ELEM_PROP_10,2): " << set.get_extend_elem_prop(EXT_ELEM_PROP_10,2) << std::endl; +// set.erase(1); +// set.erase(1); +// out << "\n\n-------------------------------------\n 105 MODFICATIONS \n-------------------------------------\n\n" << set << "\n\n"; +// out << "set.get_extend_elem_prop(EXT_ELEM_PROP_3,0): " << set.get_extend_elem_prop(EXT_ELEM_PROP_3,0) << std::endl; +// set.push_back(objects[8][5], ext_prop_row_maps[4]); +// set.freeze_elem_degree(); +// elem_props = set.get_elem_prop_header(); recreate_elem_prop_objects(elem_props,objects,prop_row_maps,prop_rows); +// out << "set.prop_keys(): " << set.prop_keys() << std::endl; +// out << "set.size(): " << set.size() << std::endl; +// out << "set.num_extend_elem_props(): " << set.num_extend_elem_props() << std::endl; +// out << "set.prop(PROP_1): " << set.prop(PROP_1) << std::endl; +// out << "set.size(): " << set.size() << std::endl; +// set.freeze_elem_degree(); +// elem_props = set.get_elem_prop_header(); recreate_elem_prop_objects(elem_props,objects,prop_row_maps,prop_rows); +// set.get_extend_elem_prop_row(0); +// out << "set.bsize(): " << set.bsize() << std::endl; +// out << "set.elem_prop_keys(): " << set.elem_prop_keys() << std::endl; +// set.elem_resize(9,179); +// out << "\n\n-------------------------------------\n 110 MODFICATIONS \n-------------------------------------\n\n" << set << "\n\n"; +// out << "set.get_extend_elem_prop(EXT_ELEM_PROP_10,1): " << set.get_extend_elem_prop(EXT_ELEM_PROP_10,1) << std::endl; +// set.push_back(objects[9][1], ext_prop_row_maps[3]); +// set.erase(0); +// out << "set.bsize(): " << set.bsize() << std::endl; +// out << "set.prop(PROP_3): " << set.prop(PROP_3) << std::endl; +// out << "set.num_extend_elem_props(): " << set.num_extend_elem_props() << std::endl; +// set.push_back(objects[9][8]); +// out << "set.num_extend_elem_props(): " << set.num_extend_elem_props() << std::endl; +// out << "set.num_props(): " << set.num_props() << std::endl; +// set.remove_prop(PROP_2); +// set.get_extend_elem_prop_row(0); +// out << "\n\n-------------------------------------\n 115 MODFICATIONS \n-------------------------------------\n\n" << set << "\n\n"; +// set.add_extend_elem_prop(EXT_ELEM_PROP_5,"-99"); +// out << "set.elem_prop_keys(): " << set.elem_prop_keys() << std::endl; +// set.prop_key(2); +// set.prop_key(0); +// set.erase(0); +// set.copy_extend_elem_prop_row(set2,4,1); +// out << "\n\n-------------------------------------\n 120 MODFICATIONS \n-------------------------------------\n\n" << set << "\n\n"; +// set.free_elem_degree(); +// out << "set.num_elem_props(): " << set.num_elem_props() << std::endl; +// set.remove_prop(PROP_8); +// out << "set.prop_index(PROP_10): " << set.prop_index(PROP_10) << std::endl; +// set.free_elem_degree(); +// out << "set.size(): " << set.size() << std::endl; +// set.remove_extend_elem_prop(EXT_ELEM_PROP_7); +// set.add_extend_elem_prop(EXT_ELEM_PROP_1,"-99"); +// out << "\n\n-------------------------------------\n 125 MODFICATIONS \n-------------------------------------\n\n" << set << "\n\n"; +// set.elem_resize(4,873); +// set.remove_extend_elem_prop(EXT_ELEM_PROP_3); +// out << "set.size(): " << set.size() << std::endl; +// set.add_extend_elem_props(set2); +// set.free_elem_degree(); +// out << "set.get_extend_elem_prop(EXT_ELEM_PROP_2,0): " << set.get_extend_elem_prop(EXT_ELEM_PROP_2,0) << std::endl; +// set.insert(objects[5][3],1); +// out << "\n\n-------------------------------------\n 130 MODFICATIONS \n-------------------------------------\n\n" << set << "\n\n"; +// out << "set.num_elem_props(): " << set.num_elem_props() << std::endl; +// out << "set.size(): " << set.size() << std::endl; +// out << "set.num_elem_props(): " << set.num_elem_props() << std::endl; +// set.push_back(objects[4][7], ext_prop_row_maps[3]); +// out << "set.elem_prop_keys(): " << set.elem_prop_keys() << std::endl; +// set.push_back(objects[4][0], ext_prop_row_maps[7]); +// set.push_back(objects[6][6], ext_prop_row_maps[2]); +// set.elem_resize(7,192); +// set.insert(objects[7][9],1); +// out << "\n\n-------------------------------------\n 135 MODFICATIONS \n-------------------------------------\n\n" << set << "\n\n"; +// out << "set.prop(PROP_3): " << set.prop(PROP_3) << std::endl; +// out << "set.get_extend_elem_prop_header(): " << set.get_extend_elem_prop_header() << std::endl; +// out << "set.size(): " << set.size() << std::endl; +// set.insert(objects[7][1],0); +// set.add_extend_elem_prop(EXT_ELEM_PROP_6,"-99"); +// out << "set.has_elem_prop(ELEM_PROP_3): " << set.has_elem_prop(ELEM_PROP_3) << std::endl; +// out << "set.vsize(): " << set.vsize() << std::endl; +// out << "set.bsize(): " << set.bsize() << std::endl; +// set.free_elem_degree(); +// set.freeze_elem_degree(); +// elem_props = set.get_elem_prop_header(); recreate_elem_prop_objects(elem_props,objects,prop_row_maps,prop_rows); +// out << "set.prop(PROP_5): " << set.prop(PROP_5) << std::endl; +// out << "set.has_extend_elem_prop(EXT_ELEM_PROP_4): " << set.has_extend_elem_prop(EXT_ELEM_PROP_4) << std::endl; +// out << "set.bsize(): " << set.bsize() << std::endl; +// set.elem_resize(6,44); +// out << "\n\n-------------------------------------\n 140 MODFICATIONS \n-------------------------------------\n\n" << set << "\n\n"; +// out << "set.get_extend_elem_prop_header(): " << set.get_extend_elem_prop_header() << std::endl; +// out << "set.num_extend_elem_props(): " << set.num_extend_elem_props() << std::endl; +// set.get_extend_elem_prop_row(2); +// out << "set.elem_prop_keys(): " << set.elem_prop_keys() << std::endl; +// set.set_extend_elem_prop_row(ext_prop_row_maps[0],6); +// set.add_extend_elem_props(set2); +// set.resize(9,561,0); +// out << "set.prop_index(PROP_3): " << set.prop_index(PROP_3) << std::endl; +// set.push_back(objects[6][8]); +// out << "\n\n-------------------------------------\n 145 MODFICATIONS \n-------------------------------------\n\n" << set << "\n\n"; +// set.insert(objects[6][0],5); +// set.add_extend_elem_props(set2); +// set.push_back(objects[6][7]); +// out << "set.num_props(): " << set.num_props() << std::endl; +// set.prop_key(7); +// set.push_back(objects[6][1], ext_prop_row_maps[4]); +// out << "\n\n-------------------------------------\n 150 MODFICATIONS \n-------------------------------------\n\n" << set << "\n\n"; +// out << "set.elem_prop_keys(): " << set.elem_prop_keys() << std::endl; +// out << "set.has_elem_prop(ELEM_PROP_10): " << set.has_elem_prop(ELEM_PROP_10) << std::endl; +// out << "set.vsize(): " << set.vsize() << std::endl; +// set.resize(5,969,0); +// out << "set.has_prop(PROP_8): " << set.has_prop(PROP_8) << std::endl; +// set.elem_resize(2,367); +// set.add_prop(PROP_2,692); +// set.add_prop(PROP_8,147); +// set.resize(8,245,0); +// out << "\n\n-------------------------------------\n 155 MODFICATIONS \n-------------------------------------\n\n" << set << "\n\n"; +// out << "set.get_extend_elem_prop(EXT_ELEM_PROP_5,3): " << set.get_extend_elem_prop(EXT_ELEM_PROP_5,3) << std::endl; +// set.prop_key(6); +// set.remove_extend_elem_prop(EXT_ELEM_PROP_8); +// set.add_extend_elem_props(set2); +// set.get_extend_elem_prop_row(5); +// set.set_extend_elem_prop(EXT_ELEM_PROP_2,"640",0); +// out << "\n\n-------------------------------------\n 160 MODFICATIONS \n-------------------------------------\n\n" << set << "\n\n"; +// out << "set.num_props(): " << set.num_props() << std::endl; +// set.free_elem_degree(); +// set.get_extend_elem_prop_row(0); +// out << "set.has_extend_elem_prop(EXT_ELEM_PROP_9): " << set.has_extend_elem_prop(EXT_ELEM_PROP_9) << std::endl; +// out << "set.elem_prop_keys(): " << set.elem_prop_keys() << std::endl; +// out << "set.prop_keys(): " << set.prop_keys() << std::endl; +// set.remove_extend_elem_prop(EXT_ELEM_PROP_2); +// out << "set.prop(PROP_9): " << set.prop(PROP_9) << std::endl; +// out << "set.size(): " << set.size() << std::endl; +// set.free_elem_degree(); +// set.freeze_elem_degree(); +// out << "\n\n-------------------------------------\n 165 MODFICATIONS \n-------------------------------------\n\n" << set << "\n\n"; +// elem_props = set.get_elem_prop_header(); recreate_elem_prop_objects(elem_props,objects,prop_row_maps,prop_rows); +// set.freeze_elem_degree(); +// elem_props = set.get_elem_prop_header(); recreate_elem_prop_objects(elem_props,objects,prop_row_maps,prop_rows); +// set.remove_extend_elem_prop(EXT_ELEM_PROP_6); +// set.remove_prop(PROP_9); +// set.push_back(objects[2][6]); +// set.remove_prop(PROP_8); +// out << "\n\n-------------------------------------\n 170 MODFICATIONS \n-------------------------------------\n\n" << set << "\n\n"; +// set.resize(1,823,0); +// out << "set.num_props(): " << set.num_props() << std::endl; +// set.elem_resize(1,218); +// set.prop_key(4); +// out << "set.size(): " << set.size() << std::endl; +// set.copy_extend_elem_prop_row(set2,4,0); +// out << "set.prop_index(PROP_3): " << set.prop_index(PROP_3) << std::endl; +// out << "set.get_extend_elem_prop_header(): " << set.get_extend_elem_prop_header() << std::endl; +// set.erase(0); +// out << "\n\n-------------------------------------\n 175 MODFICATIONS \n-------------------------------------\n\n" << set << "\n\n"; +// set.remove_extend_elem_prop(EXT_ELEM_PROP_7); +// out << "set.num_extend_elem_props(): " << set.num_extend_elem_props() << std::endl; +// set.elem_resize(2,672); +// set.prop_key(0); +// set.prop_key(2); +// set.elem_resize(4,946); +// out << "\n\n-------------------------------------\n 180 MODFICATIONS \n-------------------------------------\n\n" << set << "\n\n"; +// out << "set.bsize(): " << set.bsize() << std::endl; +// set.prop_key(7); +// out << "set.elem_prop_keys(): " << set.elem_prop_keys() << std::endl; +// out << "set.bsize(): " << set.bsize() << std::endl; +// set.remove_extend_elem_prop(EXT_ELEM_PROP_4); +// out << "set.size(): " << set.size() << std::endl; +// out << "set.prop_keys(): " << set.prop_keys() << std::endl; +// out << "set.elem_prop_keys(): " << set.elem_prop_keys() << std::endl; +// set.add_prop(PROP_8,859); +// set.add_prop(PROP_9,835); +// out << "set.prop_keys(): " << set.prop_keys() << std::endl; +// set.add_extend_elem_prop(EXT_ELEM_PROP_10,"-99"); +// out << "\n\n-------------------------------------\n 185 MODFICATIONS \n-------------------------------------\n\n" << set << "\n\n"; +// out << "set.has_prop(PROP_9): " << set.has_prop(PROP_9) << std::endl; +// out << "set.get_extend_elem_prop_header(): " << set.get_extend_elem_prop_header() << std::endl; +// out << "set.has_prop(PROP_2): " << set.has_prop(PROP_2) << std::endl; +// out << "set.has_extend_elem_prop(EXT_ELEM_PROP_8): " << set.has_extend_elem_prop(EXT_ELEM_PROP_8) << std::endl; +// out << "set.has_extend_elem_prop(EXT_ELEM_PROP_3): " << set.has_extend_elem_prop(EXT_ELEM_PROP_3) << std::endl; +// out << "set.num_extend_elem_props(): " << set.num_extend_elem_props() << std::endl; +// out << "set.bsize(): " << set.bsize() << std::endl; +// set.freeze_elem_degree(); +// elem_props = set.get_elem_prop_header(); recreate_elem_prop_objects(elem_props,objects,prop_row_maps,prop_rows); +// set.resize(9,576,0); +// set.insert(objects[4][4],1); +// set.add_extend_elem_prop(EXT_ELEM_PROP_7,"-99"); +// out << "set.get_extend_elem_prop(EXT_ELEM_PROP_9,6): " << set.get_extend_elem_prop(EXT_ELEM_PROP_9,6) << std::endl; +// set.set_extend_elem_prop_row(ext_prop_row_maps[6],8); +// out << "\n\n-------------------------------------\n 190 MODFICATIONS \n-------------------------------------\n\n" << set << "\n\n"; +// set.remove_prop(PROP_6); +// set.set_extend_elem_prop(EXT_ELEM_PROP_7,"493",2); +// set.elem_resize(9,337); +// set.add_prop(PROP_6,153); +// out << "set.bsize(): " << set.bsize() << std::endl; +// out << "set.prop_keys(): " << set.prop_keys() << std::endl; +// set.free_elem_degree(); +// out << "\n\n-------------------------------------\n 195 MODFICATIONS \n-------------------------------------\n\n" << set << "\n\n"; +// out << "set.num_extend_elem_props(): " << set.num_extend_elem_props() << std::endl; +// out << "set.prop_index(PROP_3): " << set.prop_index(PROP_3) << std::endl; +// set.add_extend_elem_props(set2); +// set.erase(4); +// set.add_extend_elem_prop(EXT_ELEM_PROP_1,"-99"); +// out << "set.get_extend_elem_prop(EXT_ELEM_PROP_5,4): " << set.get_extend_elem_prop(EXT_ELEM_PROP_5,4) << std::endl; +// out << "set.prop_index(PROP_10): " << set.prop_index(PROP_10) << std::endl; +// set.erase(8); +// set.set_extend_elem_prop_row(ext_prop_row_maps[0],2); +// out << "\n\n-------------------------------------\n 200 MODFICATIONS \n-------------------------------------\n\n" << set << "\n\n"; +// out << "set.num_props(): " << set.num_props() << std::endl; +// out << "set.size(): " << set.size() << std::endl; +// out << "set.has_extend_elem_prop(EXT_ELEM_PROP_2): " << set.has_extend_elem_prop(EXT_ELEM_PROP_2) << std::endl; +// out << "set.has_extend_elem_prop(EXT_ELEM_PROP_1): " << set.has_extend_elem_prop(EXT_ELEM_PROP_1) << std::endl; +// out << "set.get_extend_elem_prop(EXT_ELEM_PROP_9,3): " << set.get_extend_elem_prop(EXT_ELEM_PROP_9,3) << std::endl; +// set.freeze_elem_degree(); +// elem_props = set.get_elem_prop_header(); recreate_elem_prop_objects(elem_props,objects,prop_row_maps,prop_rows); +// out << "set.get_extend_elem_prop_header(): " << set.get_extend_elem_prop_header() << std::endl; +// set.freeze_elem_degree(); +// elem_props = set.get_elem_prop_header(); recreate_elem_prop_objects(elem_props,objects,prop_row_maps,prop_rows); +// out << "set.has_prop(PROP_2): " << set.has_prop(PROP_2) << std::endl; +// out << "set.num_elem_props(): " << set.num_elem_props() << std::endl; +// out << "set.has_prop(PROP_1): " << set.has_prop(PROP_1) << std::endl; +// set.copy_extend_elem_prop_row(set2,0,1); +// out << "set.num_extend_elem_props(): " << set.num_extend_elem_props() << std::endl; +// out << "set.get_extend_elem_prop_header(): " << set.get_extend_elem_prop_header() << std::endl; +// set.get_extend_elem_prop_row(6); +// out << "set.num_props(): " << set.num_props() << std::endl; +// out << "set.elem_prop_keys(): " << set.elem_prop_keys() << std::endl; +// out << "set.num_elem_props(): " << set.num_elem_props() << std::endl; +// set.add_extend_elem_props(set2); +// out << "\n\n-------------------------------------\n 205 MODFICATIONS \n-------------------------------------\n\n" << set << "\n\n"; +// set.elem_resize(2,89); +// set.push_back(objects[2][6], ext_prop_row_maps[3]); +// set.elem_resize(5,359); +// set.free_elem_degree(); +// out << "set.num_elem_props(): " << set.num_elem_props() << std::endl; +// set.remove_extend_elem_prop(EXT_ELEM_PROP_10); +// out << "\n\n-------------------------------------\n 210 MODFICATIONS \n-------------------------------------\n\n" << set << "\n\n"; +// out << "set.bsize(): " << set.bsize() << std::endl; +// out << "set.vsize(): " << set.vsize() << std::endl; +// out << "set.has_extend_elem_prop(EXT_ELEM_PROP_1): " << set.has_extend_elem_prop(EXT_ELEM_PROP_1) << std::endl; +// out << "set.num_extend_elem_props(): " << set.num_extend_elem_props() << std::endl; +// out << "set.prop_index(PROP_7): " << set.prop_index(PROP_7) << std::endl; +// out << "set.num_extend_elem_props(): " << set.num_extend_elem_props() << std::endl; +// set.insert(objects[6][7],5); +// out << "set.num_elem_props(): " << set.num_elem_props() << std::endl; +// set.set_extend_elem_prop_row(ext_prop_row_maps[3],0); +// set.add_extend_elem_prop(EXT_ELEM_PROP_6,"-99"); +// set.remove_prop(PROP_4); +// out << "set.num_extend_elem_props(): " << set.num_extend_elem_props() << std::endl; +// set.add_extend_elem_props(set2); +// out << "\n\n-------------------------------------\n 215 MODFICATIONS \n-------------------------------------\n\n" << set << "\n\n"; +// out << "set.num_elem_props(): " << set.num_elem_props() << std::endl; +// set.add_extend_elem_prop(EXT_ELEM_PROP_5,"-99"); +// set.remove_prop(PROP_7); +// set.add_extend_elem_props(set2); +// set.elem_resize(5,955); +// set.resize(4,369,0); +// out << "\n\n-------------------------------------\n 220 MODFICATIONS \n-------------------------------------\n\n" << set << "\n\n"; +// set.add_prop(PROP_4,364); +// set.freeze_elem_degree(); +// elem_props = set.get_elem_prop_header(); recreate_elem_prop_objects(elem_props,objects,prop_row_maps,prop_rows); +// set.add_prop(PROP_7,495); +// set.free_elem_degree(); +// out << "set.size(): " << set.size() << std::endl; +// set.push_back(objects[6][6]); +// out << "\n\n-------------------------------------\n 225 MODFICATIONS \n-------------------------------------\n\n" << set << "\n\n"; +// out << "set.size(): " << set.size() << std::endl; +// set.free_elem_degree(); +// out << "set.vsize(): " << set.vsize() << std::endl; +// out << "set.get_extend_elem_prop(EXT_ELEM_PROP_5,3): " << set.get_extend_elem_prop(EXT_ELEM_PROP_5,3) << std::endl; +// set.append_extend_elem_props(set2); +// out << "set.prop_keys(): " << set.prop_keys() << std::endl; +// set.push_back(objects[0][4]); +// set.add_extend_elem_props(set2); +// out << "set.bsize(): " << set.bsize() << std::endl; +// out << "set.get_extend_elem_prop_header(): " << set.get_extend_elem_prop_header() << std::endl; +// out << "set.prop(PROP_10): " << set.prop(PROP_10) << std::endl; +// set.copy_extend_elem_prop_row(set2,3,4); +// out << "\n\n-------------------------------------\n 230 MODFICATIONS \n-------------------------------------\n\n" << set << "\n\n"; +// set.get_extend_elem_prop_row(1); +// out << "set.prop_index(PROP_10): " << set.prop_index(PROP_10) << std::endl; +// out << "set.has_elem_prop(ELEM_PROP_8): " << set.has_elem_prop(ELEM_PROP_8) << std::endl; +// set.set_extend_elem_prop(EXT_ELEM_PROP_10,"898",1); +// out << "set.bsize(): " << set.bsize() << std::endl; +// out << "set.bsize(): " << set.bsize() << std::endl; +// set.get_extend_elem_prop_row(1); + + + out << std::endl << std::endl << "-------------------------------------" << std::endl; + out << " FINAL PRINT " << std::endl; + out << "-------------------------------------\n" << std::endl; + + out << set << std::endl; + + std::cout << "Ran cpp test successfully" << std::endl; + + +} diff --git a/cmd/subdiv_strands.cpp b/cmd/subdiv_strands.cpp new file mode 100644 index 0000000..f889f0e --- /dev/null +++ b/cmd/subdiv_strands.cpp @@ -0,0 +1,173 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + +#include "bts/cmd.h" + +#include "progressbar.h" + +#include "bts/common.h" + +#include "bts/fibre/track.h" +#include "bts/fibre/strand.h" +#include "bts/fibre/track/set.h" + + + + + +#include "bts/inline_functions.h" + +#include "phantom/subdiv/subdiv.h" + + +#include "phantom/interface.h" + + + +using namespace BTS; + +SET_VERSION_DEFAULT; +SET_AUTHOR ("Thomas G. Close"); +SET_COPYRIGHT (NULL); + +DESCRIPTION = { + "Subdivides thicker strands into more thinner strands", + "", + NULL +}; + +ARGUMENTS = { + Argument ("input", "The paths to be subdivided.").type_file (), + Argument ("output", "The subdivided paths.").optional().type_file(), + Argument() +}; + + +OPTIONS = { + Option ("num_points", "The number of points that will be generated along the strand location") + + Argument ("num_points", "").type_integer (1, 100, 2000), + + Option ("old_strand_r", "The old radius of the strands") + + Argument ("old_strand_r", "").type_float (SMALL_FLOAT, 1.0, LARGE_FLOAT), + + Option ("strands_per_acs", "Instead of specifying the radius of the subdivided strands, the strands per area can be specified instead.") + + Argument ("strands_per_acs", "").type_float (-1.0, -1.0, LARGE_FLOAT), + + Option ("new_strand_r", "The new radius of the strands") + + Argument ("new_strand_r", "").type_float (SMALL_FLOAT, 1.0, LARGE_FLOAT), + + Option ("degree", "DegreeVector of the output strands if converting from track to strand") + + Argument ("degree", "").type_integer (1, 100, 2000), + + +Option() }; + + +EXECUTE { + + std::string input_location = argument[0]; + std::string output_location; + + if (argument.size() > 1) + output_location = argument[1].c_str(); + else + output_location = input_location; + + + size_t num_points = 0; + size_t degree = 0; + double old_strand_r = 1.0; + double new_strand_r = 1.0; + double strands_per_acs = -1.0; + + Options opt = get_options("num_points"); + if (opt.size()) + num_points = opt[0][0]; + + opt = get_options("old_strand_r"); + if (opt.size()) + old_strand_r = opt[0][0]; + + opt = get_options("new_strand_r"); + if (opt.size()) + new_strand_r = opt[0][0]; + + opt = get_options("strands_per_acs"); + if (opt.size()) { + if (get_options("new_strand_r").size()) + throw Exception ("'-strands_per_acs' option cannot be used in conjunction with '-new_strand_r' option."); + + strands_per_acs = opt[0][0]; + + } + + opt = get_options("degree"); + if (opt.size()) + degree = opt[0][0]; + + + if (strands_per_acs > 0) + new_strand_r = old_strand_r / MR::Math::sqrt(strands_per_acs); + + + BTS::Fibre::Track::Set tcks(input_location, num_points); + BTS::Fibre::Track::Set subdivided_tcks(tcks.get_extend_props()); + + std::vector > pre_points; + std::vector > post_points; + + Strand_collection c, subdivided_c; + + generate_pre_points(tcks, pre_points); + + generate_post_points(tcks, post_points); + + MR::ProgressBar progress_bar ("Subdividing strands...", 0); + + tcks.add_extend_elem_prop(BTS::Fibre::Track::RADIUS_PROP, str(old_strand_r)); + + convert_mr_to_nfg(&c, tcks, pre_points, post_points); + progress_bar++; + + subdivide_collection(&subdivided_c, &c, new_strand_r); + + progress_bar++; + convert_nfg_to_mr(subdivided_tcks, pre_points, post_points, &subdivided_c); + + if (tcks.has_extend_elem_prop(BTS::Fibre::Track::Set::ORIGINAL_DEGREE_PROP)) { + + subdivided_tcks.add_extend_elem_prop(BTS::Fibre::Track::Set::ORIGINAL_DEGREE_PROP, str(BTS::Fibre::Strand::DEFAULT_DEGREE)); + + for (size_t tck_i = 0; tck_i < tcks.size(); ++tck_i) { + + size_t bundle_index = to(subdivided_tcks.get_extend_elem_prop(BTS::Fibre::Track::BUNDLE_INDEX_EPROP, tck_i)); + std::string original_degree = tcks.get_extend_elem_prop(BTS::Fibre::Track::Set::ORIGINAL_DEGREE_PROP, bundle_index); + subdivided_tcks.set_extend_elem_prop(BTS::Fibre::Track::Set::ORIGINAL_DEGREE_PROP, original_degree, tck_i); + + } + } + + progress_bar++; + subdivided_tcks.save(output_location, degree); + + //MR::ProgressBar::done(); +} diff --git a/cmd/subtract_fibres.cpp b/cmd/subtract_fibres.cpp new file mode 100644 index 0000000..8f966cb --- /dev/null +++ b/cmd/subtract_fibres.cpp @@ -0,0 +1,175 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + +#include "bts/common.h" + +#include "bts/cmd.h" +#include "progressbar.h" + +#include "bts/fibre/strand/set.h" +#include "bts/fibre/tractlet/set.h" +#include "bts/fibre/track/set.h" + + +#include "bts/inline_functions.h" + + +using namespace BTS; + +SET_VERSION_DEFAULT; +SET_AUTHOR ("Thomas G. Close"); +SET_COPYRIGHT (NULL); + +DESCRIPTION = { + "Trims paths to a sphere of specified radius.", + "The sections of paths that lie outside the radius of the sphere are removed and sections that reenter are split into new paths.", + NULL +}; + +ARGUMENTS = { + Argument ("input", "The fibres to be subtracted from.").type_file (), + Argument ("subtract", "The fibres to subtract.").type_file (), + Argument ("output", "The resultant fibres.").optional().type_file(), + Argument() +}; + + +OPTIONS = { + + Option ("no_acs", "Don't acs in the subtraction."), + + +Option() }; + + + +EXECUTE { + + + std::string input_location = argument[0]; + std::string subtract_location = argument[1]; + std::string output_location; + + if (argument.size() > 2) + output_location = argument[2].c_str(); + else + output_location = input_location; + + if (File::extension(input_location) != File::extension(subtract_location)) + throw Exception ("Extensions of input files do not match ('" + File::extension(input_location) + "' and '" + File::extension(input_location) + "')."); + + + + if (File::has_extension(input_location)) { + + MR::ProgressBar progress_bar("Subtracting strands..."); + + BTS::Fibre::Strand::Set input(input_location); + BTS::Fibre::Strand::Set subtract(subtract_location); + + if (input.size() != subtract.size()) + throw Exception ("Number of points don't match."); + + double base_intensity = input.base_intensity(); + + for (size_t tck_i = 0; tck_i < input.size(); tck_i++) { + + if (input[tck_i].degree() != subtract[tck_i].degree()) + throw Exception ("Degrees don't match."); + + double acs = input[tck_i].acs(); + + input[tck_i] -= subtract[tck_i]; + + input[tck_i].set_acs(acs); + + + } + + input.set_base_intensity(base_intensity); + + input.save(output_location); + + } else if (File::has_extension(input_location)) { + + MR::ProgressBar progress_bar("Subtracting tractlets..."); + + BTS::Fibre::Tractlet::Set input(input_location); + BTS::Fibre::Tractlet::Set subtract(subtract_location); + + if (input.size() != subtract.size()) + throw Exception ("Number of points don't match."); + + double base_intensity = input.base_intensity(); + + + for (size_t tck_i = 0; tck_i < input.size(); tck_i++) { + + if (input[tck_i].degree() != subtract[tck_i].degree()) + throw Exception ("Degrees don't match."); + + double acs = input[tck_i].acs(); + + input[tck_i] -= subtract[tck_i]; + + input[tck_i].set_acs(acs); + + } + + input.set_base_intensity(base_intensity); + + + input.save(output_location); + + } else if (File::has_extension(input_location)) { + + MR::ProgressBar progress_bar("Subtracting tracks..."); + + BTS::Fibre::Track::Set input(input_location); + BTS::Fibre::Track::Set subtract(subtract_location); + + double base_intensity = input.base_intensity(); + + + if (input.size() != subtract.size()) + throw Exception ("Number of points don't match."); + + for (size_t tck_i = 0; tck_i < input.size(); tck_i++) { + + if (input[tck_i].num_points() != subtract[tck_i].num_points()) + throw Exception ("Number of points don't match."); + + input[tck_i] -= subtract[tck_i]; + + } + + input.set_base_intensity(base_intensity); + + + input.save(output_location); + + + } else + throw Exception ("Unrecognised extension ('" + File::extension(input_location)); + + +} diff --git a/cmd/subtract_images.cpp b/cmd/subtract_images.cpp new file mode 100644 index 0000000..138ae1f --- /dev/null +++ b/cmd/subtract_images.cpp @@ -0,0 +1,96 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + + + + +#include "bts/cmd.h" +#include "progressbar.h" + +#include "bts/common.h" +#include "bts/image/expected/buffer.h" +#include "bts/image/observed/buffer.h" + + + + +#include "bts/inline_functions.h" + + +using namespace BTS; + +SET_VERSION_DEFAULT; +SET_AUTHOR ("Thomas G. Close"); +SET_COPYRIGHT (NULL); + +DESCRIPTION = { + "Subtractlets one image from another", + "", + NULL +}; + +ARGUMENTS = { + Argument ("initial", "The initial image the second image will be subtracted from.").type_image_in(), + + Argument ("subtract", "The image that will be subtracted from the initial image.").type_image_in(), + + Argument ("output_image", "The resulting image").type_image_out (), + + Argument() +}; + + +OPTIONS = { + +Option() + +}; + + + +EXECUTE { + + +//------------------------------// +// Load Input Image Buffer // +//------------------------------// + + + std::string image_location = argument[0]; + std::string subtract_image_location = argument[1]; + std::string output_location = argument[2]; + + Image::Observed::Buffer image(image_location); + Image::Observed::Buffer subtract_image (subtract_image_location); + + image -= subtract_image; + + image.save(output_location); + + +} + + + + + + diff --git a/cmd/summarise_strands.cpp b/cmd/summarise_strands.cpp new file mode 100644 index 0000000..20d8289 --- /dev/null +++ b/cmd/summarise_strands.cpp @@ -0,0 +1,193 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Written by Thomas G. Close, 04/03/2009. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + +#include "bts/cmd.h" +// + +#include "progressbar.h" + +#include "bts/common.h" + +#include "bts/fibre/strand.h" +#include "bts/fibre/strand/set.h" + + +#include "bts/inline_functions.h" + + +using namespace BTS; + +SET_VERSION_DEFAULT; +SET_AUTHOR ("Thomas G. Close"); +SET_COPYRIGHT (NULL); + +DESCRIPTION = { + "Extractlets salient features from a set of Strand descriptors", + "Features are extractleted from the strand descriptor representation of a collection of strands. These features can then be compared with priors on these features.", + NULL +}; + +ARGUMENTS = { + Argument ("input", "The strand coefficients to be analyzed.").allow_multiple().type_file (), + Argument ("output", "output directory where the feature files will be written").type_file(), + Argument() +}; + + +OPTIONS = { + + Option ("all", "Saves all the features. Overrides all other flags"), + + Option ("v0_norm", "Save the norm of the v0 vector"), + + Option ("v1_norm", "Save the norm of the v1 vector"), + + Option ("v2_norm", "Save the norm of the v2 vector"), + + Option ("dot_v1_v2", "Save the dot product of the v1 and v2 vectors"), + + Option ("angle_v1_v2", "Save the angle between the v1 and v2 vectors"), + + Option ("dot_v0_v1", "Save the dot product of the v0 and v1 vectors"), + + Option ("degree", "The degree of the Strand coefficients used to describe the strands") + + Argument ("degree", "").type_integer (1, 3, 200), + + +Option() }; + + + +EXECUTE { + + std::string input_location = argument[0]; + std::string output_dir = argument[1]; + + bool save_all = get_options("save_all").size(); + bool save_v0_norm = get_options("save_v0_norm").size() || save_all; + bool save_v1_norm = get_options("save_v1_norm").size() || save_all; + bool save_v2_norm = get_options("save_v2_norm").size() || save_all; + bool save_dot_v1_v2 = get_options("save_dot_v1_v2").size() || save_all; + bool save_angle_v1_v2 = get_options("save_angle_v1_v2").size() || save_all; + bool save_dot_v0_v1 = get_options("save_dot_v0_v1").size() || save_all; + size_t degree = 0; + + Options opt = get_options("degree"); + if (opt.size()) + degree = opt[0][0]; + + Fibre::Strand::Set strands (input_location, degree); + + int count = 0; + + if (!(save_all || save_v0_norm || save_v1_norm || save_v2_norm || save_dot_v0_v1 || save_dot_v1_v2 || save_angle_v1_v2)) + throw Exception("No options supplied, please select a feature to save"); + + + std::ofstream v0_norm_out, v1_norm_out, v2_norm_out, dot_v1_v2_out, angle_v1_v2_out, dot_v0_v1_out; + + + if (save_v0_norm) + v0_norm_out.open ((output_dir + "/v0_norm.txt").c_str(), std::ios::out); + + if (save_v1_norm) + v1_norm_out.open ((output_dir + "/v1_norm.txt").c_str(), std::ios::out); + + if (save_v2_norm) + v2_norm_out.open ((output_dir + "/v2_norm.txt").c_str(), std::ios::out); + + if (save_dot_v1_v2) + dot_v1_v2_out.open ((output_dir + "/dot_v1_v2.txt").c_str(), std::ios::out); + + if (save_angle_v1_v2) + angle_v1_v2_out.open ((output_dir + "/angle_v1_v2.txt").c_str(), std::ios::out); + + if (save_dot_v0_v1) + dot_v0_v1_out.open ((output_dir + "/dot_v0_v1.txt").c_str(), std::ios::out ); + + + + MR::ProgressBar progress_bar ("extractleting features from strand descriptors...", strands.size()); + + for (size_t strand_i = 0; strand_i < strands.size(); ++strand_i) { + + Fibre::Strand strand = strands[strand_i]; + + Coord v0 = strand[0]; + Coord v1 = strand[1]; + Coord v2 = strand[2]; + + double v0_norm = v0.norm(); + double v1_norm = v1.norm(); + double v2_norm = v2.norm(); + double dot_v1_v2 = v1.dot(v2) / (v1_norm * v2_norm); + double dot_v0_v1 = v0.dot(v1) / (v1_norm * v0_norm); + + + if (save_v0_norm) + v0_norm_out << v0_norm << std::endl; + + + if (save_v1_norm) + v1_norm_out << v1_norm << std::endl; + + + if (save_v2_norm) + v2_norm_out << v2_norm << std::endl; + + + if (save_dot_v1_v2) + dot_v1_v2_out << dot_v1_v2 << std::endl; + + + if (save_angle_v1_v2) + angle_v1_v2_out << acos(dot_v1_v2) * 180 / M_PI << std::endl; + + + if (save_dot_v0_v1) + dot_v0_v1_out << dot_v0_v1 << std::endl; + + count++; + progress_bar++; + + } + + if (save_v0_norm) + v0_norm_out.close(); + + if (save_v1_norm) + v1_norm_out.close(); + + if (save_v2_norm) + v2_norm_out.close(); + + if (save_dot_v1_v2) + dot_v1_v2_out.close(); + + if (save_angle_v1_v2) + angle_v1_v2_out.close(); + + if (save_dot_v0_v1) + dot_v0_v1_out.close(); + + +} diff --git a/cmd/svd_fibres.cpp b/cmd/svd_fibres.cpp new file mode 100644 index 0000000..53a37eb --- /dev/null +++ b/cmd/svd_fibres.cpp @@ -0,0 +1,207 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, Jul 26, 2010. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + + +#include "bts/cmd.h" + +#include "bts/common.h" + +#include "bts/fibre/strand/set.h" +#include "bts/fibre/tractlet/set.h" + +#include "bts/file.h" + +#include "bts/math/svd.h" + + + +#include "bts/inline_functions.h" + +using namespace BTS; + + +template void svd_fibres(const std::string& input_location, const std::string& output_location, size_t max_num_components); + + +SET_VERSION_DEFAULT; +SET_AUTHOR ("Thomas G. Close"); +SET_COPYRIGHT (NULL); + + +DESCRIPTION = { + "svd_fibres", + "", + NULL +}; + +ARGUMENTS = { + Argument ("input location","").type_file (), + Argument ("output location","").type_file (), + Argument() +}; + + +OPTIONS = { + + Option("max_num_components","The number of principle components to be returned..") + + Argument("max_num_components","").type_integer(0,UINT_MAX,UINT_MAX), + +Option() }; + + +EXECUTE { + + + std::string input_location = argument[0]; + std::string output_location = argument[1]; + + size_t max_num_components = UINT_MAX; + + Options opt = get_options("max_num_components"); + if (opt.size()) + max_num_components = opt[0][0]; + + if (File::extension(input_location) != File::extension(output_location)) + throw Exception ("Input location ('" + File::extension(input_location) + "') does not match output location ('" + File::extension(output_location) + "')."); + + MR::ProgressBar progress_bar ("Performing SVD on fibres ..."); + + if (File::has_extension(input_location)) { + + svd_fibres(input_location, output_location, max_num_components); + + } else if (File::has_extension(input_location)) { + + svd_fibres(input_location, output_location, max_num_components); + + } else + throw Exception ("Unrecognised extension '" + File::extension(input_location) + "'."); + + +} + +template void svd_fibres(const std::string& input_location, const std::string& output_location, size_t max_num_components) { + + typename T::Reader reader(input_location); + + T input_fibres, output_fibres; + + size_t num_cols = 0; + + std::vector< MR::Math::Vector > input_vectors; + + while (reader.next(input_fibres)) { + + MR::Math::Vector& input_vector = input_fibres; + + if (!num_cols) //First one. + num_cols = input_vector.size(); + else if (num_cols != input_vector.size()) + throw Exception ("Inconsistent lengths (" + str(num_cols) + " and " + str(input_vector.size()) + ") found in input location."); + + input_vectors.push_back(input_vector); + + //Save the input_fibres structure so that the usv matrix can be converted back into the right format. + if (!output_fibres.size()) + output_fibres = input_fibres; + + } + + size_t num_rows = input_vectors.size(); + + MR::Math::Matrix M (num_rows, num_cols); + + for (size_t row_i = 0; row_i < num_rows; row_i++) + M.row(row_i) = input_vectors[row_i]; + + + Math::USV usv = Math::svd(M); + + std::vector ext_header; + ext_header.push_back("singular_value"); + + std::map file_props; + file_props["method"] = "svd_fibres"; + + typename T::Writer writer(output_location, reader, ext_header, file_props); + + size_t num_components = min2(max_num_components, num_cols); + + for (size_t comp_i = 0; comp_i < num_components; comp_i++) { + + output_fibres = usv.v.column(comp_i); + + output_fibres.set_extend_prop("singular_value", str(usv.sigma[comp_i])); + + writer.append(output_fibres); + + } + +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cmd/test_bed.cpp b/cmd/test_bed.cpp new file mode 100644 index 0000000..d279d30 --- /dev/null +++ b/cmd/test_bed.cpp @@ -0,0 +1,506 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Written by Thomas G. Close, 04/03/2009. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + +*/ + + +extern "C" { +#include +#include +} + + +#include "bts/cmd.h" + +#include "bts/common.h" + +#include "bts/math/common.h" + +#include "bts/prob/test/gaussian.h" +#include "bts/prob/test/landscape.h" +#include "bts/prob/test/landscape/peak.h" +#include "bts/prob/test/bayes_log_regression.h" +#include "bts/prob/uniform.h" +#include "bts/mcmc/proposal/distribution.h" +#include "bts/mcmc/proposal/distribution/gaussian.h" +#include "bts/mcmc/proposal/walker.h" +#include "bts/mcmc/proposal/momentum.h" + +#include "bts/fibre/strand/set.h" +#include "bts/fibre/tractlet/set.h" + +#include "bts/mcmc/metropolis.h" +#include "bts/mcmc/hamiltonian.h" +#include "bts/mcmc/riemannian.h" + +#include "bts/triple.h" + + +#include "bts/mcmc/state.h" +//#include "bts/mcmc/state/writer.h" +#include "bts/mcmc/state/tensor/writer.h" +#include "bts/utilities/reader.h" + +#include "bts/fibre/strand/set/momentum.h" +#include "bts/fibre/tractlet/set/momentum.h" + +#include "bts/inline_functions.h" + +#include "bts/diffusion/response.h" + + + +using namespace BTS; + +const char* STEP_LOCATION_DEFAULT = "/home/tclose/Code/Tractography/params/test_bed/scaling.tes"; + +SET_VERSION_DEFAULT; +SET_AUTHOR ("Thomas G. Close"); +SET_COPYRIGHT (NULL); + +DESCRIPTION = { + "dummy program", + "", + NULL +}; + +ARGUMENTS = { + Argument ("initial location", "The location of the initial state.").type_file (), + Argument ("samples location", "The location where the samples will be saved.").type_file (), + Argument() +}; + + +const char* ALGORITHM_TYPE_DEFAULT = "metropolis"; +const char* PROB_TYPE_DEFAULT = "Prob::Test::Gaussian"; +const double STEP_SCALE_DEFAULT = 0.1; +const size_t NUM_ITERATIONS_DEFAULT = 10; +const size_t SAMPLE_PERIOD_DEFAULT = 1e2; +const size_t NUM_LEAPFROG_STEPS_DEFAULT = 30; +const size_t NUM_NEWTON_STEPS_DEFAULT = 6; +const char* WALKER_STEP_LOCATION_DEFAULT = "/home/tclose/data/mcmc/metropolis/params/walker/scaling.sta"; +const char* MOMENTUM_STEP_LOCATION_DEFAULT = "/home/tclose/data/mcmc/hamiltonian/params/momentum/scaling.sta"; +const char* AXIS_SCALES_DEFAULT_LOCATION_DEFAULT = "/home/tclose/data/prob/test/gaussian/axis_scales.sta"; + +OPTIONS = { + + Option ("algorithm", "Select the algorithm to use (either 'metropolis', 'hamiltonian' at this stage).") + + Argument ("algorithm", "").type_text(), + + Option ("prob_type", "Select the probability object (either 'Prob::Test::Gaussian' or 'Prob::Test::Peaks' at this stage.") + + Argument ("prob_type", ""), + + Option ("num_samples", "The Number of MCMC iterations to take of the prob distribution over the tractlets") + + Argument ("num_samples", "").type_integer (1, NUM_ITERATIONS_DEFAULT, LARGE_INT), + + Option ("sample_period", "The number of MCMC iterations that will be performed before a sample is saved") + + Argument ("sample_period", "").type_integer (1, SAMPLE_PERIOD_DEFAULT, LARGE_INT), + + Option ("num_leapfrog_steps", "The number of leapfrog steps to be performed in the 'hamiltonian' and 'riemannian' algorithms.") + + Argument ("num_leapfrog_steps", "").type_integer (1, NUM_LEAPFROG_STEPS_DEFAULT, LARGE_INT), + + Option ("num_newton_steps", "The number of Newton steps that will be performed in calculating the non-separable Hamiltonian in the 'riemannian' algorithm.") + + Argument ("num_newton_steps", "").type_integer (1, NUM_NEWTON_STEPS_DEFAULT, LARGE_INT), + + Option ("seed", "The random seed that is passed to the random generator") + + Argument ("seed", ""), + + Option ("axis_scales_location", "Location of the file containing the scales of the Gaussian axes") + + Argument ("axis_scales_location", ""), + + Option ("blr_location", "Location of the Bayesian log regression data.") + + Argument ("blr_location", "").type_text (Prob::Test::BayesLogRegression::DATA_LOCATION_DEFAULT), + + Option ("blr_poly_order", "Order of the polynomials used in the Bayesian Log Regression.") + + Argument ("blr_poly_order", "").type_integer (1, Prob::Test::BayesLogRegression::POLY_ORDER_DEFAULT, LARGE_INT), + + Option ("blr_prior_variance", "Variance of the prior used in the Bayesian Log Regression") + + Argument ("blr_prior_variance", "").type_float (SMALL_FLOAT, Prob::Test::BayesLogRegression::PRIOR_VARIANCE_DEFAULT, LARGE_FLOAT), + + Option ("step_scale", "Overall step scale.") + + Argument ("step_scale", "").type_float (SMALL_FLOAT, STEP_SCALE_DEFAULT, LARGE_FLOAT), + + Option ("step_location", "Name of the file containing the relative scales of the step sizes.") + + Argument ("step_location", ""), + + Option ("save_iterations", "Save every iteration in seperate file (with '.iter' inserted before the extension)."), + + Option ("suppress_stdout", "Don't print probability to standard out."), + + PROPOSAL_DISTRIBUTION_PARAMETERS, + + PROPOSAL_MOMENTUM_PARAMETERS, + + COMMON_PARAMETERS, + +Option() }; + + + +EXECUTE { + + std::string initial_location = argument[0]; + std::string samples_location = argument[1]; + + Options opt; + + std::string algorithm_type = ALGORITHM_TYPE_DEFAULT; + std::string prob_type = PROB_TYPE_DEFAULT; + size_t num_samples = NUM_ITERATIONS_DEFAULT; + size_t sample_period = SAMPLE_PERIOD_DEFAULT; + size_t num_leapfrog_steps = NUM_LEAPFROG_STEPS_DEFAULT; + size_t num_newton_steps = NUM_NEWTON_STEPS_DEFAULT; + size_t seed = time(NULL); + std::string axis_scales_location = AXIS_SCALES_DEFAULT_LOCATION_DEFAULT; + std::string blr_location = Prob::Test::BayesLogRegression::DATA_LOCATION_DEFAULT; + size_t blr_poly_order = Prob::Test::BayesLogRegression::POLY_ORDER_DEFAULT; + float blr_prior_variance = Prob::Test::BayesLogRegression::PRIOR_VARIANCE_DEFAULT; + double step_scale = STEP_SCALE_DEFAULT; + std::string step_location; + + bool save_iterations = true; + bool suppress_print = false; + + + opt = get_options("algorithm"); + if (opt.size()) + algorithm_type = opt[0][0].c_str(); //.get_string() + + opt = get_options("prob_type"); + if (opt.size()) + prob_type = opt[0][0].c_str(); + + opt = get_options("num_samples"); + if (opt.size()) + num_samples = opt[0][0]; + + opt = get_options("sample_period"); + if (opt.size()) + sample_period = opt[0][0]; + + opt = get_options("num_leapfrog_steps"); + if (opt.size()) + num_leapfrog_steps = opt[0][0]; + + opt = get_options("num_newton_steps"); + if (opt.size()) + num_newton_steps = opt[0][0]; + + opt = get_options("seed"); + if (opt.size()) { + std::string seed_string = opt[0][0]; + seed = to(seed_string); + } else + std::cout << "No random seed supplied. Using timestamp: " << seed << std::endl; + + opt = get_options("axis_scales_location"); + if (opt.size()) + axis_scales_location = opt[0][0].c_str(); + + + opt = get_options("blr_location"); + if (opt.size()) + blr_location = opt[0][0].c_str(); + + opt = get_options("blr_poly_order"); + if (opt.size()) + blr_poly_order = opt[0][0]; + + opt = get_options("blr_prior_variance"); + if (opt.size()) + blr_prior_variance = opt[0][0]; + + opt = get_options("step_scale"); + if (opt.size()) + step_scale = opt[0][0]; + + opt = get_options("save_iterations"); + if (opt.size()) + save_iterations = true; + + opt = get_options("suppress_print"); + if (opt.size()) + suppress_print = true; + + if (algorithm_type == "metropolis") + step_location = WALKER_STEP_LOCATION_DEFAULT; + + else + step_location = MOMENTUM_STEP_LOCATION_DEFAULT; + + + opt = get_options("step_location"); + if (opt.size()) + step_location = opt[0][0].c_str(); + + + // Loads parameters to construct Proposal::Distribution (any variables with 'prop_' prefix) + SET_PROPOSAL_DISTRIBUTION_PARAMETERS; + + // Loads parameters to construct Proposal::Distribution ('prop_' prefix) + SET_PROPOSAL_MOMENTUM_PARAMETERS(initial_location); + + // Loads parameters to construct Prob::Test::Peaks (any variables with 'test_gen_' prefix) + SET_TEST_LANDSCAPE_PARAMETERS; + + // Loads parameters that are common to all commands. + SET_COMMON_PARAMETERS; + + + //-------------------------------------// + // Initialize random number generator // + //-------------------------------------// + + + gsl_rng* rand_gen = gsl_rng_alloc(gsl_rng_taus); + gsl_rng_set(rand_gen, seed); + + + //---------------------------// + // Initialise the test state // + //---------------------------// + + MCMC::State state(initial_location); + + //-----------------------------------// + // Initialize Proposal::Distribution // + //-----------------------------------// + + MCMC::Proposal::Distribution *proposal_distribution = MCMC::Proposal::Distribution::factory(prop_distr_type, rand_gen); + + MCMC::State step (step_location); + + step *= step_scale; + + MCMC::Proposal::Walker walker (proposal_distribution, step); + MCMC::Proposal::Momentum momentum (proposal_distribution, step); + + //----------------------------------------------// + // Initialize SampleWriter and its Properties // + //----------------------------------------------// + + + // Set the 'run-wide' properties. + std::map run_properties; + + run_properties["algorithm"] = algorithm_type; + run_properties["prob_type"] = prob_type; + run_properties["sample_period"] = str(sample_period); + run_properties["num_leapfrog_steps"] = str(num_leapfrog_steps); + run_properties["num_newton_steps"] = str(num_newton_steps); + run_properties["num_samples"] = str(num_samples); + run_properties["seed"] = str(seed); + run_properties["step"] = Math::matlab_str(step); + run_properties["step_scale"] = str(step_scale); + run_properties["step_location"] = step_location; + + + ADD_PROPOSAL_DISTRIBUTION_PROPERTIES(run_properties); + + ADD_TEST_LANDSCAPE_PROPERTIES(run_properties); + + ADD_COMMON_PROPERTIES(run_properties); + + //-------------------// + // Run the algorithm // + //-------------------// + + if (prob_type == "Prob::Test::Landscape") { + + Prob::Test::Landscape test_peaks(lnd_location); + + if (algorithm_type == "metropolis") { + +// MCMC::metropolis ( +// state, +// test_peaks, +// test_peaks, +// walker, +// samples_location, +// run_properties, +// num_samples * sample_period, +// sample_period, +// rand_gen, +// true, +// suppress_print +// ); + + throw Exception ("removed for debugging."); + + } else if (!strcmp(algorithm_type.c_str(), "hamiltonian")) { + + MCMC::hamiltonian ( + state, + test_peaks, + test_peaks, + momentum, + samples_location, + run_properties, + num_samples, + num_leapfrog_steps, + rand_gen, + true, + save_iterations, + suppress_print + ); + + } else + throw Exception ("Unrecognised value for '-algorithm' option \"" + algorithm_type + "\", can be either \"metropolis\" or \"hamiltonian\"."); + + if (!lnd_location.size()) + test_peaks.save(samples_location + ".lnd"); + + } else if (prob_type == "Prob::Test::Gaussian") { + + run_properties["axis_scales_location"] = str(axis_scales_location); + + MCMC::State axis_scale (axis_scales_location); + Prob::Test::Gaussian test_gaussian(axis_scale); + + if (algorithm_type == "metropolis") { + +// MCMC::metropolis ( +// state, +// test_gaussian, +// test_gaussian, +// walker, +// samples_location, +// run_properties, +// num_samples * sample_period, +// sample_period, +// rand_gen, +// true, +// suppress_print +// ); + + throw Exception(""); + + } else if (!strcmp(algorithm_type.c_str(), "hamiltonian")) { + + MCMC::hamiltonian ( + state, + test_gaussian, + test_gaussian, + momentum, + samples_location, + run_properties, + num_samples, + num_leapfrog_steps, + rand_gen, + true, + save_iterations, + suppress_print + ); + + } else if (!strcmp(algorithm_type.c_str(), "riemannian")) { + + + MCMC::Proposal::Momentum::Weighted::NonSeparable nonseparable_momentum = MCMC::Proposal::Momentum::Weighted::NonSeparable::factory( state, + momen_step_scale, + momen_step_location, + proposal_distribution, + num_newton_steps); + + Prob::Uniform uniform; + + MCMC::riemannian ( + state, + test_gaussian, + uniform, + nonseparable_momentum, + samples_location, + run_properties, + num_samples, + num_leapfrog_steps, + num_newton_steps, + rand_gen, + true, + save_iterations, + suppress_print + ); + + } else + throw Exception ("Unrecognised value for '-algorithm' option \"" + algorithm_type + "\", can be either 'metropolis', 'hamiltonian' or 'riemannian'."); + + } else if (prob_type == "Prob::Test::BayesLogRegression") { + + Prob::Test::BayesLogRegression bayes_log_regression (blr_location, blr_poly_order, blr_prior_variance); + + if (!strcmp(algorithm_type.c_str(), "riemannian")) { + + + MCMC::Proposal::Momentum::Weighted::NonSeparable nonseparable_momentum = MCMC::Proposal::Momentum::Weighted::NonSeparable::factory( state, + momen_step_scale, + momen_step_location, + proposal_distribution, + num_newton_steps); + Prob::Uniform uniform; + + MCMC::riemannian ( + state, + bayes_log_regression, + uniform, + nonseparable_momentum, + samples_location, + run_properties, + num_samples, + num_leapfrog_steps, + num_newton_steps, + rand_gen, + true, + save_iterations, + suppress_print + ); + + } else + throw Exception ("Unrecognised value for '-algorithm' option \"" + algorithm_type + "\", can only be 'riemannian'."); + + } else + throw Exception ("Unrecognised probability type " + prob_type + "', can be either 'Prob::Test::Landscape' or 'Prob::Test::Gaussian'."); + + + std::ofstream prop_file; + + prop_file.open((samples_location + ".prp").c_str()); + + for (std::map::iterator prop_it = run_properties.begin(); prop_it != run_properties.end(); ++prop_it) + prop_file << prop_it->first << ": " << prop_it->second << std::endl; + + prop_file.close(); + + + if (prob_type == "Prob::Test::Landscape") { + std::cout << "\n\nMATLAB plot command:\n\nplot_test_scan " << lnd_location << " -state_filename " << samples_location; + + if (algorithm_type == "metropolis") + std::cout << " -mark 0"; + + } else { + + std::cout << "\n\nMATLAB plot command:\n\nplot_test_bed " << samples_location; + + std::cout << std::endl << std::endl; + } + + + +} + + diff --git a/cmd/test_gradient.cpp b/cmd/test_gradient.cpp new file mode 100644 index 0000000..e60b7b2 --- /dev/null +++ b/cmd/test_gradient.cpp @@ -0,0 +1,1734 @@ +/* + Copyright 2010 Brain Research Institute/National ICT Australia (NICTA), Melbourne, Australia + + Written by Tom G. Close, 4/03/10. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + +*/ + + +#include "bts/cmd.h" + +#include "bts/common.h" + +#include "math/matrix.h" + +#include "bts/prob/likelihood.h" +#include "bts/prob/likelihood/gaussian.h" +#include "bts/prob/likelihood/one_sided_gaussian.h" +#include "bts/prob/test/gaussian.h" +#include "bts/prob/test/landscape.h" +#include "bts/prob/test/landscape/peak.h" +#include "bts/diffusion/encoding.h" + +#include "bts/analysis/gradient_tester.h" +#include "bts/analysis/image_gradient_tester.h" +#include "bts/analysis/hessian_tester.h" +#include "bts/analysis/image_hessian_tester.h" +#include "bts/analysis/rank3_hessian_tester.h" +#include "bts/analysis/fisher_gradient_tester.h" +#include "bts/analysis/fisher_gradient_matrix_tester.h" + +#include "bts/fibre/tractlet/set.h" +#include "bts/fibre/strand/set.h" + +#include "bts/diffusion/model.h" +#include "bts/image/expected/trilinear/buffer.h" +#include "bts/image/expected/gaussian/buffer.h" +#include "bts/image/expected/quartic/buffer.h" + +#include "bts/image/observed/buffer.h" + +#include "bts/prob/uniform.h" +#include "bts/prob/prior.h" + + + + + +#include "bts/prob/likelihood.h" +#include "bts/prob/likelihood.h" +#include "bts/prob/likelihood/one_sided_gaussian.h" +#include "bts/prob/likelihood/gaussian.h" + +#include "bts/mcmc/state.h" +#include "bts/utilities/reader.h" +#include "bts/mcmc/state/tensor.h" +#include "bts/mcmc/state/tensor/writer.h" + +#include "bts/fibre/strand/basic_section/tensor.h" +#include "bts/fibre/tractlet/section/tensor.h" +#include "bts/math/common.h" + +#include "bts/fibre/base/tensor_writer.cpp.h" + + +#include "bts/inline_functions.h" + +#define TEST_GRADIENT(State, Object, function, object_instance) \ + State state; \ +\ + State::Reader reader(state_location); \ + State::Writer analytic_writer (analytic_output_location, reader, properties), numeric_writer (numeric_output_location, reader, properties); \ +\ + Analysis::GradientTester grad_tester (object_instance); \ + Analysis::GradientTester::Function test_function; \ +\ + test_function = &Object::function; \ +\ + while (reader.next(state)) { \ + State analytic_gradient(state), numeric_gradient(state); \ +\ + grad_tester.test(test_function, state, step_size, analytic_gradient, numeric_gradient); \ +\ + analytic_writer.append(analytic_gradient); \ + numeric_writer.append(numeric_gradient); \ +\ + } \ +\ + reader.close(); \ + analytic_writer.close(); \ + numeric_writer.close(); \ + + +#define TEST_ELEMENT_GRADIENT(State, Object, function, object_instance) \ + State state; \ +\ + State::Reader reader(state_location); \ + State::Writer analytic_writer (analytic_output_location, reader, properties), numeric_writer (numeric_output_location, reader, properties); \ +\ + Analysis::GradientTester grad_tester (object_instance); \ + Analysis::GradientTester::Function test_function; \ +\ + test_function = &Object::function; \ +\ + while (reader.next(state)) { \ + State analytic_gradient(state.size(), numeric_gradient(state.size()); \ +\ +\ for (size_t elem_i = 0; elem_i < state.size(); elem_i++) { \ + grad_tester.test(test_function, state[elem_i], step_size, analytic_gradient[elem_i], numeric_gradient[elem_i]); \ + } \ +\ + analytic_writer.append(analytic_gradient); \ + numeric_writer.append(numeric_gradient); \ +\ + } \ +\ + reader.close(); \ + analytic_writer.close(); \ + numeric_writer.close(); \ + + +#define TEST_SINGLE_GRADIENT(State, Object, function, object_instance) \ +\ + State state (state_location); \ + State analytic_gradient(state), numeric_gradient(state); \ +\ + Analysis::GradientTester grad_tester (object_instance); \ + Analysis::GradientTester::Function test_function; \ +\ + test_function = &Object::function; \ +\ + grad_tester.test(test_function, state, step_size, analytic_gradient, numeric_gradient); \ +\ + analytic_gradient.save(analytic_output_location, properties); \ + numeric_gradient.save(numeric_output_location, properties); \ + + +#define TEST_IMAGE_GRADIENT(State, Object, function, object_instance) \ + State state; \ +\ + State::Reader reader(state_location); \ + State::Writer analytic_writer (analytic_output_location, reader, properties), numeric_writer (numeric_output_location, reader, properties); \ +\ + Analysis::ImageGradientTester grad_tester (object_instance); \ + Analysis::ImageGradientTester::Function test_function; \ +\ + test_function = &Object::function; \ +\ + while (reader.next(state)) { \ +\ + object_instance.zero(); \ +\ + Image::Container::Buffer analytic_gradient(img_dims, object_instance.num_encodings()); \ + Image::Container::Buffer numeric_gradient(img_dims, object_instance.num_encodings()); \ +\ + grad_tester.test(test_function, state, step_size, analytic_gradient, numeric_gradient); \ +\ + for (size_t z = 0; z < object_instance.dim(Z); z++) { \ + for (size_t y = 0; y < object_instance.dim(Y); y++) { \ + for (size_t x = 0; x < object_instance.dim(X); x++) { \ + for (size_t encode_i = 0; encode_i < object_instance.num_encodings(); encode_i++) { \ + analytic_writer.append(analytic_gradient(x,y,z)[encode_i]); \ + numeric_writer.append(numeric_gradient(x,y,z)[encode_i]); \ + } \ + } \ + } \ + } \ + } \ +\ + reader.close(); \ + analytic_writer.close(); \ + numeric_writer.close(); \ + + +#define TEST_IMAGE_HESSIAN(State, Object, function, object_instance) \ + State state; \ + State::Reader reader (state_location); \ + if (!reader.next(state)) \ + throw Exception ("Did not find any states in file '" + state_location + "'."); \ + reader.close(); \ +\ + State::Tensor::Writer analytic_writer (analytic_output_location + ".tnr", state), numeric_writer (numeric_output_location + ".tnr", state); \ + reader.open(state_location); \ +\ + Analysis::ImageHessianTester hess_tester (object_instance); \ + Analysis::ImageHessianTester::Function test_function; \ +\ + test_function = &Object::function; \ +\ + while (reader.next(state)) { \ +\ + object_instance.zero(); \ +\ + Image::Container::Buffer analytic_hessian(img_dims, object_instance.num_encodings()); \ + Image::Container::Buffer numeric_hessian(img_dims, object_instance.num_encodings()); \ +\ + hess_tester.test(test_function, state, step_size, analytic_hessian, numeric_hessian); \ +\ + for (size_t z = 0; z < object_instance.dim(Z); z++) { \ + for (size_t y = 0; y < object_instance.dim(Y); y++) { \ + for (size_t x = 0; x < object_instance.dim(X); x++) { \ + for (size_t encode_i = 0; encode_i < object_instance.num_encodings(); encode_i++) { \ + analytic_writer.append(analytic_hessian(x,y,z)[encode_i]); \ + numeric_writer.append(numeric_hessian(x,y,z)[encode_i]); \ + } \ + } \ + } \ + } \ + } \ +\ + reader.close(); \ + analytic_writer.close(); \ + numeric_writer.close(); \ + + +#define TEST_OBJECT_ELEMENT_GRADIENT(State, Object, function, object_instance) \ + State state; \ +\ + State::Writer analytic_writer (analytic_output_location, properties), numeric_writer (numeric_output_location, properties); \ + State::Reader reader; \ +\ + for (size_t i = 0; i < object_instance.size(); ++i) { \ +\ + reader.open(state_location); \ +\ + Analysis::GradientTester grad_tester (object_instance[i]); \ + Analysis::GradientTester::Function test_function; \ +\ + test_function = &Object::function; \ +\ + while (reader.next(state)) { \ + State analytic_gradient(state), numeric_gradient(state); \ +\ + grad_tester.test(test_function, state, step_size, analytic_gradient, numeric_gradient); \ +\ + analytic_writer.append(analytic_gradient); \ + numeric_writer.append(numeric_gradient); \ +\ + } \ +\ + reader.close(); \ +\ + } \ +\ + analytic_writer.close(); \ + numeric_writer.close(); \ + + +#define TEST_OBJECT_ELEMENT_HESSIAN(State, Object, function, object_instance) \ + State state; \ + State::Reader reader (state_location); \ + if (!reader.next(state)) \ + throw Exception ("Did not find any states in file '" + state_location + "'."); \ + reader.close(); \ +\ + State::Tensor::Writer analytic_writer (analytic_output_location + ".tnr", state), numeric_writer (numeric_output_location + ".tnr", state); \ +\ + for (size_t i = 0; i < object_instance.size(); ++i) { \ +\ + reader.open(state_location); \ +\ + Analysis::HessianTester grad_tester (object_instance[i]); \ + Analysis::HessianTester::Function test_function; \ +\ + test_function = &Object::function; \ +\ + while (reader.next(state)) { \ + State::Tensor analytic_hessian(state), numeric_hessian(state); \ +\ + grad_tester.test(test_function, state, step_size, analytic_hessian, numeric_hessian); \ +\ + analytic_writer.append(analytic_hessian); \ + numeric_writer.append(numeric_hessian); \ + \ + } \ +\ + reader.close(); \ +\ + } \ +\ + analytic_writer.close(); \ + numeric_writer.close(); \ + + +#define TEST_WRITABLE_OBJECT_ELEMENT_GRADIENT(State, Object, function, object_instance) \ + State::Writable state; \ +\ + State::Writable::Writer analytic_writer (analytic_output_location, properties), numeric_writer (numeric_output_location, properties); \ + State::Writable::Reader reader(state_location); \ +\ + for (size_t i = 0; i < object_instance.size(); ++i) { \ +\ + Analysis::GradientTester grad_tester (object_instance[i]); \ + Analysis::GradientTester::Function test_function; \ +\ + test_function = &Object::function; \ +\ + while (reader.next(state)) { \ + State analytic_gradient(state.size(), numeric_gradient(state.size()); \ +\ + grad_tester.test(test_function, state, step_size, analytic_gradient, numeric_gradient); \ +\ + analytic_writer.append(analytic_gradient); \ + numeric_writer.append(numeric_gradient); \ +\ + } \ + } \ +\ + reader.close(); \ + analytic_writer.close(); \ + numeric_writer.close(); \ + + +#define TEST_VOXEL_GRADIENT(State, Object, function, image_instance) \ + State state; \ +\ + State::Writer analytic_writer (analytic_output_location, properties), numeric_writer (numeric_output_location, properties); \ +\ + for (size_t z = 0; z < image_instance.dim(Z); ++z) { \ + for (size_t y = 0; y < image_instance.dim(Y); ++y) { \ + for (size_t x = 0; x < image_instance.dim(X); ++x) { \ +\ + State::Reader reader(state_location); \ +\ + Analysis::GradientTester grad_tester (image_instance(x,y,z)); \ + Analysis::GradientTester::Function test_function; \ +\ + test_function = &Object::function; \ +\ + while (reader.next(state)) { \ + State analytic_gradient(state), numeric_gradient(state); \ +\ + grad_tester.test(test_function, state, step_size, analytic_gradient, numeric_gradient); \ +\ + analytic_writer.append(analytic_gradient); \ + numeric_writer.append(numeric_gradient); \ +\ + } \ +\ + reader.close(); \ +\ + } \ + } \ + } \ +\ + analytic_writer.close(); \ + numeric_writer.close(); \ + + +#define TEST_VOXEL_HESSIAN(State, Object, function, image_instance) \ + State state; \ + State::Reader reader (state_location); \ + if (!reader.next(state)) \ + throw Exception ("Did not find any states in file '" + state_location + "'."); \ + reader.close(); \ +\ + State::Tensor::Writer analytic_writer (analytic_output_location + ".tnr", state), numeric_writer (numeric_output_location + ".tnr", state); \ +\ + for (size_t z = 0; z < image_instance.dim(Z); ++z) { \ + for (size_t y = 0; y < image_instance.dim(Y); ++y) { \ + for (size_t x = 0; x < image_instance.dim(X); ++x) { \ +\ + State::Reader reader(state_location); \ +\ + Analysis::HessianTester grad_tester (image_instance(x,y,z)); \ + Analysis::HessianTester::Function test_function; \ +\ + test_function = &Object::function; \ +\ + while (reader.next(state)) { \ + State::Tensor analytic_hessian(state), numeric_hessian(state); \ +\ + grad_tester.test(test_function, state, step_size, analytic_hessian, numeric_hessian); \ +\ + analytic_writer.append(analytic_hessian); \ + numeric_writer.append(numeric_hessian); \ +\ + } \ +\ + reader.close(); \ +\ + } \ + } \ + } \ +\ + analytic_writer.close(); \ + numeric_writer.close(); \ + + +#define TEST_WRITABLE_VOXEL_GRADIENT(State, Object, function, image_instance) \ + State::Writable state; \ +\ + State::Writable::Writer analytic_writer (analytic_output_location, properties), numeric_writer (numeric_output_location, properties); \ +\ + for (size_t z = 0; z < image_instance.dim(Z); ++z) { \ + for (size_t y = 0; y < image_instance.dim(Y); ++y) { \ + for (size_t x = 0; x < image_instance.dim(X); ++x) { \ +\ + State::Writable::Reader reader(state_location); \ +\ + Analysis::GradientTester grad_tester (image_instance(x,y,z)); \ + Analysis::GradientTester::Function test_function; \ +\ + test_function = &Object::function; \ +\ + while (reader.next(state)) { \ + State analytic_gradient(state.size(), numeric_gradient(state.size()); \ +\ + grad_tester.test(test_function, state, step_size, analytic_gradient, numeric_gradient); \ +\ + analytic_writer.append(analytic_gradient); \ + numeric_writer.append(numeric_gradient); \ +\ + } \ +\ + reader.close(); \ +\ + } \ + } \ + } \ +\ + analytic_writer.close(); \ + numeric_writer.close(); \ + + +#define TEST_DIRECTION_GRADIENT(State, function, image_instance) \ + State state; \ + std::map read_properties; \ + std::vector row_properties_list; \ +\ + State::Writer analytic_writer (analytic_output_location, properties), numeric_writer (numeric_output_location, properties); \ +\ + for (size_t z = 0; z < image_instance.dim(Z); ++z) { \ + for (size_t y = 0; y < image_instance.dim(Y); ++y) { \ + for (size_t x = 0; x < image_instance.dim(X); ++x) { \ + for (size_t encode_i = 0; encode_i < image_instance.num_encodings(); encode_i++) { \ +\ + State::Reader reader(state_location); \ +\ + Analysis::GradientTester grad_tester (image_instance(x,y,z).direction(encode_i)); \ + Analysis::GradientTester::Function test_function; \ +\ + test_function = &Image::Expected::Direction::function; \ +\ + while (reader.next(state)) { \ + State analytic_gradient(state.size(), numeric_gradient(state.size()); \ +\ + grad_tester.test(test_function, state, step_size, analytic_gradient, numeric_gradient); \ +\ + analytic_writer.append(analytic_gradient); \ + numeric_writer.append(numeric_gradient); \ + } \ +\ + reader.close(); \ +\ + } \ + } \ + } \ + } \ +\ + analytic_writer.close(); \ + numeric_writer.close(); + + +#define TEST_DIRECTION_HESSIAN(State, function, image_instance) \ + State state; \ + State::Reader reader (state_location); \ + if (!reader.next(state)) \ + throw Exception ("Did not find any states in file '" + state_location + "'."); \ + reader.close(); \ +\ + State::Tensor::Writer analytic_writer (analytic_output_location + ".tnr", state), numeric_writer (numeric_output_location + ".tnr", state); \ +\ + for (size_t z = 0; z < image_instance.dim(Z); ++z) { \ + for (size_t y = 0; y < image_instance.dim(Y); ++y) { \ + for (size_t x = 0; x < image_instance.dim(X); ++x) { \ + for (size_t encode_i = 0; encode_i < image_instance.num_encodings(); encode_i++) { \ +\ + State::Reader reader(state_location); \ +\ + Analysis::HessianTester hess_tester (image_instance(x,y,z).direction(encode_i)); \ + Analysis::HessianTester::Function test_function; \ +\ + test_function = &Image::Expected::Direction::function; \ +\ + while (reader.next(state)) { \ + State::Tensor analytic_hessian(state.size(), numeric_hessian(state.size()); \ +\ + hess_tester.test(test_function, state, step_size, analytic_hessian, numeric_hessian); \ +\ + analytic_writer.append(analytic_hessian); \ + numeric_writer.append(numeric_hessian); \ + } \ +\ + reader.close(); \ +\ + } \ + } \ + } \ + } \ +\ + analytic_writer.close(); \ + numeric_writer.close(); + + +#define TEST_IMAGE_POINTER_GRADIENT(State, Object, function, object_instance, state) \ + State* analytic_gradient = state.clone(); \ + State* numeric_gradient = state.clone(); \ +\ + Analysis::PointerGradientTester grad_tester (object_instance); \ + Analysis::PointerGradientTester::Function test_function; \ +\ + test_function = &Object::function; \ +\ + grad_tester.test(test_function, state, step_size, *analytic_gradient, *numeric_gradient); \ +\ + analytic_gradient->save(analytic_output_location); \ + numeric_gradient->save(numeric_output_location); \ +\ + delete analytic_gradient; \ + delete numeric_gradient; \ + + +#define TEST_HESSIAN(State, Object, function, object_instance) \ + State state; \ + State::Reader reader (state_location); \ + if (!reader.next(state)) \ + throw Exception ("Did not find any states in file '" + state_location + "'."); \ +\ + State::Tensor::Writer analytic_writer (analytic_output_location + ".tnr", state), numeric_writer (numeric_output_location + ".tnr", state); \ +\ + reader.close(); \ + reader.open(state_location); \ +\ + Analysis::HessianTester grad_tester (object_instance); \ + Analysis::HessianTester::Function test_function; \ +\ + test_function = &Object::function; \ +\ + while (reader.next(state)) { \ + State::Tensor analytic_hessian(state), numeric_hessian(state); \ +\ + grad_tester.test(test_function, state, step_size, analytic_hessian, numeric_hessian); \ +\ + analytic_writer.append(analytic_hessian); \ + numeric_writer.append(numeric_hessian); \ +\ + } \ +\ + reader.close(); \ + analytic_writer.close(); \ + numeric_writer.close(); \ + + +#define TEST_RANK3_HESSIAN(State, Object, function, object_instance) \ + State state; \ + State::Reader reader (state_location); \ + if (!reader.next(state)) \ + throw Exception ("Did not find any states in file '" + state_location + "'."); \ +\ + State::Tensor::Writer analytic_writer (analytic_output_location + ".tnr3", state), numeric_writer (numeric_output_location + ".tnr3", state); \ +\ + reader.close(); \ + reader.open(state_location); \ +\ + Analysis::Rank3HessianTester grad_tester (object_instance); \ + Analysis::Rank3HessianTester::Function test_function; \ +\ + test_function = &Object::function; \ +\ + while (reader.next(state)) { \ + std::vector analytic_rank3_hessian, numeric_rank3_hessian; \ +\ + grad_tester.test(test_function, state, step_size, analytic_rank3_hessian, numeric_rank3_hessian); \ +\ + for (size_t dim_i = 0; dim_i < state.size(); dim_i++) { \ + analytic_writer.append(analytic_rank3_hessian[dim_i]); \ + numeric_writer.append(numeric_rank3_hessian[dim_i]); \ + } \ +\ + } \ +\ + reader.close(); \ + analytic_writer.close(); \ + numeric_writer.close(); \ + + +#define TEST_FISHER_GRADIENT(State, Object, function, object_instance) \ + State state; \ + State::Reader reader (state_location); \ + if (!reader.next(state)) \ + throw Exception ("Did not find any states in file '" + state_location + "'."); \ +\ + State::Tensor::Writer analytic_writer (analytic_output_location + ".tnr", state), numeric_writer (numeric_output_location + ".tnr", state); \ +\ + reader.close(); \ + reader.open(state_location); \ +\ + Analysis::FisherGradientTester grad_tester (object_instance); \ + Analysis::FisherGradientTester::Function test_function; \ +\ + test_function = &Object::function; \ +\ + while (reader.next(state)) { \ + std::vector analytic_fisher_gradient, numeric_fisher_gradient; \ +\ + grad_tester.test(test_function, state, step_size, analytic_fisher_gradient, numeric_fisher_gradient); \ +\ + if (analytic_fisher_gradient.size() != numeric_fisher_gradient.size()) \ + throw Exception ("Sizes of Fisher gradients do not match"); \ +\ + for (size_t i = 0; i < analytic_fisher_gradient.size(); i++) { \ + analytic_writer.append(analytic_fisher_gradient[i]); \ + numeric_writer.append(numeric_fisher_gradient[i]); \ + } \ +\ + } \ +\ + reader.close(); \ + analytic_writer.close(); \ + numeric_writer.close(); \ + + +#define TEST_FISHER_GRADIENT_MATRIX(State, Object, function, object_instance) \ + State state; \ + State::Reader reader (state_location); \ + if (!reader.next(state)) \ + throw Exception ("Did not find any states in file '" + state_location + "'."); \ +\ + State::Tensor::Writer analytic_writer (analytic_output_location + ".tnr", state), numeric_writer (numeric_output_location + ".tnr", state); \ +\ + reader.close(); \ + reader.open(state_location); \ +\ + Analysis::FisherGradientMatrixTester grad_tester (object_instance); \ + Analysis::FisherGradientMatrixTester::Function test_function; \ +\ + test_function = &Object::function; \ +\ + while (reader.next(state)) { \ + std::vector analytic_fisher_gradient, numeric_fisher_gradient; \ +\ + grad_tester.test(test_function, state, step_size, analytic_fisher_gradient, numeric_fisher_gradient); \ +\ + if (analytic_fisher_gradient.size() != numeric_fisher_gradient.size()) \ + throw Exception ("Sizes of Fisher gradients do not match"); \ +\ + for (size_t i = 0; i < analytic_fisher_gradient.size(); i++) { \ + analytic_writer.append(analytic_fisher_gradient[i]); \ + numeric_writer.append(numeric_fisher_gradient[i]); \ + } \ +\ + } \ +\ + reader.close(); \ + analytic_writer.close(); \ + numeric_writer.close(); \ + + +#define ONLY_ACTIVE_FUNCTIONS + +using namespace BTS; + +SET_VERSION_DEFAULT; +SET_AUTHOR ("Thomas G. Close"); +SET_COPYRIGHT (NULL); + +DESCRIPTION = { + "Compare analytically calculated gradients against numerical approximations.", + NULL +}; + +ARGUMENTS = { + Argument ("state", "State about which the gradient will be tested.").type_file (), + Argument ("output", "Output analysis file").type_file (), + Argument() +}; + +OPTIONS = { + + + Option ("object_type", "The object_type that the function belongs to.") + + Argument ("object_type", "").type_text(), + + Option ("state_type", "The state to pass to the test_function.") + + Argument ("state_type", "").type_text(), + + Option ("function_name", "The name of the function to test.") + + Argument ("function_name", "").type_text(), + + Option ("hessian", "Calculate Hessian instead of gradient."), + +// Option ("fisher_info", "Calculate gradient of the Fisher information gradient."), + + Option ("rank3_hessian", "Calculate 3rd order Hessian instead of gradient."), + + Option ("step_size", "The size of the steps used to build the numerical approximation.") + + Argument ("step_size", "").type_float (SMALL_FLOAT, 1e-4, LARGE_FLOAT), + + Option ("encoding_orientation", "Test encoding orientation.") + + Argument ("encoding_orientation", "").type_text(), + + Option ("axis_scales_location", "Location of the file containing the scales of the Gaussian axes") + + Argument ("axis_scales_location", "").type_text (Prob::Test::Gaussian::AXIS_SCALES_LOCATION_DEFAULT), + +// Option ("diff_encode_index", "Index of the diffusion encoding to use") +// + Argument ("diff_encode_index", "").type_integer (0, 1000, 1), + + Option ("element_index", "Index of the 'Object' element to use.") + + Argument("element_index", "").type_integer(0,0, LARGE_INT), + + DIFFUSION_PARAMETERS, + + IMAGE_PARAMETERS, + + EXPECTED_IMAGE_PARAMETERS, + + LIKELIHOOD_PARAMETERS, + + PRIOR_PARAMETERS, + + TEST_LANDSCAPE_PARAMETERS, + + COMMON_PARAMETERS, + + Option ("obs_image", "The location of the reference image that is to be set") + + Argument ("obs_image", "").type_image_in(), + + Option() +}; + + + + +EXECUTE { + + + + + //-----------------// + // Load Arguments // + //-----------------// + + std::string state_location = argument[0]; + std::string output_location = argument[1]; + + if (File::extension(state_location) != File::extension(output_location)) + throw Exception ("Extension of output, '" + File::extension(output_location) + ", does not match extension of input, '" + File::extension(state_location) + "'."); + + std::string analytic_output_location = File::strip_extension(output_location) + str(".analytic.") + File::extension(output_location); + std::string numeric_output_location = File::strip_extension(output_location) + str(".numeric.") + File::extension(output_location); + +// +// +// +// +// //----------------------------------// +// // Get and Set Optional Parameters // +// //----------------------------------// +// +// double step_size = 1e-4; +// Triple encoding_orientation (1.0, 0.0, 0.0); +// std::string axis_scales_location = Prob::Test::Gaussian::AXIS_SCALES_LOCATION_DEFAULT; +// std::string object_type = "Prob::Prior::Magnitude"; +// std::string function_name = "log_prob"; +// bool calculate_hessian = false; +// bool calculate_rank3_hessian = false; +//// bool calculate_fisher_gradient = false; +//// size_t diff_encode_index = 1; +// std::string prior_b_intens_gauss_mean_type; +// std::string obs_image_name; +// size_t element_index = 0; +// +// std::string state_type; +// if (File::has_extension(state_location)) +// state_type = "Fibre::Strand::Set"; +// +// else if (File::has_extension(state_location)) +// state_type = "Fibre::Tractlet::Set"; +// +// else if (File::has_extension(state_location)) +// state_type = "Fibre::Strand"; +// +// else if (File::has_extension(state_location)) +// state_type = "Fibre::Tractlet"; +// +// else if (File::has_extension< Triple >(state_location)) +// state_type = "Triple"; +// +// else if (File::has_extension(state_location)) +// state_type = "Fibre::Strand::Section"; +//// +//// else if (File::has_extension(state_location)) +//// state_type = "Image::Observed"; +// +// else if (File::has_extension(state_location)) +// state_type = "MCMC::State"; +// +// else +// throw Exception ("Unrecognised extension for state, '" + File::extension(state_location) + "'."); +// +// +// +// Options opt; +// +// opt = get_options("object_type"); +// if (opt.size()) +// object_type = (std::string)opt[0][0]; +// +// opt = get_options("state_type"); +// if (opt.size()) +// state_type = (std::string)opt[0][0]; +// +// opt = get_options("function_name"); +// if (opt.size()) +// function_name = (std::string)opt[0][0]; +// +// opt = get_options("hessian"); +// if (opt.size()) +// calculate_hessian = true; +// +//// opt = get_options("fisher_info"); +//// if (opt.size()) +//// calculate_fisher_gradient = true; +// +// opt = get_options("rank3_hessian"); +// if (opt.size()) +// calculate_rank3_hessian = true; +// +// opt = get_options("step_size"); +// if (opt.size()) +// step_size = opt[0][0]; +// +// opt = get_options("encoding_orientation"); +// if (opt.size()) +// encoding_orientation = parse_triple(opt[0][0]); +// +// opt = get_options("axis_scales_location"); +// if (opt.size()) +// axis_scales_location = (std::string)opt[0][0]; +// +//// opt = get_options("diff_encode_index"); +//// if (opt.size()) +//// diff_encode_index = opt[0][0]; +// +// opt = get_options("element_index"); +// if (opt.size()) +// element_index = opt[0][0]; +// +// // Loads parameters to construct Diffusion::Model ('diff_' prefix) +// SET_DIFFUSION_PARAMETERS; +// +// // Loads parameters to construct Image::Expected::*::Buffer that are inherited from Image::Observed::Buffer ('img_' prefix) +// SET_IMAGE_PARAMETERS; +// +// // Loads parameters to construct Image::Expected::*::Buffer ('img_' prefix) +// SET_EXPECTED_IMAGE_PARAMETERS; +// +// // Loads parameters to construct Prob::Likelihood('like_' prefix) +// SET_LIKELIHOOD_PARAMETERS; +// +// // Loads parameters to construct Prob::Prior('prior_' prefix) +// SET_PRIOR_PARAMETERS; +// +// // Loads parameters to construct Prob::Test::Landscape ('test_gen_' prefix) +// SET_TEST_LANDSCAPE_PARAMETERS; +// +// // Loads parameters that are common to all commands. +// SET_COMMON_PARAMETERS; +// +// +////----------------------// +//// Load observed image // +////----------------------// +// +// Image::Observed::Buffer obs_image; +// +// bool obs_image_provided = false; +// +// opt = get_options("obs_image"); +// if (opt.size()) { +// +// obs_image_name = (std::string)opt[0][0]; +// obs_image.load(obs_image_name); +// +// if ((obs_image.properties().count("diff_response_SH")) && (Math::matlab_str(diff_response_SH) != obs_image.properties()["diff_response_SH"])) +// std::cout << std::endl << "Warning! Diffusion response function harmonics (" << Math::matlab_str(diff_response_SH) << ") do not match reference image (" << obs_image.properties()["diff_response_SH"] + ")!" << std::endl; +// +// obs_image_provided = true; +// +// } else { +// +// if (object_type.substr(0,18) == "Prob::Likelihood::") +// throw Exception("Observed image location (-obs_image option) required for 'Prob::Likelihood::*' object types (" + object_type + ")."); +// +// obs_image.reset(img_dims, img_vox_lengths, img_offsets, Diffusion::Encoding::Set(diff_encodings)); +// +// } +// +// +// //----------------------------// +// // Initialize Expected Image // +// //----------------------------// +// +// +// Diffusion::Model diffusion_model = Diffusion::Model::factory (diff_encodings, +// diff_response_SH, +// diff_adc, +// diff_fa, +// diff_isotropic); +// +// Image::Expected::Buffer* exp_image = Image::Expected::Buffer::factory(exp_type, +// img_dims, +// img_vox_lengths, +// diffusion_model, +// exp_num_length_sections, +// exp_num_width_sections, +// exp_interp_extent, +// img_offsets, +// exp_enforce_bounds, +// exp_half_width); +// +// +// //----------------------------------------------------------------// +// // Auto-generate base intensity initial value/b_intens_gauss_mean // +// //----------------------------------------------------------------// +// +// if ((exp_base_intensity < 0) && obs_image_provided) +// exp_base_intensity = exp_image->base_intensity_default(obs_image, state_location); +// +// //-----------------------// +// // Initialize Likelihood // +// //-----------------------// +// +// Prob::Likelihood* likelihood = 0; +// +// if (obs_image_provided) +// likelihood = Prob::Likelihood::factory(like_type, obs_image, exp_image, like_snr, like_b0_include, like_outside_scale, like_ref_b0, like_ref_signal); +// +// +// //--------------------// +// //--- Prior ---// +// //--------------------// +// +// Prob::Prior prior (prior_scale, +// prior_mag_scale, +// prior_mag_aux_scale, +// prior_hook_scale, +// prior_hook_num_points, +// prior_density_high_scale, +// prior_density_low_scale, +// prior_density_num_points, +// prior_acs_scale, +// prior_acs_mean); +// +// +// +// MCMC::State axis_scale (axis_scales_location); +// Prob::Test::Gaussian test_gaussian(axis_scale); +// +// +// Prob::Test::Landscape test_landscape; +// +// if (lnd_location.size()) +// test_landscape = Prob::Test::Landscape(lnd_location, lnd_roi_radius, lnd_barrier_rate); +// +// +// +////-----------------// +//// Save properties // +////-----------------// +// +// std::map properties; +// +// properties["method"] = "test_gradient"; +// properties["object_type"] = object_type; +// properties["state_type"] = state_type; +// properties["state_location"] = state_location; +// properties["function_name"] = function_name; +// properties["step_size"] = str(step_size); +// +// if (state_type == "MCMC::State") +// properties["axis_scales_location"] = str(axis_scales_location); +// +// if (object_type == "Diffusion::Response") +// properties["diff_encode_index"] = str(obs_image_name); +// +// if (obs_image_name.size()) +// properties["obs_image"] = obs_image_name; +// +// if (object_type.substr(0,9) == "Diffusion") { +// ADD_DIFFUSION_PROPERTIES(properties); +// +// } else if (object_type.substr(0,17) == "Prob::Likelihood") { +// ADD_LIKELIHOOD_PROPERTIES(properties); +// +// ADD_EXPECTED_IMAGE_PROPERTIES(properties); +// +// ADD_DIFFUSION_PROPERTIES(properties); +// +//// ADD_DENSITY_IMAGE_PROPERTIES(properties); +// +// +// } else if (object_type.substr(0,5) == "Image") { +// ADD_IMAGE_PROPERTIES(properties); +// +// if (object_type.substr(7,8) == "Expected") { +// +// ADD_EXPECTED_IMAGE_PROPERTIES(properties); +// +// ADD_DIFFUSION_PROPERTIES(properties); +// +// } +//// } else if (object_type.substr(7,7) == "Density") { +//// +//// ADD_DENSITY_IMAGE_PROPERTIES(properties); +//// +//// } +// +// } else if (object_type.substr(0,11) == "Prob::Prior") { +// ADD_PRIOR_PROPERTIES(properties); +// +// } else if (object_type == "Prob::Test::Landscape") +// ADD_TEST_LANDSCAPE_PROPERTIES(properties); +// +// +// +// +// +// +// +////----------------------------------------------------------------------------------------------------------------// +////---------------------------------------- Select State, Object and Function -----------------------------------// +////----------------------------------------------------------------------------------------------------------------// +// +// +// +// +// +////----------------------------// +////------ Fibre::Strand -------// +////----------------------------// +// +// +// if (state_type == "Fibre::Strand") { +// +// //--- Prob::Prior ---// +// +// if (object_type == "Prob::Prior") { +// +// if (function_name == "log_prob") { +// +// if (calculate_hessian) { +// TEST_HESSIAN(Fibre::Strand, Prob::Prior, log_prob, prior); +// } else { +// TEST_GRADIENT(Fibre::Strand, Prob::Prior, log_prob, prior); +// } +// +// } else if (function_name == "log_prob_and_fisher") { +// +// TEST_FISHER_GRADIENT(Fibre::Strand, Prob::Prior, log_prob_and_fisher, prior); +// +// } else +// throw Exception ("Unrecognised function '" + object_type + "::" + function_name + "(const " + state_type + "&, " + state_type + "&)'."); +// +// +////--- Prob::Prior::Magnitude ---// +// +// } else if (object_type == "Prob::PriorComponent::Magnitude") { +// +// Prob::PriorComponent::Magnitude prior_curvature_magnitude (prior_mag_scale); +// +// if (function_name == "log_prob") { +// +// if (calculate_hessian) { +// TEST_HESSIAN(Fibre::Strand, Prob::PriorComponent::Magnitude, log_prob, prior_curvature_magnitude); +// } else { +// TEST_GRADIENT(Fibre::Strand, Prob::PriorComponent::Magnitude, log_prob, prior_curvature_magnitude); +// } +// +// } else if (function_name == "log_prob_and_fisher") { +// +// TEST_FISHER_GRADIENT(Fibre::Strand, Prob::PriorComponent::Magnitude, log_prob_and_fisher, prior_curvature_magnitude); +// +// } else +// throw Exception ("Unrecognised function '" + object_type + "::" + function_name + "(const " + state_type + "&, " + state_type + "&)'."); +// +////--- Prob::Prior::Hook ---// +// +// } else if (object_type == "Prob::Prior::Hook") { +// +// Prob::Prior::Hook prior_midpoint_insidecube (prior_hook_scale, prior_hook_num_points, prior_mid_cube_sd); +// +// if (function_name == "log_prob") { +// +// TEST_GRADIENT(Fibre::Strand, Prob::Prior::Hook, log_prob, prior_midpoint_insidecube); +// +// } else +// throw Exception ("Unrecognised function '" + object_type + "::" + function_name + "(const " + state_type + "&, " + state_type + "&)'."); +// } +////--- Image::Expected::Quartic::Buffer ---// +// +// } else if (object_type == "Image::Expected::Quartic::Buffer") { +// +// Image::Expected::Quartic::Buffer exp_image_quartic ( img_dims, +// img_vox_lengths, +// diffusion_model, +// exp_num_length_sections, +// exp_num_width_sections, +// exp_interp_extent, +// img_offsets, +// exp_enforce_bounds); +// +// if (function_name == "part_image") { +// +// if (calculate_hessian) { +// TEST_IMAGE_HESSIAN(Fibre::Strand, Image::Expected::Quartic::Buffer, part_image, exp_image_quartic); +// } else { +// TEST_IMAGE_GRADIENT(Fibre::Strand, Image::Expected::Quartic::Buffer, part_image, exp_image_quartic); +// } +// +// } else +// throw Exception ("Unrecognised function '" + object_type + "::" + function_name + "(const " + state_type + "&, " + state_type + "&)'."); +// +// +// } else +// throw Exception ("Unrecognised object_type, '" + object_type + "', for state type '" + state_type + "'."); +// +// +////----------------------------// +////------ Fibre::Tractlet -------// +////----------------------------// +// +// +// } else if (state_type == "Fibre::Tractlet") { +// +// if (object_type == "Prob::Prior::Density") { +// +// Prob::Prior::Density prior_density (prior_density_high_scale, prior_density_low_scale, prior_density_num_points); +// +// if (function_name == "log_prob") { +// +// if (calculate_hessian) { +// +// TEST_HESSIAN(Fibre::Tractlet, Prob::Prior::Density, log_prob, prior_density); +// +// } else { +// +// TEST_GRADIENT(Fibre::Tractlet, Prob::Prior::Density, log_prob, prior_density); +// +// } +// +// } else if (function_name == "log_prob_and_fisher") { +// +// TEST_FISHER_GRADIENT(Fibre::Tractlet, Prob::Prior::Density, log_prob_and_fisher, prior_density); +// +// } else +// throw Exception ("Unrecognised function '" + object_type + "::" + function_name + "(const " + state_type + "&, " + state_type + "&)'."); +// +// } else if (object_type == "Image::Expected::Quartic::Buffer") { +// +// Image::Expected::Quartic::Buffer exp_image_quartic ( img_dims, +// img_vox_lengths, +// diffusion_model, +// exp_num_length_sections, +// exp_num_width_sections, +// exp_interp_extent, +// img_offsets, +// exp_enforce_bounds); +// +// if (function_name == "part_image") { +// if (calculate_hessian) { +// +// Fibre::Tractlet state; +// Fibre::Tractlet::Reader reader (state_location); +// if (!reader.next(state)) +// throw Exception ("Did not find any states in file '" + state_location + "'."); +// reader.close(); +// +// Fibre::Tractlet::Tensor::Writer analytic_writer (analytic_output_location + ".tnr", state), numeric_writer (numeric_output_location + ".tnr", state); +// reader.open(state_location); +// +// Analysis::ImageHessianTester hess_tester (exp_image_quartic); +// Analysis::ImageHessianTester::Function test_function; +// +// test_function = &Image::Expected::Quartic::Buffer::part_image; +// +// while (reader.next(state)) { +// +// exp_image_quartic.zero(); +// +// Image::Container::Buffer analytic_hessian(img_dims, exp_image_quartic.num_encodings()); +// Image::Container::Buffer numeric_hessian(img_dims, exp_image_quartic.num_encodings()); +// +// hess_tester.test(test_function, state, step_size, analytic_hessian, numeric_hessian); +// +// for (size_t z = 0; z < exp_image_quartic.dim(Z); z++) { +// for (size_t y = 0; y < exp_image_quartic.dim(Y); y++) { +// for (size_t x = 0; x < exp_image_quartic.dim(X); x++) { +// for (size_t encode_i = 0; encode_i < exp_image_quartic.num_encodings(); encode_i++) { +// analytic_writer.append(analytic_hessian(x,y,z)[encode_i]); +// numeric_writer.append(numeric_hessian(x,y,z)[encode_i]); +// } +// } +// } +// } +// } +// +// reader.close(); +// analytic_writer.close(); +// numeric_writer.close(); +// +//// TEST_IMAGE_HESSIAN(Fibre::Tractlet, Image::Expected::Quartic::Buffer, part_image, exp_image_quartic); +// } else { +// TEST_IMAGE_GRADIENT(Fibre::Tractlet, Image::Expected::Quartic::Buffer, part_image, exp_image_quartic); +// } +// } else +// throw Exception ("Unrecognised function '" + object_type + "::" + function_name + "(const " + state_type + "&, " + state_type + "&)'."); +// +// +// } else +// throw Exception ("Unrecognised object_type, '" + object_type + "', for state type '" + state_type + "'."); +// +// +////----------------------------// +////----- Fibre::Strand::Set----// +////----------------------------// +// +// } else if (state_type == "Fibre::Strand::Set") { +// +////--- Prob::Likelihood::Gaussian ---// +// +// if (object_type == "Prob::Likelihood::Gaussian") { +// +// Prob::Likelihood::Gaussian likelihood_imagediff_gaussian (obs_image, exp_image, 1); +// +// if (function_name == "log_prob") { +// if (calculate_hessian) { +// TEST_HESSIAN(Fibre::Strand::Set, Prob::Likelihood::Gaussian, log_prob, likelihood_imagediff_gaussian); +// } else { +// TEST_GRADIENT(Fibre::Strand::Set, Prob::Likelihood::Gaussian, log_prob, likelihood_imagediff_gaussian); +// } +// } else if (function_name == "log_prob_and_fisher") { +// +// if (calculate_hessian) { +// +// std::cout << "WARNING!! Requires that observed image is equal to expected image for given strand set." << std::endl; +// +// TEST_HESSIAN(Fibre::Strand::Set, Prob::Likelihood::Gaussian, log_prob_and_fisher, likelihood_imagediff_gaussian); +// } else { +// TEST_FISHER_GRADIENT_MATRIX(Fibre::Strand::Set, Prob::Likelihood::Gaussian, log_prob_and_fisher, likelihood_imagediff_gaussian); +// } +// } else +// throw Exception ("Unrecognised function '" + object_type + "::" + function_name + "(const " + state_type + "&, " + state_type + "&)'."); +// +//#ifndef ONLY_ACTIVE_FUNCTIONS +////--- Prob::Likelihood::OneSidedGaussian ---// +// } else if (object_type == "Prob::Likelihood::OneSidedGaussian") { +// +// Prob::Likelihood::OneSidedGaussian likelihood_weak (&obs_image, exp_image, 1); +// +// if (function_name == "log_prob") { +// +// TEST_GRADIENT(Fibre::Strand::Set, Prob::Likelihood::OneSidedGaussian, log_prob, likelihood_weak); +// +// } else +// throw Exception ("Unrecognised function '" + object_type + "::" + function_name + "(const " + state_type + "&, " + state_type + "&)'."); +//#endif +// +////--- Prob::Likelihood::OneSidedGaussian ---// +// } else if (object_type == "Prob::Prior") { +// +// Prob::Prior prior_strand = *dynamic_cast(prior); +// +// if (function_name == "log_prob") { +// if (calculate_hessian) { +// TEST_HESSIAN(Fibre::Strand::Set, Prob::Prior, log_prob, prior_strand); +// } else { +// TEST_GRADIENT(Fibre::Strand::Set, Prob::Prior, log_prob, prior_strand); +// } +// +// } else if (function_name == "log_prob_and_fisher") { +// +// TEST_FISHER_GRADIENT_MATRIX(Fibre::Strand::Set, Prob::Prior, log_prob_and_fisher, prior_strand); +// +// } else +// throw Exception ("Unrecognised function '" + object_type + "::" + function_name + "(const " + state_type + "&, " + state_type + "&)'."); +// +// } else +// throw Exception ("Unrecognised object_type, '" + object_type + "', for state type '" + state_type + "'."); +// +// +// +////----------------------------// +////----- Fibre::Tractlet::Set ----// +////----------------------------// +// +// } else if (state_type == "Fibre::Tractlet::Set") { +// +// +////--- Prob::Likelihood::Gaussian ---// +// if (object_type == "Prob::Likelihood::Gaussian") { +// +// Prob::Likelihood::Gaussian likelihood_imagediff_gaussian (obs_image, exp_image, 1); +// +// if (function_name == "log_prob") { +// +// if (calculate_hessian) { +// TEST_HESSIAN(Fibre::Tractlet::Set, Prob::Likelihood::Gaussian, log_prob, likelihood_imagediff_gaussian); +// } else { +// TEST_GRADIENT(Fibre::Tractlet::Set, Prob::Likelihood::Gaussian, log_prob, likelihood_imagediff_gaussian); +// } +// +// } else if (function_name == "log_prob_and_fisher") { +// +// TEST_FISHER_GRADIENT_MATRIX(Fibre::Tractlet::Set, Prob::Likelihood::Gaussian, log_prob_and_fisher, likelihood_imagediff_gaussian); +// +// } else +// throw Exception ("Unrecognised function '" + object_type + "::" + function_name + "(const " + state_type + "&, " + state_type + "&)'."); +// +//#ifndef ONLY_ACTIVE_FUNCTIONS +////--- Prob::Likelihood::OneSidedGaussian ---// +// +// } else if (object_type == "Prob::Likelihood::OneSidedGaussian") { +// +// Prob::Likelihood::OneSidedGaussian likelihood_weak (&obs_image, exp_image, 1); +// +//// if (function_name == "log_prob") { +//// +//// TEST_GRADIENT(Fibre::Tractlet::Set, Prob::Likelihood::OneSidedGaussian, log_prob, likelihood_weak); +//// +//// } else +// throw Exception ("Unrecognised function '" + object_type + "::" + function_name + "(const " + state_type + "&, " + state_type + "&)'."); +//#endif +// +// } else +// throw Exception ("Unrecognised object_type, '" + object_type + "', for state type '" + state_type + "'."); +// +// +// +////-----------------// +////----- Triple ----// +////-----------------// +// +// } else if (state_type == "Triple") { +// +// if (object_type == "Diffusion::Response") { +// +// if (function_name == "weighting") { +// +// if (calculate_hessian) { +// TEST_OBJECT_ELEMENT_HESSIAN(Coord, Diffusion::Response, weighting, diffusion_model); +// } else { +// TEST_OBJECT_ELEMENT_GRADIENT(Coord, Diffusion::Response, weighting, diffusion_model); +// } +// +// } else +// throw Exception ("Unrecognised function '" + object_type + "::" + function_name + "(const " + state_type + "&, " + state_type + "&)'."); +// +//#ifndef ONLY_ACTIVE_FUNCTIONS +// } else if (object_type == "Image::Expected::Trilinear::Voxel") { +// +// +// Image::Expected::Trilinear::Buffer exp_image_trilinear ( img_dims, +// img_vox_lengths, +// diffusion_model, +// exp_num_length_sections, +// exp_num_width_sections, +// exp_interp_extent, +// img_offsets, +// exp_enforce_bounds); +// +// if (function_name == "interpolate") { +// +// TEST_VOXEL_GRADIENT(Triple, Image::Expected::Trilinear::Voxel, interpolate, exp_image_trilinear); +// +// } else +// throw Exception ("Unrecognised function '" + object_type + "::" + function_name + "(const " + state_type + "&, " + state_type + "&)'."); +//#endif +//#ifndef ONLY_ACTIVE_FUNCTIONS +// } else if (object_type == "Image::Expected::Gaussian::Voxel") { +// +// +// Image::Expected::Gaussian::Buffer exp_image_gaussian ( img_dims, +// img_vox_lengths, +// diffusion_model, +// exp_num_length_sections, +// exp_num_width_sections, +// exp_interp_extent, +// exp_half_width, +// img_offsets, +// exp_enforce_bounds); +// +// if (function_name == "interpolate") { +// +// TEST_VOXEL_GRADIENT(Triple, Image::Expected::Gaussian::Voxel, interpolate, exp_image_gaussian); +// +// } else +// throw Exception ("Unrecognised function '" + object_type + "::" + function_name + "(const " + state_type + "&, " + state_type + "&)'."); +//#endif +// } else if (object_type == "Image::Expected::Quartic::Voxel") { +// +// +// Image::Expected::Quartic::Buffer exp_image_quartic ( img_dims, +// img_vox_lengths, +// diffusion_model, +// exp_num_length_sections, +// exp_num_width_sections, +// exp_interp_extent, +// img_offsets, +// exp_enforce_bounds); +// +// if (function_name == "interpolate") { +// +// if (calculate_hessian) { +// TEST_VOXEL_HESSIAN(Coord, Image::Expected::Quartic::Voxel, interpolate, exp_image_quartic); +// } else { +// TEST_VOXEL_GRADIENT(Coord, Image::Expected::Quartic::Voxel, interpolate, exp_image_quartic); +// } +// +// } else +// throw Exception ("Unrecognised function '" + object_type + "::" + function_name + "(const " + state_type + "&, " + state_type + "&)'."); +// +// } else +// throw Exception ("Unrecognised -object_type '" + object_type + "' for state type '" + state_type + "'."); +// +// +////---------------------------------------// +////----- Fibre::Strand::Section ----// +////---------------------------------------// +// +// } else if (state_type == "Fibre::Strand::Section") { +// +//#ifdef CODE_TESTING +// +// if (object_type == "Image::Expected::Quartic::Voxel") { +// +// +// Image::Expected::Quartic::Buffer exp_image_quartic ( img_dims, +// img_vox_lengths, +// diffusion_model, +// exp_num_length_sections, +// exp_num_width_sections, +// exp_interp_extent, +// img_offsets, +// exp_enforce_bounds); +// +// if (function_name == "interpolate") { +// +// if (calculate_hessian) { +// TEST_VOXEL_HESSIAN(Fibre::Strand::Section, Image::Expected::Quartic::Voxel, interpolate, exp_image_quartic); +// } else { +// TEST_VOXEL_GRADIENT(Fibre::Strand::Section, Image::Expected::Quartic::Voxel, interpolate, exp_image_quartic); +// } +// +// } else +// throw Exception ("Unrecognised function '" + object_type + "::" + function_name + "(const " + state_type + "&, " + state_type + "&)'."); +// +// +//#ifndef ONLY_ACTIVE_FUNCTIONS +// } else if (object_type == "Image::Expected::Trilinear::Direction") { +// +// +// Image::Expected::Trilinear::Buffer exp_image_trilinear ( img_dims, +// img_vox_lengths, +// diffusion_model, +// exp_num_length_sections, +// exp_num_width_sections, +// exp_interp_extent, +// img_offsets, +// exp_enforce_bounds); +// +// if (function_name == "signal") { +// +// TEST_DIRECTION_GRADIENT(Fibre::Strand::Section, signal, exp_image_trilinear); +// +// } else +// throw Exception ("Unrecognised function '" + object_type + "::" + function_name + "(const " + state_type + "&, " + state_type + "&)'."); +// +//#endif +//#ifndef ONLY_ACTIVE_FUNCTIONS +// } else if (object_type == "Image::Expected::Gaussian::Direction") { +// +// +// Image::Expected::Gaussian::Buffer exp_image_gaussian ( img_dims, +// img_vox_lengths, +// diffusion_model, +// exp_num_length_sections, +// exp_num_width_sections, +// exp_interp_extent, +// exp_half_width, +// img_offsets, +// exp_enforce_bounds); +// +// if (function_name == "signal") { +// +// TEST_DIRECTION_GRADIENT(Fibre::Strand::Section, signal, exp_image_gaussian); +// +// } else +// throw Exception ("Unrecognised function '" + object_type + "::" + function_name + "(const " + state_type + "&, " + state_type + "&)'."); +// +//#endif +// } else if (object_type == "Image::Expected::Quartic::Direction") { +// +// +// Image::Expected::Quartic::Buffer exp_image_quartic ( img_dims, +// img_vox_lengths, +// diffusion_model, +// exp_num_length_sections, +// exp_num_width_sections, +// exp_interp_extent, +// img_offsets, +// exp_enforce_bounds); +// +// if (function_name == "signal") { +// if (calculate_hessian) { +// TEST_DIRECTION_HESSIAN(Fibre::Strand::Section, signal, exp_image_quartic); +// } else { +// TEST_DIRECTION_GRADIENT(Fibre::Strand::Section, signal, exp_image_quartic); +// } +// } else +// throw Exception ("Unrecognised function '" + object_type + "::" + function_name + "(const " + state_type + "&, " + state_type + "&)'."); +// +// +// +// } else +// throw Exception ("Unrecognised -object_type '" + object_type + "' for state type '" + state_type + "'."); +// +//#else +// +// throw Exception ("test_gradient must be compiled with CODE_TESTING macro to test Fibre::Strand::Sections."); +// +//#endif /* CODE_TESTING */ +// +// } else if (state_type == "Fibre::Tractlet::Section") { +// +//#ifdef CODE_TESTING +// +// if (object_type == "Image::Expected::Direction::Quartic") { +// +// Image::Expected::Quartic::Buffer exp_image_quartic ( img_dims, +// img_vox_lengths, +// diffusion_model, +// exp_num_length_sections, +// exp_num_width_sections, +// exp_interp_extent, +// img_offsets, +// exp_enforce_bounds); +// +// if (function_name == "signal") { +// +// TEST_DIRECTION_GRADIENT(Fibre::Tractlet::Section, signal, exp_image_quartic); +// +// } else +// throw Exception ("Unrecognised function '" + object_type + "::" + function_name + "(const " + state_type + "&, " + state_type + "&)'."); +// +//#ifndef ONLY_ACTIVE_FUNCTIONS +// } else if (object_type == "Image::Expected::Direction::Trilinear") { +// +// +// Image::Expected::Trilinear::Buffer exp_image_trilinear ( img_dims, +// img_vox_lengths, +// diffusion_model, +// exp_num_length_sections, +// exp_num_width_sections, +// exp_interp_extent, +// img_offsets, +// exp_enforce_bounds); +// +// if (function_name == "signal") { +// +// TEST_DIRECTION_GRADIENT(Fibre::Tractlet::Section, signal, exp_image_trilinear); +// +// } else +// throw Exception ("Unrecognised function '" + object_type + "::" + function_name + "(const " + state_type + "&, " + state_type + "&)'."); +// +//#endif +//#ifndef ONLY_ACTIVE_FUNCTIONS +// } else if (object_type == "Image::Expected::Direction::Gaussian") { +// +// +// Image::Expected::Gaussian::Buffer exp_image_gaussian ( img_dims, +// img_vox_lengths, +// diffusion_model, +// exp_num_length_sections, +// exp_num_width_sections, +// exp_interp_extent, +// exp_half_width, +// img_offsets, +// exp_enforce_bounds); +// +// if (function_name == "signal") { +// +// TEST_DIRECTION_GRADIENT(Fibre::Tractlet::Section, signal, exp_image_gaussian); +// +// } else +// throw Exception ("Unrecognised function '" + object_type + "::" + function_name + "(const " + state_type + "&, " + state_type + "&)'."); +// +//#endif +// } else +// throw Exception ("Unrecognised -object_type '" + object_type + "' for state type '" + state_type + "'."); +// +// +// +//#else +// +// throw Exception ("test_gradient must be compiled with CODE_TESTING macro to test Fibre::Tractlet::Sections."); +// +//#endif /* CODE_TESTING */ +// +// //---------------------------// +// //----- Image::Observed ----// +// //---------------------------// +// +// } else if (state_type == "Image::Observed") { +// +// +// Image::Observed::Buffer image (state_location); //, Diffusion::Encoding::Set(diff_encodings)); +// +// +//// if (object_type == "Image::Observed") { +//// +//// if (function_name == "sum_strong_difference") { +//// +//// TEST_IMAGE_POINTER_GRADIENT(Image::Observed, Image::Observed, sum_strong_difference, obs_image, image); +//// +//// } else if (function_name == "sum_weak_difference") { +//// +//// TEST_IMAGE_POINTER_GRADIENT(Image::Observed, Image::Observed, sum_weak_difference, obs_image, image); +//// +//// } else +//// throw Exception ("Unrecognised function '" + object_type + "::" + function_name + "(const " + state_type + "&, " + state_type + "&)'."); +//// } else +//// throw Exception ("Unrecognised -object_type '" + object_type + "' for state type '" + state_type + "'."); +//// +//// +// throw Exception ("deprecated."); +// +////----------------------// +////----- MCMC::State ----// +////----------------------// +// +// } else if (state_type == "MCMC::State") { +// +// if (object_type == "Prob::Test::Gaussian") { +// +// if (function_name == "log_prob") { +// +// if (calculate_hessian) { +// TEST_HESSIAN(MCMC::State, Prob::Test::Gaussian, log_prob, test_gaussian); +// } else { +// TEST_GRADIENT(MCMC::State, Prob::Test::Gaussian, log_prob, test_gaussian); +// } +// } else +// throw Exception ("Unrecognised function '" + object_type + "::" + function_name + "(const " + state_type + "&, " + state_type + "&)'."); +// +// } else if (object_type == "Prob::Test::Landscape") { +// +// if (function_name == "log_prob") { +// +// if (calculate_rank3_hessian) { +// TEST_RANK3_HESSIAN(MCMC::State, Prob::Test::Landscape, log_prob, test_landscape); +// } else if (calculate_hessian) { +// TEST_HESSIAN(MCMC::State, Prob::Test::Landscape, log_prob, test_landscape); +// } else { +// TEST_GRADIENT(MCMC::State, Prob::Test::Landscape, log_prob, test_landscape); +// } +// +// } else +// throw Exception ("Unrecognised function '" + object_type + "::" + function_name + "(const " + state_type + "&, " + state_type + "&)'."); +// +// +// } else if (object_type == "Prob::Test::Landscape::Peak") { +// +// if (function_name == "gaussian_log_prob") { +// +// +// if (calculate_rank3_hessian) { +// TEST_RANK3_HESSIAN(MCMC::State, Prob::Test::Landscape::Peak, gaussian_log_prob, test_landscape[element_index]); +// } else if (calculate_hessian) { +// TEST_HESSIAN(MCMC::State, Prob::Test::Landscape::Peak, gaussian_log_prob, test_landscape[element_index]); +// } else { +// TEST_GRADIENT(MCMC::State, Prob::Test::Landscape::Peak, gaussian_log_prob, test_landscape[element_index]); +// } +// +// } else +// throw Exception ("Unrecognised function '" + object_type + "::" + function_name + "(const " + state_type + "&, " + state_type + "&)'."); +// +// +// } else +// throw Exception ("Unrecognised -object_type '" + object_type + "' for state type '" + state_type + "'."); +// +// +// } else +// throw Exception ("Unrecognised state_type, '" + state_type + "'."); +// +// +// delete likelihood; +// delete exp_image; +// +// std::cout << std::endl << "Generated analytic and numerical gradients: " << std::endl; +// std::cout << " State: " << state_type << std::endl; +// std::cout << " Object: " << object_type << std::endl; +// std::cout << " Function: " + function_name << "\n" << std::endl; +// +// std::cout << "\nMATLAB Plot command:\n\nclose all; "; +// +// if (function_name == "log_prob_and_fisher") +// std::cout << "plot_fisher_gradient " + output_location << ".tnr\n\n" << std::endl; +// else if (calculate_rank3_hessian) +// std::cout << "plot_rank3_hessian " + output_location << ".tnr3\n\n" << std::endl; +// else if (calculate_hessian) +// std::cout << "plot_hessian " + output_location << ".tnr\n\n" << std::endl; +// else +// std::cout << "plot_gradient " + output_location << "\n\n" << std::endl; +//// + +} + + diff --git a/cmd/test_scan.cpp b/cmd/test_scan.cpp new file mode 100644 index 0000000..a690771 --- /dev/null +++ b/cmd/test_scan.cpp @@ -0,0 +1,173 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, 10/09/2010. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + + +#include "bts/cmd.h" + +#include "bts/common.h" +#include "bts/file.h" +#include "image/header.h" +#include "bts/prob/test/landscape.h" + +#include "bts/inline_functions.h" + +using namespace BTS; + +SET_VERSION_DEFAULT; +SET_AUTHOR ("Thomas G. Close"); +SET_COPYRIGHT (NULL); + +DESCRIPTION = { + "test_scan", + "", + NULL +}; + +ARGUMENTS = { + Argument ("input_peaks","Location of the input peaks file").type_file (), + Argument ("output_image","Location of the output image").optional().type_image_out (), + Argument() +}; + + +double NUM_STEPS_DEFAULT = 100; +double AXIS_SCALE_DEFAULT = 15.0; + +OPTIONS = { + + Option ("num_steps1", "Number of taken along axis.") + + Argument ("num_steps", "").type_integer (1, NUM_STEPS_DEFAULT, LARGE_INT), + + Option ("num_steps2", "Number of taken along second axis.") + + Argument ("num_steps", "").type_integer (1, NUM_STEPS_DEFAULT, LARGE_INT), + + Option ("axis1_scale", "Scale applied to axis1, used to quickly scale binary masks.") + + Argument ("axis1_scale", "").type_float (SMALL_FLOAT, AXIS_SCALE_DEFAULT, LARGE_FLOAT), + + Option ("axis2_scale", "Scale applied to axis2, used to quickly scale binary masks.") + + Argument ("axis2_scale", "").type_float (SMALL_FLOAT, AXIS_SCALE_DEFAULT, LARGE_FLOAT), + +Option() }; + + + +EXECUTE { + + + std::string input_location = argument[0]; + std::string output_location; + + if (argument.size() == 2) + output_location = argument[0].c_str(); + else + output_location = File::strip_extension(input_location) + ".mif"; + + size_t num_steps1 = NUM_STEPS_DEFAULT;; + size_t num_steps2; + + double axis1_scale = AXIS_SCALE_DEFAULT; + double axis2_scale; + + Options opt = get_options("num_steps1"); + if (opt.size()) + num_steps1 = opt[0][0]; + + opt = get_options("num_steps2"); + if (opt.size()) + num_steps2 = opt[0][0]; + else + num_steps2 = num_steps1; + + opt = get_options("axis1_scale"); + if (opt.size()) + axis1_scale = opt[0][0]; + + opt = get_options("axis2_scale"); + if (opt.size()) + axis2_scale = opt[0][0]; + else + axis2_scale = axis1_scale; + + + Prob::Test::Landscape peaks(input_location); + + if (peaks.num_dims() != 2) + throw Exception ("Can only produce scan image for peaks of dimension 2 (" + str(peaks.num_dims()) + " supplied)."); + + MCMC::State point(2); + + MR::Image::Header header; + + header.set_ndim(2); + + header.set_dim(0, num_steps1); + header.set_dim(1, num_steps2); + + header.set_description(0, File::basename("Axis 1")); + header.set_description(1, File::basename("Axis 2")); + + header.set_vox(0, 2.0 * axis1_scale / (double)num_steps1); + header.set_vox(1, 2.0 * axis2_scale / (double)num_steps2); + + + header["num_steps1"] = str(num_steps1); + header["num_steps2"] = str(num_steps2); + + header["axis1_scale"] = str(axis1_scale); + header["axis2_scale"] = str(axis2_scale); + + + File::clear_path(output_location); + + header.create(output_location); + + double inc1 = 2.0 / (double)(num_steps1 - 1); + double inc2 = 2.0 / (double)(num_steps2 - 1); + + MR::Image::Voxel pixel (header); + + //Nicety, makes sure the loop goes out of scope, and prints its close message before the MATLAB plot command is issued. + if (1) { + + MR::DataSet::Loop loop ("Scanning over 2 dimensions...", 0, 2); + loop.start(pixel); + + for (double frac1 = -1.0; frac1 <= 1.0 + inc1/2.0; frac1 += inc1) { // The +inc/2.0 safeguards against rounding errors. + + for (double frac2 = -1.0; frac2 <= 1.0 + inc2/2.0; frac2 += inc2) { + + point[0] = frac1 * axis1_scale; + point[1] = frac2 * axis2_scale; + + pixel.value() = peaks.log_prob(point); + + loop.next(pixel); + + } + + } + } + + std::cout << std::endl << "\nMATLAB plot command:\n\nplot_test_scan " << output_location << "\n" << std::endl; + + +} diff --git a/cmd/thesis_merge.cpp b/cmd/thesis_merge.cpp new file mode 100644 index 0000000..a8f061b --- /dev/null +++ b/cmd/thesis_merge.cpp @@ -0,0 +1,119 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + +#include "bts/common.h" + +#include "bts/cmd.h" +#include "progressbar.h" + +#include "bts/fibre/track.h" +#include "bts/fibre/track/set.h" + +#include "bts/math/odr.h" + + +#include "bts/inline_functions.h" + + +using namespace BTS; + +SET_VERSION_DEFAULT; +SET_AUTHOR ("Thomas G. Close"); +SET_COPYRIGHT (NULL); + +DESCRIPTION = { + "Trims paths to a sphere of specified radius.", + "The sections of paths that lie outside the radius of the sphere are removed and sections that reenter are split into new paths.", + NULL +}; + +ARGUMENTS = { +// Argument ("input", "The tracks to be offset.").type_file (), +// Argument ("output", "The returned offset tracks.").optional().type_file(), + Argument() +}; + + +OPTIONS = { + + Option ("degree", "The degree of the merged strand.") + + Argument ("degree", "").type_integer (1, 4, LARGE_INT), + + +Option() }; + + +EXECUTE { + + +// std::string input_location = argument[0]; +// std::string output_location; +// +// if (argument.size() > 1) +// output_location = argument[1]; +// else +// output_location = input_location; + + size_t degree = 4; + + Options opt = get_options("degree"); + if (opt.size()) + degree = opt[0][0]; + + Fibre::Strand::Set strands("/home/tclose/thesis/MCMC/data/merge/both.str"); + Fibre::Strand::Set combined; + + MR::ProgressBar pb("Merging..."); + + Fibre::Strand merged = strands[0].merge(strands[1], 100, degree); + + combined.push_back(merged); + + combined.save("/home/tclose/thesis/MCMC/data/merge/merged.str"); + + + //Generate ODR line + Fibre::Track::Set tcks = strands.to_tracks(10); + + std::vector points; + + for (size_t tck_i = 0; tck_i < 2; tck_i++) + for (size_t point_i = 0; point_i < tcks[tck_i].size(); ++point_i) + points.push_back(tcks[tck_i][point_i]); + + Math::Line odr_line = Math::odr(points); + + std::ofstream fout ("/home/tclose/thesis/MCMC/data/merge/odr.txt"); + + fout << odr_line.centre[0] << " " << odr_line.centre[1] << " " << odr_line.centre[2] << " " << std::endl; + fout << odr_line.direction[0] << " " << odr_line.direction[1] << " " << odr_line.direction[2] << " " << std::endl; + +} + + + + + + + + + diff --git a/cmd/trim_fibres.cpp b/cmd/trim_fibres.cpp new file mode 100644 index 0000000..8b653ab --- /dev/null +++ b/cmd/trim_fibres.cpp @@ -0,0 +1,304 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + +#include "bts/common.h" + +#include "bts/cmd.h" +#include "progressbar.h" + + +#include "phantom/interface.h" + +#include "phantom/trim/trim.h" +#include "bts/fibre/track.h" +#include "bts/fibre/track/set.h" +#include "bts/fibre/tractlet.h" +#include "bts/fibre/tractlet/set.h" + + + +#include "bts/inline_functions.h" + +const size_t NUM_LENGTH_SECTIONS_DEFAULT = 50; +const size_t NUM_WIDTH_SECTIONS_DEFAULT = 40; + +using namespace BTS; + +SET_VERSION_DEFAULT; +SET_AUTHOR ("Thomas G. Close"); +SET_COPYRIGHT (NULL); + +DESCRIPTION = { + "Trims paths to a sphere of specified radius.", + "The sections of paths that lie outside the radius of the sphere are removed and sections that reenter are split into new paths.", + NULL +}; + +ARGUMENTS = { + Argument ("input", "The fibres to be trimmed.").type_file (), + Argument ("output", "The returned trimmed fibres.").optional().type_file(), + Argument() +}; + + +OPTIONS = { + + Option ("degree", "Limit the degree of the Strand coefficients used to describe the strands to the first - degrees") + + Argument ("degree", "Limit the degree of the Strand coefficients used to describe the strands to the first - degrees").type_integer (1, 200, 3), + + Option ("distance", "The radius of the sphere the strands will be trimmed to") + + Argument ("new_sphere_r", "").type_float (SMALL_FLOAT, 1.0, LARGE_FLOAT), + + Option ("length_reject_threshold", "The length below which new strands will be rejected") + + Argument ("length_reject_threshold", "").type_float (SMALL_FLOAT, 1.0, LARGE_FLOAT), + + Option ("num_length_sections", "The number of length sections used in conversion between tractlets or strands and tracks.") + + Argument ("num_length_sections", "").type_integer (1, NUM_LENGTH_SECTIONS_DEFAULT, LARGE_INT), + + Option ("num_width_sections", "The number of width sections used in conversion between tractlets and tracks.") + + Argument ("num_width_sections", "").type_integer (1, NUM_WIDTH_SECTIONS_DEFAULT, LARGE_INT), + + Option ("cube", "Trim the set to a cube instead of the default sphere."), + +Option() }; + + +BTS::Fibre::Track::Set trim_tcks(BTS::Fibre::Track::Set& input_tcks, double sphere_r, double length_reject_threshold, bool trim_to_cube); + +BTS::Fibre::Tractlet::Set trim_tractlets(BTS::Fibre::Tractlet::Set& input_tractlets, double distance, double length_reject_threshold, bool trim_to_cube, size_t num_length_sections, size_t num_width_sections); + +EXECUTE { + + + std::string input_location = argument[0]; + std::string output_location; + + if (argument.size() > 1) + output_location = argument[1].c_str(); + else + output_location = input_location; + + size_t num_length_sections = NUM_LENGTH_SECTIONS_DEFAULT; + size_t num_width_sections = NUM_WIDTH_SECTIONS_DEFAULT; + size_t degree = 3; + double distance = 1.0; + double length_reject_threshold = 0.05; + bool cube = false; + + Options opt = get_options("num_length_sections"); + if (opt.size()) + num_length_sections = opt[0][0]; + + opt = get_options("num_width_sections"); + if (opt.size()) + num_width_sections = opt[0][0]; + + opt = get_options("degree"); + if (opt.size()) + degree = opt[0][0]; + + opt = get_options("distance"); + if (opt.size()) + distance = opt[0][0]; + + opt = get_options("length_reject_threshold"); + if (opt.size()) + length_reject_threshold = opt[0][0]; + + opt = get_options("cube"); + if (opt.size()) + cube = true; + + + if (File::has_or_txt_extension(input_location) || File::has_or_txt_extension(input_location)) { + + BTS::Fibre::Track::Set input(input_location, num_length_sections); + + MR::ProgressBar progress_bar("Trimming strands/tracks..."); + + BTS::Fibre::Track::Set output = trim_tcks(input, distance, length_reject_threshold, cube); + + output.save(output_location, degree); + + } else if (File::has_or_txt_extension(input_location)) { + + MR::ProgressBar progress_bar("Trimming tractlets..."); + + BTS::Fibre::Tractlet::Set input(input_location); + + BTS::Fibre::Tractlet::Set output = trim_tractlets(input, distance, length_reject_threshold, cube, num_length_sections, num_width_sections); + + output.save(output_location); + + } else if (File::has_or_txt_extension(input_location)) { + + MR::ProgressBar progress_bar("Trimming strand sets..."); + + BTS::Fibre::Strand::Set::Reader reader(input_location); + + + std::map props = reader.get_extend_props(); + + props["method"] = "trim"; + props["trim_dist"] = str(distance); + props["cube"] = str(cube); + + std::vector elem_header; + + elem_header.push_back(BTS::Fibre::Track::BUNDLE_INDEX_EPROP); + + BTS::Fibre::Strand::Set::Writer writer(output_location, reader, reader.extend_prop_keys(), elem_header, props); + + BTS::Fibre::Strand::Set strands; + + while (reader.next(strands)) { + + BTS::Fibre::Track::Set tcks = strands.to_tracks(num_length_sections); + + std::map props = strands.get_extend_props(); + + BTS::Fibre::Track::Set trimmed_tcks = trim_tcks(tcks, distance, length_reject_threshold, cube); + + //FIXME: Remove explicit as it should be handled by the "loaded_degree" property + strands = trimmed_tcks.to_strands(strands[0].degree()); + + strands.set_extend_props(props); + + writer.append(strands); + + ++progress_bar; + + } + + } else if (File::has_or_txt_extension(input_location)) { + + MR::ProgressBar progress_bar("Trimming track sets..."); + + BTS::Fibre::Track::Set::Reader reader(input_location); + BTS::Fibre::Track::Set::Writer writer(output_location, reader, reader.extend_prop_keys(), reader.extend_elem_prop_keys(), reader.get_extend_props()); + + BTS::Fibre::Track::Set tracks; + + while (reader.next(tracks)) { + writer.append(trim_tcks(tracks, distance, length_reject_threshold, cube)); + + ++progress_bar; + } + + } else if (File::has_or_txt_extension(input_location)) { + + MR::ProgressBar progress_bar("Trimming tractlet sets..."); + + BTS::Fibre::Tractlet::Set::Reader reader(input_location); + + std::map props = reader.get_extend_props(); + + props["method"] = "trim"; + props["trim_dist"] = str(distance); + props["cube"] = str(cube); + + std::vector elem_header; + + elem_header.push_back(BTS::Fibre::Track::BUNDLE_INDEX_EPROP); + + BTS::Fibre::Tractlet::Set::Writer writer(output_location, reader, reader.extend_prop_keys(), elem_header, props); + + BTS::Fibre::Tractlet::Set tractlets; + + while (reader.next(tractlets)) { + writer.append(trim_tractlets(tractlets, distance, length_reject_threshold, cube, num_length_sections, num_width_sections)); + ++progress_bar; + } + + + } else + throw Exception ("Unrecognised extension for input file '" + File::extension(input_location) + "'."); + + +} + + + + +BTS::Fibre::Track::Set trim_tcks(BTS::Fibre::Track::Set& input_tcks, double distance, double length_reject_threshold, bool trim_to_cube) { + + BTS::Fibre::Track::Set trimmed_tcks(input_tcks.get_extend_props()); + + std::vector > pre_points; + std::vector > post_points; + + Strand_collection c, trimmed_c; + + input_tcks.remove_short_tracks(3); + + generate_pre_points(input_tcks, pre_points); + + generate_post_points(input_tcks, post_points); + + convert_mr_to_nfg(&c, input_tcks, pre_points, post_points); + + trim(&trimmed_c, &c, distance, length_reject_threshold, 0, trim_to_cube); + + convert_nfg_to_mr(trimmed_tcks, pre_points, post_points, &trimmed_c); + + return trimmed_tcks; + +} + + +BTS::Fibre::Tractlet::Set trim_tractlets(BTS::Fibre::Tractlet::Set& input_tractlets, double distance, double length_reject_threshold, bool trim_to_cube, size_t num_length_sections, size_t num_width_sections) { + + //FIXME: Remove this as it should be handled by the "loaded_degree" property + size_t degree = input_tractlets[0].degree(); + + BTS::Fibre::Track::Set input_tcks = input_tractlets.to_tracks(num_length_sections, num_width_sections); + + BTS::Fibre::Track::Set trimmed_tcks = trim_tcks(input_tcks, distance, length_reject_threshold, trim_to_cube); + + BTS::Fibre::Tractlet::Set trimmed_tractlets = trimmed_tcks.to_tractlets(degree); + + trimmed_tractlets.set_extend_props(input_tractlets.get_extend_props()); + + return trimmed_tractlets; + +} + + + + + + + + + + + + + + + + + + + + + diff --git a/gdb_printers/python/bts/__init__.py b/gdb_printers/python/bts/__init__.py new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/gdb_printers/python/bts/__init__.py @@ -0,0 +1 @@ + diff --git a/gdb_printers/python/bts/fibre/__init__.py b/gdb_printers/python/bts/fibre/__init__.py new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/gdb_printers/python/bts/fibre/__init__.py @@ -0,0 +1 @@ + diff --git a/gdb_printers/python/bts/fibre/__init__.pyc b/gdb_printers/python/bts/fibre/__init__.pyc new file mode 100644 index 0000000..bf02ca8 Binary files /dev/null and b/gdb_printers/python/bts/fibre/__init__.pyc differ diff --git a/gdb_printers/python/bts/fibre/printers.py b/gdb_printers/python/bts/fibre/printers.py new file mode 100644 index 0000000..fd5e529 --- /dev/null +++ b/gdb_printers/python/bts/fibre/printers.py @@ -0,0 +1,360 @@ +# Pretty-printers for 'BTS::Fibre::*'. + +# Copyright (C) 2008, 2009 Free Software Foundation, Inc. + +# 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 . + +import gdb +import itertools +import re + + + +class TriplePrinter: + "Print Triple" + + def __init__(self, val): + self.val = val + + def to_string(self): + return self.val['p'] + + def display_hint(self): + return 'array' + + +class CoordPrinter: + "Print Coord" + + def __init__(self, val): + self.val = val + + def to_string(self): + x = self.val['data'].dereference() + y = (self.val['data'] + self.val['stride']).dereference() + z = (self.val['data'] + 2 * self.val['stride']).dereference() + return "[%g, %g, %g]" % (x,y,z) + + def display_hint(self): + return 'array' + + +# +#class FibreTractletPrinter: +# "Print Fibre::Strand and Fibre::Track objects" +# +# class _iterator: +# def __init__ (self, size, degree, stride, data_ptr): +# self.size = size +# self.degree = degree +# self.stride = stride +# self.data_ptr = data_ptr +# self.count = 0 +# self.x1_offset = 0 +# self.y1_offset = stride +# self.z1_offset = stride * 2 +# self.x2_offset = stride * degree * 3 +# self.y2_offset = stride * (degree * 3 + 1) +# self.z2_offset = stride * (degree * 3 + 2) +# self.x3_offset = stride * (degree * 6) +# self.y3_offset = stride * (degree * 6 + 1) +# self.z3_offset = stride * (degree * 6 + 2) +# +# def __iter__(self): +# return self +# +# def next(self): +# if self.count == self.size: +# raise StopIteration +# count = self.count +# x1 = str((self.data_ptr + self.x1_offset).dereference()) +# y1 = str((self.data_ptr + self.y1_offset).dereference()) +# z1 = str((self.data_ptr + self.z1_offset).dereference()) +# x2 = str((self.data_ptr + self.x2_offset).dereference()) +# y2 = str((self.data_ptr + self.y2_offset).dereference()) +# z2 = str((self.data_ptr + self.z2_offset).dereference()) +# x3 = str((self.data_ptr + self.x3_offset).dereference()) +# y3 = str((self.data_ptr + self.y3_offset).dereference()) +# z3 = str((self.data_ptr + self.z3_offset).dereference()) +# self.data_ptr = self.data_ptr + self.stride * 3 +# self.count = self.count + 1 +# return ('[%d]' % count, gdb.Value(x1 + " " + y1 + " " + z1 + " | " + +# x2 + " " + y2 + " " + z2 + " | " + +# x3 + " " + y3 + " " + z3)) +# +# def __init__(self, typename, val): +# self.typename = typename +# self.val = val +# +# def children(self): +# return self._iterator(self.val['sze'], +# self.val['dgree'], +# self.val['stride'], +# self.val['data']) +# +# def to_string(self): +# return ("%s: size %d" % (self.typename, self.val['sze'])) + +#def get_element(): + +class FibreStrandTrackPrinter: + "Print Fibre::Strand and Fibre::Track objects" + + def __init__(self, typename, val): + self.typename = typename + self.val = val + self.stride = val['stride'] + self.data_ptr = val['data'] + self.size = self.val['sze'] + + def children(self): + for i in xrange(self.size): + x = self.next_elem() + y = self.next_elem() + z = self.next_elem() + yield '%d' % i, '[%g, %g, %g]' % (x,y,z) + + def to_string(self): + if self.typename == 'Fibre::Strand': + size_name = 'degree' + else: + size_name = 'size' + return ("%s (%s=%d):" % (self.typename, size_name, self.size)) + + def next_elem(self): + elem = self.data_ptr.dereference() + self.data_ptr = self.data_ptr + self.stride + return elem + + + +class FibreTractletPrinter: + "Print Fibre::Strand and Fibre::Track objects" + + def __init__(self, val): + self.val = val + self.stride = val['stride'] + self.data_ptr = val['data'] + self.size = self.val['sze'] + self.degree = self.val['dgree'] + + def children(self): + for i in xrange(self.degree): + yield '%d' % i, '[%g, %g, %g | %g, %g, %g | %g, %g, %g ]' % (self.get_elem(i, 0, 0), self.get_elem(i, 0, 1), self.get_elem(i, 0, 2), + self.get_elem(i, 1, 0), self.get_elem(i, 1, 1), self.get_elem(i, 1, 2), + self.get_elem(i, 2, 0), self.get_elem(i, 2, 1), self.get_elem(i, 2, 2)) + + def to_string(self): + return ("Fibre::Tractlet (degree=%d): " % self.degree) + + def get_elem(self, degree_i, ax_i, dim_i): + address = self.data_ptr + ((ax_i * self.degree + degree_i) * 3 + dim_i) * self.stride + return address.dereference() + + + +class FibreSectionPrinter: + "Print Fibre::Strand::Section" + + class _iterator: + def __init__ (self, section, stride, data): + self.field = 'position' + self.stride = stride + self.data = data + + def __iter__(self): + return self + + def next(self): + if self.field == 'end': + raise StopIteration + elif self.field == 'position': + self.field = 'tangent' + x = str(self.data_ptr.dereference()) + y = str((self.data_ptr + self.stride * 1).dereference()) + z = str((self.data_ptr + self.stride * 2).dereference()) + return ('position', gdb.Value("[" + x + ", " + y + ", " + z + "]")) + elif self.field == 'tangent': + self.field = 'intensity' + x = str((self.data_ptr + self.stride * 3).dereference()) + y = str((self.data_ptr + self.stride * 4).dereference()) + z = str((self.data_ptr + self.stride * 5).dereference()) + return ('tangent', gdb.Value("[" + x + ", " + y + ", " + z + "]")) + elif self.field == 'intensity': + self.field = 'end' + intensity = (self.data + 6 * self.stride).dereference() + return ('intensity', gdb.Value(intensity)) + + else: + raise StopIteration + + + def __init__(self, typename, val): + self.typename = typename + self.val = val + + def children(self): + return self._iterator(self.val['stride'], + self.val['data']) + + def to_string(self): + return "%s" % self.typename + + + class _iterator: + def __init__ (self, size, degree, stride, data_ptr): + self.size = size + self.degree = degree + self.stride = stride + self.data_ptr = data_ptr + self.count = 0 + self.x1_offset = 0 + self.y1_offset = stride + self.z1_offset = stride * 2 + self.x2_offset = stride * degree * 3 + self.y2_offset = stride * (degree * 3 + 1) + self.z2_offset = stride * (degree * 3 + 2) + self.x3_offset = stride * (degree * 6) + self.y3_offset = stride * (degree * 6 + 1) + self.z3_offset = stride * (degree * 6 + 2) + + def __iter__(self): + return self + + def next(self): + if self.count == self.size: + raise StopIteration + count = self.count + x1 = (self.data_ptr + self.x1_offset).dereference() + y1 = (self.data_ptr + self.y1_offset).dereference() + z1 = (self.data_ptr + self.z1_offset).dereference() + x2 = (self.data_ptr + self.x2_offset).dereference() + y2 = (self.data_ptr + self.y2_offset).dereference() + z2 = (self.data_ptr + self.z2_offset).dereference() + x3 = (self.data_ptr + self.x3_offset).dereference() + y3 = (self.data_ptr + self.y3_offset).dereference() + z3 = (self.data_ptr + self.z3_offset).dereference() + self.data_ptr = self.data_ptr + self.stride * 3 + self.count = self.count + 1 + return ('[%d]' % count, gdb.Value("%f.4 %f.4 %f.4 | %f.4 %f.4 %f.4 | %f.4 %f.4 %f.4 " % (x1, y1, z1, x2, y2, z2, x3, y3, z3))) + + def __init__(self, typename, val): + self.typename = typename + self.val = val + + + + def to_string(self): + return ("%s: size %d" % (self.typename, self.val['sze'])) + + +class FibreSetPrinter: + "Print Fibre::Set" + + class _iterator: + def __init__ (self, set, size): + self.set = set + self.size = size + self.count = 0 + + def __iter__(self): + return self + + def next(self): + if self.count == self.size: + raise StopIteration + count = self.count + self.count = self.count + 1 + elem = self.set['elem'](count) + return ('[%d]' % count, elem) + + def __init__(self, typename, val): + self.typename = typename + self.val = val + + def children(self): + return self._iterator(self.val, + self.val['sze']) + + def to_string(self): + return ("%s: size %d" % (self.typename, self.val['sze'])) + + + +def register_bts_fibre_printers (obj): + "Register Bayesian Tractlet Sampling (BTS) Fibre pretty-printers with objfile Obj." + + if obj == None: + obj = gdb + + obj.pretty_printers.append (lookup_function) + + +def lookup_function (val): + "Look-up and return a pretty-printer that can print val." + + # Get the type. + type = val.type + + # If it points to a reference, get the reference. + if type.code == gdb.TYPE_CODE_REF: + type = type.target () + + # Get the unqualified type, stripped of typedefs. + type = type.unqualified ().strip_typedefs () + + # Get the type name. + typename = type.tag + if typename == None: + return None + + # Iterate over local dictionary of types to determine + # if a printer is registered for that type. Return an + # instantiation of the printer if found. + for function in pretty_printers_dict: + if function.search (typename): + return pretty_printers_dict[function] (val) + + # Cannot find a pretty printer. Return None. + return None + +def build_bts_fibre_dictionary (): + # bts objects requiring pretty-printing. + # In order from: + pretty_printers_dict[re.compile('^CoordView$')] = lambda val: CoordViewPrinter(val) + pretty_printers_dict[re.compile('^BTS::Triple<.*>$')] = lambda val: TriplePrinter(val) + pretty_printers_dict[re.compile('^BTS::Coord$')] = lambda val: CoordPrinter(val) + pretty_printers_dict[re.compile('^BTS::Fibre::Strand$')] = lambda val: FibreStrandTrackPrinter("Fibre::Strand", val) + pretty_printers_dict[re.compile('^BTS::Fibre::Tractlet$')] = lambda val: FibreTractletPrinter(val) + pretty_printers_dict[re.compile('^BTS::Fibre::Track$')] = lambda val: FibreStrandTrackPrinter("Fibre::Track", val) +# pretty_printers_dict[re.compile('^BTS::Fibre::Strand::Set$')] = lambda val: FibreSetPrinter("Fibre::Strand::Set", val) +# pretty_printers_dict[re.compile('^BTS::Fibre::Tractlet::Set$')] = lambda val: FibreSetPrinter("Fibre::Tractlet::Set", val) +# pretty_printers_dict[re.compile('^BTS::Fibre::Set<.*>$')] = lambda val: FibreSetPrinter("Fibre::Set", val) +# pretty_printers_dict[re.compile('^BTS::Fibre::Track::Set$')] = lambda val: FibreSetPrinter("Fibre::Track::Set", val) +# pretty_printers_dict[re.compile('^BTS::Fibre::Strand::Tensor$')] = lambda val: FibreStrandPrinter("Fibre::Strand::Tensor", val) +# pretty_printers_dict[re.compile('^BTS::Fibre::Tractlet::Tensor$')] = lambda val: FibreTractletPrinter("Fibre::Tractlet::Tensor", val) +# pretty_printers_dict[re.compile('^BTS::Fibre::Track::Tensor$')] = lambda val: FibreTrackPrinter("Fibre::Track::Tensor", val) +# pretty_printers_dict[re.compile('^BTS::Fibre::Strand::Set::Tensor$')] = lambda val: FibreSetPrinter("Fibre::Strand::Set::Tensor", val) +# pretty_printers_dict[re.compile('^BTS::Fibre::Tractlet::Set::Tensor$')] = lambda val: FibreSetPrinter("Fibre::Tractlet::Set::Tensor", val) + pretty_printers_dict[re.compile('^BTS::Fibre::Tractlet::Section$')] = lambda val: FibreSectionPrinter("Fibre::Tractlet::Section", val) + pretty_printers_dict[re.compile('^BTS::Fibre::Strand::BasicSection$')] = lambda val: FibreSectionPrinter("Fibre::Strand::BasicSection", val) + pretty_printers_dict[re.compile('^BTS::Fibre::Strand::Section$')] = lambda val: FibreSectionPrinter("Fibre::Strand::Section", val) +# pretty_printers_dict[re.compile('^BTS::Fibre::Tractlet::Section::Tensor$')] = lambda val: FibreTractletSectionPrinter("Fibre::Tractlet::Section::Tensor", val) +# pretty_printers_dict[re.compile('^BTS::Fibre::Strand::Section::Tensor$')] = lambda val: FibreStrandSectionPrinter("Fibre::Strand::Section::Tensor", val) +# pretty_printers_dict[re.compile('^BTS::Fibre::Strand::BasicSection::Tensor$')] = lambda val: FibreStrandSectionPrinter("Fibre::Strand::BasicSection::Tensor", val) + + +pretty_printers_dict = {} + +build_bts_fibre_dictionary () diff --git a/gdb_printers/python/bts/fibre/printers.pyc b/gdb_printers/python/bts/fibre/printers.pyc new file mode 100644 index 0000000..aefc75f Binary files /dev/null and b/gdb_printers/python/bts/fibre/printers.pyc differ diff --git a/gdb_printers/python/bts/image/__init__.py b/gdb_printers/python/bts/image/__init__.py new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/gdb_printers/python/bts/image/__init__.py @@ -0,0 +1 @@ + diff --git a/gdb_printers/python/bts/image/__init__.pyc b/gdb_printers/python/bts/image/__init__.pyc new file mode 100644 index 0000000..580b211 Binary files /dev/null and b/gdb_printers/python/bts/image/__init__.pyc differ diff --git a/gdb_printers/python/bts/image/printers.py b/gdb_printers/python/bts/image/printers.py new file mode 100644 index 0000000..8ff9c7b --- /dev/null +++ b/gdb_printers/python/bts/image/printers.py @@ -0,0 +1,337 @@ +# Pretty-printers for 'BTS::Image::*'. + +# Copyright (C) 2008, 2009 Free Software Foundation, Inc. + +# 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 . + +import gdb +import itertools +import re + + +class ImageVoxelPrinter: + "Print Image::*::Voxel" + + class _iterator: + def __init__ (self, start, finish): + self.item = start + self.finish = finish + self.count = 0 + + def __iter__(self): + return self + + def next(self): + if self.item == self.finish: + raise StopIteration + count = self.count + self.count = self.count + 1 + elt = self.item.dereference() + self.item = self.item + 1 + return ('[%d]' % count, elt) + + def __init__(self, typename, template_type, val): + self.typename = typename + self.template_type = template_type + self.base_val = val.cast(gdb.lookup_type('BTS::Image::Voxel<%s>' % template_type)) + + + def children(self): + return self._iterator(self.base_val['intensities']['_M_impl']['_M_start'], + self.base_val['intensities']['_M_impl']['_M_finish']) + + def to_string(self): + return self.typename + + def display_hint(self): + if self.template_type == 'double': + return 'array' + else: + return '' + + + +class ImageDensityVoxelPrinter: + "Print Image::Density::Voxel" + + class _iterator: + def __init__ (self, val): + self.field = 'coordinate' + self.val = val + + def __iter__(self): + return self + + def next(self): + if self.field == 'end': + raise StopIteration + elif self.field == 'coordinate': + self.field = 'centre_point' + return ('coordinate', self.val['coordinate']) + elif self.field == 'centre_point': + self.field = 'tangent' + return ('centre_point', self.val['centre_point']) + elif self.field == 'dens': + self.field = 'end' + return ('dens', self.val['dens']) + + + def __init__(self, val): + self.val = val + + def to_string(self): + return 'Image::Density::Voxel' + + + +class VoxelIterator: + def __init__(self, rbtree): + self.size = rbtree['_M_t']['_M_impl']['_M_node_count'] + self.node = rbtree['_M_t']['_M_impl']['_M_header']['_M_left'] + self.count = 0 + + def __iter__(self): + return self + + def __len__(self): + return int (self.size) + + def next(self): + if self.count == self.size: + raise StopIteration + result = self.node + self.count = self.count + 1 + if self.count < self.size: + # Compute the next node. + node = self.node + if node.dereference()['_M_right']: + node = node.dereference()['_M_right'] + while node.dereference()['_M_left']: + node = node.dereference()['_M_left'] + else: + parent = node.dereference()['_M_parent'] + while node == parent.dereference()['_M_right']: + node = parent + parent = parent.dereference()['_M_parent'] + if node.dereference()['_M_right'] != parent: + node = parent + self.node = node + return result + + + +class ImageBufferPrinter: + "Print Image::*::Buffer" + + # Turn an VoxelIterator into a pretty-print iterator. + class _iter: + def __init__(self, rbiter, type): + self.rbiter = rbiter + self.count = 0 + self.type = type + + def __iter__(self): + return self + + def next(self): + if self.count % 2 == 0: + n = self.rbiter.next() + n = n.cast(self.type).dereference()['_M_value_field'] + self.pair = n + item = n['first'] + else: + item = self.pair['second'] + result = ('[%d]' % self.count, item) + self.count = self.count + 1 + return result + + def __init__ (self, typename, val): + + self.val = val + + if typename == 'BTS::Image::Buffer': + self.typename = 'BTS::Image::Buffer' + self.voxel_typename = 'BTS::Image::Voxel' + if typename == 'BTS::Image::Density::Buffer': + self.typename = 'BTS::Image::Density::Buffer' + self.voxel_typename = 'BTS::Image::Density::Voxel' + elif typename == 'BTS::Image::Container::Buffer': + self.typename = 'BTS::Image::Container::Buffer< %s >' % val.type.template_argument(0) + self.voxel_typename = 'BTS::Image::Container::Voxel< %s >' % val.type.template_argument(0) + elif typename == 'BTS::Image::Expected::Buffer_tpl': + self.typename = 'BTS::Image::Expected::Buffer_tpl< %s >' % val.type.template_argument(0) + self.voxel_typename = '%s' % val.type.template_argument(0) + elif typename == 'BTS::Image::Observed::Buffer_tpl': + self.typename = 'BTS::Image::Observed::Buffer_tpl< %s >' % val.type.template_argument(0) + self.voxel_typename = '%s' % val.type.template_argument(0) + else: + self.typename = typename + self.voxel_typename = '%s::Voxel' % '::'.join(typename.split('::')[:-1]) + + + + + def to_string (self): + return '%s' % (self.typename) + + def children (self): + nodetype = gdb.lookup_type('std::_Rb_tree_node< std::pair< const BTS::Image::Coord, %s > >' % self.voxel_typename) + nodetype = nodetype.pointer() + return self._iter (VoxelIterator (self.val['voxels']), nodetype) + + def display_hint (self): + return 'map' + +class ImageReferencePrinter: + "Print Image::Reference" + + # Turn an VoxelIterator into a pretty-print iterator. + class _iter: + def __init__(self, rbiter, type): + self.rbiter = rbiter + self.count = 0 + self.type = type + + def __iter__(self): + return self + + def next(self): + if self.count % 2 == 0: + n = self.rbiter.next() + n = n.cast(self.type).dereference()['_M_value_field'] + self.pair = n + item = n['first'] + else: + item = self.pair['second'] + result = ('[%d]' % self.count, item) + self.count = self.count + 1 + return result + + def __init__ (self, typename, val): + + self.val = val + self.typename = typename + self.voxel_typename = 'std::__debug::vector<%s*, std::allocator<%s*> >' % (val.type.template_argument(0), val.type.template_argument(0)) + + def to_string (self): + return '%s' % (self.typename) + + def children (self): + nodetype = gdb.lookup_type('std::_Rb_tree_node< std::pair< const BTS::Image::Coord, %s > >' % self.voxel_typename) + nodetype = nodetype.pointer() + return self._iter (VoxelIterator (self.val['voxels']), nodetype) + + def display_hint (self): + return 'map' + + +class ImagePrinter: + "Print Image::Observed" + + def __init__(self, val): + self.val = val + + def to_string(self): + if self.val['type'].string() == 'trilinear': + return self.val.cast(gdb.lookup_type('BTS::Image::Expected::Trilinear::Buffer')) + + elif self.val['type'].string() == 'top_hat': + return self.val.cast(gdb.lookup_type('BTS::Image::Expected::TopHat::Buffer')) + + elif self.val['type'].string() == 'gaussian': + return self.val.cast(gdb.lookup_type('BTS::Image::Expected::Gaussian::Buffer')) + + elif self.val['type'].string() == 'quartic': + return self.val.cast(gdb.lookup_type('BTS::Image::Expected::Quartic::Buffer')) + + elif self.val['type'].string() == 'realistic': + return self.val.cast(gdb.lookup_type('BTS::Image::Expected::Realistic::Buffer')) + + elif self.val['type'].string() == 'sinc': + return self.val.cast(gdb.lookup_type('BTS::Image::Expected::Sinc::Buffer')) + + elif self.val['type'].string() == 'reverse_sqrt': + return self.val.cast(gdb.lookup_type('BTS::Image::Expected::ReverseSqrt::Buffer')) + + else: + return ("Unknown observed/expected image type '%s'." % self.val['type'].string()) + + +def register_bts_image_printers (obj): + "Register Bayesian Tractlet Sampling (BTS) Image pretty-printers with objfile Obj." + + if obj == None: + obj = gdb + + obj.pretty_printers.append (lookup_function) + +def lookup_function (val): + "Look-up and return a pretty-printer that can print val." + + # Get the type. + type = val.type + + # If it points to a reference, get the reference. + if type.code == gdb.TYPE_CODE_REF: + type = type.target () + + # Get the unqualified type, stripped of typedefs. + type = type.unqualified ().strip_typedefs () + + # Get the type name. + typename = type.tag + if typename == None: + return None + + # Iterate over local dictionary of types to determine + # if a printer is registered for that type. Return an + # instantiation of the printer if found. + for function in pretty_printers_dict: + if function.search (typename): + return pretty_printers_dict[function] (val) + + # Cannot find a pretty printer. Return None. + return None + +def build_bts_image_dictionary (): + # bts objects requiring pretty-printing. + # In order from: + pretty_printers_dict[re.compile('^BTS::Image::Buffer$')] = lambda val: ImageBufferPrinter("BTS::Image::Buffer", val) + pretty_printers_dict[re.compile('^BTS::Image::Expected::Quartic::Buffer$')] = lambda val: ImageBufferPrinter("BTS::Image::Expected::Quartic::Buffer", val) + pretty_printers_dict[re.compile('^BTS::Image::Expected::Gaussian::Buffer$')] = lambda val: ImageBufferPrinter("BTS::Image::Expected::Gaussian::Buffer", val) + pretty_printers_dict[re.compile('^BTS::Image::Expected::Trilinear::Buffer$')] = lambda val: ImageBufferPrinter("BTS::Image::Expected::Trilinear::Buffer", val) + pretty_printers_dict[re.compile('^BTS::Image::Observed::Buffer$')] = lambda val: ImageBufferPrinter("BTS::Image::Observed::Buffer", val) + pretty_printers_dict[re.compile('^BTS::Image::Density::Buffer$')] = lambda val: ImageBufferPrinter("BTS::Image::Density::Buffer", val) + pretty_printers_dict[re.compile('^BTS::Image::Container::Buffer<.*>$')] = lambda val: ImageBufferPrinter("BTS::Image::Container::Buffer", val) + pretty_printers_dict[re.compile('^BTS::Image::Reference::Buffer<.*>$')] = lambda val: ImageReferencePrinter("BTS::Image::Reference::Buffer", val) + pretty_printers_dict[re.compile('^BTS::Image::Expected::Buffer$')] = lambda val: ImagePrinter(val) + pretty_printers_dict[re.compile('^BTS::Image::Expected::Buffer_tpl<.*>$')] = lambda val: ImageBufferPrinter('BTS::Image::Expected::Buffer_tpl', val) + pretty_printers_dict[re.compile('^BTS::Image::Observed::Buffer_tpl<.*>$')] = lambda val: ImageBufferPrinter('BTS::Image::Observed::Buffer_tpl', val) + pretty_printers_dict[re.compile('^BTS::Image::Voxel$')] = lambda val: ImageVoxelPrinter("BTS::Image::Voxel", 'double', val) + pretty_printers_dict[re.compile('^BTS::Image::Expected::Quartic::Voxel$')] = lambda val: ImageVoxelPrinter("BTS::Image::Expected::Quartic::Voxel", 'double', val) + pretty_printers_dict[re.compile('^BTS::Image::Expected::Gaussian::Voxel$')] = lambda val: ImageVoxelPrinter("BTS::Image::Expected::Gaussian::Voxel", 'double', val) + pretty_printers_dict[re.compile('^BTS::Image::Expected::Trilinear::Voxel$')] = lambda val: ImageVoxelPrinter("BTS::Image::Expected::Trilinear::Voxel", 'double', val) + pretty_printers_dict[re.compile('^BTS::Image::Expected::TopHat::Voxel$')] = lambda val: ImageVoxelPrinter("BTS::Image::Expected::TopHat::Voxel",'double', val) + pretty_printers_dict[re.compile('^BTS::Image::Observed::Voxel$')] = lambda val: ImageVoxelPrinter("BTS::Image::Observed::Voxel", 'double', val) + pretty_printers_dict[re.compile('^BTS::Image::Container::Voxel$')] = lambda val: ImageVoxelPrinter("BTS::Image::Container::Voxel", 'BTS::Fibre::Strand', val) + pretty_printers_dict[re.compile('^BTS::Image::Container::Voxel$')] = lambda val: ImageVoxelPrinter("BTS::Image::Container::Voxel", 'BTS::Fibre::Tractlet', val) + pretty_printers_dict[re.compile('^BTS::Image::Container::Voxel$')] = lambda val: ImageVoxelPrinter("BTS::Image::Container::Voxel", 'BTS::Fibre::Strand::Tensor', val) + pretty_printers_dict[re.compile('^BTS::Image::Container::Voxel$')] = lambda val: ImageVoxelPrinter("BTS::Image::Container::Voxel", 'BTS::Fibre::Tractlet::Tensor', val) + pretty_printers_dict[re.compile('^BTS::Image::Container::Voxel< MR::Math::Vector >$')] = lambda val: ImageVoxelPrinter("BTS::Image::Container::Voxel>", ' MR::Math::Vector ', val) + pretty_printers_dict[re.compile('^BTS::Image::Container::Voxel< MR::Math::Matrix >$')] = lambda val: ImageVoxelPrinter("BTS::Image::Container::Voxel>", ' MR::Math::Matrix ', val) + pretty_printers_dict[re.compile('^BTS::Image::Density::Voxel$')] = lambda val: ImageDensityVoxelPrinter(val) + +pretty_printers_dict = {} + +build_bts_image_dictionary () \ No newline at end of file diff --git a/gdb_printers/python/bts/image/printers.pyc b/gdb_printers/python/bts/image/printers.pyc new file mode 100644 index 0000000..b43eb32 Binary files /dev/null and b/gdb_printers/python/bts/image/printers.pyc differ diff --git a/gdb_printers/python/bts/mcmc/__init__.py b/gdb_printers/python/bts/mcmc/__init__.py new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/gdb_printers/python/bts/mcmc/__init__.py @@ -0,0 +1 @@ + diff --git a/gdb_printers/python/bts/mcmc/printers.py b/gdb_printers/python/bts/mcmc/printers.py new file mode 100644 index 0000000..a9c2b0e --- /dev/null +++ b/gdb_printers/python/bts/mcmc/printers.py @@ -0,0 +1,110 @@ +# Pretty-printers for 'BTS::MCMC::*'. + +# Copyright (C) 2008, 2009 Free Software Foundation, Inc. + +# 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 . + +import gdb +import itertools +import re + +class ProposalMomentumPrinter: + "Print MCMC::Proposal::Momentum" + + class _iterator: + def __init__ (self, size, stride, data_ptr): + self.size = size + self.stride = stride + self.data_ptr = data_ptr + self.count = 0 + + def __iter__(self): + return self + + def next(self): + if self.count == self.size: + raise StopIteration + count = self.count + elt = self.data_ptr.dereference() + self.data_ptr = self.data_ptr + self.stride + self.count = self.count + 1 + return ('[%d]' % count, elt) + + def __init__(self, typename, val): + self.typename = typename + + if typename == 'MCMC::Proposal::Momentum': + self.val = val + else: + self.val = val.cast(gdb.lookup_type('BTS::MCMC::Proposal::Momentum')) + + def children(self): + return self._iterator(self.val['momen']['size'], + self.val['momen']['stride'], + self.val['momen']['data']) + + def to_string(self): + return ("%s: size %d" % (self.typename, self.val['momen']['size'])) + + + def display_hint(self): + return 'array' + + +def register_bts_mcmc_printers (obj): + "Register Bayesian Tract Sampling (BTS) MCMC pretty-printers with objfile Obj." + + if obj == None: + obj = gdb + + obj.pretty_printers.append (lookup_function) + +def lookup_function (val): + "Look-up and return a pretty-printer that can print val." + + # Get the type. + type = val.type + + # If it points to a reference, get the reference. + if type.code == gdb.TYPE_CODE_REF: + type = type.target () + + # Get the unqualified type, stripped of typedefs. + type = type.unqualified ().strip_typedefs () + + # Get the type name. + typename = type.tag + if typename == None: + return None + + # Iterate over local dictionary of types to determine + # if a printer is registered for that type. Return an + # instantiation of the printer if found. + for function in pretty_printers_dict: + if function.search (typename): + return pretty_printers_dict[function] (val) + + # Cannot find a pretty printer. Return None. + return None + +def build_bts_mcmc_dictionary (): + # bts objects requiring pretty-printing. + # In order from: + pretty_printers_dict[re.compile('^BTS::MCMC::Proposal::Momentum$')] = lambda val: ProposalMomentumPrinter("MCMC::Proposal::Momentum", val) + pretty_printers_dict[re.compile('^BTS::MCMC::Proposal::Momentum::Weighted$')] = lambda val: ProposalMomentumPrinter("MCMC::Proposal::Momentum::Weighted", val) + pretty_printers_dict[re.compile('^BTS::MCMC::Proposal::Momentum::Weighted::NonSeparable$')] = lambda val: ProposalMomentumPrinter("MCMC::Proposal::Momentum::Weighted::NonSeparable", val) + +pretty_printers_dict = {} + +build_bts_mcmc_dictionary () diff --git a/gdb_printers/python/mr/__init__.py b/gdb_printers/python/mr/__init__.py new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/gdb_printers/python/mr/__init__.py @@ -0,0 +1 @@ + diff --git a/gdb_printers/python/mr/math/__init__.py b/gdb_printers/python/mr/math/__init__.py new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/gdb_printers/python/mr/math/__init__.py @@ -0,0 +1 @@ + diff --git a/gdb_printers/python/mr/math/printers.py b/gdb_printers/python/mr/math/printers.py new file mode 100644 index 0000000..dac7c57 --- /dev/null +++ b/gdb_printers/python/mr/math/printers.py @@ -0,0 +1,170 @@ +# Pretty-printers for 'BTS::Fibre::*'. + +# Copyright (C) 2008, 2009 Free Software Foundation, Inc. + +# 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 . + +import gdb +import itertools +import re + + +class MathVectorPrinter: + "Print Math::Vector" + + class _iterator: + def __init__ (self, size, stride, data_ptr): + self.size = size + self.stride = stride + self.data_ptr = data_ptr + self.count = 0 + + def __iter__(self): + return self + + def next(self): + if self.count == self.size: + raise StopIteration + count = self.count + elt = self.data_ptr.dereference() + self.data_ptr = self.data_ptr + self.stride + self.count = self.count + 1 + return ('[%d]' % count, elt) + + def __init__(self, typename, val): + self.typename = typename + self.val = val + + def children(self): + return self._iterator(self.val['size'], + self.val['stride'], + self.val['data']) + + def to_string(self): + return ("%s: size %d" % (self.typename, self.val['size'])) + + + def display_hint(self): + return 'array' + +class RowPrinter: + + def __init__(self): + print 'done' + + +class MathMatrixPrinter: + "Print Math::Matrix" + + class _iterator: + def __init__ (self, num_rows, num_cols, row_size, data_ptr): + self.num_rows = num_rows + self.num_cols = num_cols + self.row_size = row_size + self.data_ptr = data_ptr + self.row_count = 0 + self.col_count = 0 + + def __iter__(self): + return self + + def next(self): + if self.row_count == self.num_rows: + raise StopIteration + + row_count = self.row_count + col_count = self.col_count + + if col_count == 0: + print '\n' + + elt = self.data_ptr.dereference() + + self.col_count += 1 + if self.col_count == self.num_cols: + self.row_count += 1 + self.col_count = 0 + self.data_ptr = self.data_ptr + (self.row_size - self.num_cols + 1) + else: + self.data_ptr = self.data_ptr + 1 + + return ('(%d,%d)' % (row_count, col_count), elt) + + def __init__(self, typename, val): + self.typename = typename + self.val = val + + def children(self): + return self._iterator(self.val['size1'], + self.val['size2'], + self.val['tda'], + self.val['data']) + + def to_string(self): + return ("%s: rows %d, cols %d" % (self.typename, self.val['size1'], self.val['size2'])) + + + def display_hint(self): + return 'array' + + +def register_mr_math_printers (obj): + "Register MRtrix (MR) Math pretty-printers with objfile Obj." + + if obj == None: + obj = gdb + + obj.pretty_printers.append (lookup_function) + +def lookup_function (val): + "Look-up and return a pretty-printer that can print val." + + # Get the type. + type = val.type + + # If it points to a reference, get the reference. + if type.code == gdb.TYPE_CODE_REF: + type = type.target () + + # Get the unqualified type, stripped of typedefs. + type = type.unqualified ().strip_typedefs () + + # Get the type name. + typename = type.tag + if typename == None: + return None + + # Iterate over local dictionary of types to determine + # if a printer is registered for that type. Return an + # instantiation of the printer if found. + for function in pretty_printers_dict: + if function.search (typename): + return pretty_printers_dict[function] (val) + + # Cannot find a pretty printer. Return None. + return None + +def build_mr_math_dictionary (): + # bts objects requiring pretty-printing. + # In order from: + pretty_printers_dict[re.compile('^MR::Math::Vector<.*>$')] = lambda val: MathVectorPrinter('MR::Math::Vector', val) + pretty_printers_dict[re.compile('^MR::Math::Matrix<.*>$')] = lambda val: MathMatrixPrinter('MR::Math::Matrix', val) + pretty_printers_dict[re.compile('^BTS::Fibre::Strand::Set::Tensor$')] = lambda val: MathMatrixPrinter('BTS::Fibre::Strand::Set::Tensor', val) + pretty_printers_dict[re.compile('^BTS::Fibre::Tract::Set::Tensor$')] = lambda val: MathMatrixPrinter('BTS::Fibre::Tract::Set::Tensor', val) + pretty_printers_dict[re.compile('^BTS::MCMC::State$')] = lambda val: MathVectorPrinter('BTS::MCMC::State', val) + pretty_printers_dict[re.compile('^BTS::MCMC::State::Tensor$')] = lambda val: MathMatrixPrinter('BTS::MCMC::State::Tensor', val) + +pretty_printers_dict = {} + +build_mr_math_dictionary () diff --git a/hessian_todo.txt b/hessian_todo.txt new file mode 100644 index 0000000..1a3e6b6 --- /dev/null +++ b/hessian_todo.txt @@ -0,0 +1,7 @@ +Implement tensor classes +Extend reader and writer classes. +Extend gradient tester to hessian tester +Extend unzip to flatten and zip to unflatten +implement hessian calculations. + + diff --git a/link/metropolis b/link/metropolis new file mode 120000 index 0000000..25f9586 --- /dev/null +++ b/link/metropolis @@ -0,0 +1 @@ +../bin/metropolis__nograd \ No newline at end of file diff --git a/matlab/CSD/SH2RH.m b/matlab/CSD/SH2RH.m new file mode 100644 index 0000000..f2d1294 --- /dev/null +++ b/matlab/CSD/SH2RH.m @@ -0,0 +1,16 @@ +function RH = SH2RH (SH) + +% function RH = SH2RH (SH) +% +% Calculate the rotational harmonic decomposition up to +% harmonic order 'lmax'for an axially and antipodally +% symmetric surface 'SH' (in SH coefficients). Note that +% all m~=0 coefficients will be ignored as axial symmetry +% is assumed. + +lmax = lmax_for_SH (SH); +D_SH = gen_delta (0, 0, lmax); +k = find (D_SH); +RH = SH(k)./D_SH(k); + + diff --git a/matlab/CSD/SH2amp.m b/matlab/CSD/SH2amp.m new file mode 100644 index 0000000..74b7283 --- /dev/null +++ b/matlab/CSD/SH2amp.m @@ -0,0 +1,8 @@ +function S = SH2amp (SH, scheme) + +% function S = SH2amp (SH, scheme) +% +% Maps SH coefficients 'SH' to amplitudes along directions +% in 'scheme' + +S = scheme.sh(:, 1:size(SH,1))*SH; diff --git a/matlab/CSD/amp2SH.m b/matlab/CSD/amp2SH.m new file mode 100644 index 0000000..12809a5 --- /dev/null +++ b/matlab/CSD/amp2SH.m @@ -0,0 +1,13 @@ +function SH = amp2SH (S, scheme); + +% function SH = amp2SH (S, scheme); +% +% Maps signals 'S' measured along directions in 'scheme' +% the corresponding even SH coefficients + +if ~isfield (scheme, 'shinv') + scheme.shinv = pinv(scheme.sh); +end + +SH = scheme.shinv * S; + diff --git a/matlab/CSD/c2s.m b/matlab/CSD/c2s.m new file mode 100644 index 0000000..f39f615 --- /dev/null +++ b/matlab/CSD/c2s.m @@ -0,0 +1,8 @@ +function S = c2s(X) + +% Convert cartesian coordinates to the equivalent spherical coordinates. +% Assumes X = [ X Y Z ], and returns S = [ el az r ]. + +S(:,3) = sqrt(sum(X.^2, 2)); +S(:,1) = acos(X(:,3)./S(:,3)); +S(:,2) = atan2(X(:,2), X(:,1)); diff --git a/matlab/CSD/csdeconv.m b/matlab/CSD/csdeconv.m new file mode 100644 index 0000000..40b64d6 --- /dev/null +++ b/matlab/CSD/csdeconv.m @@ -0,0 +1,69 @@ +function [ F_SH, num_it ] = csdeconv(R_RH, S_SH, scheme, lambda, tau) + +% function F_SH = SR_csdeconv(R_RH, S_SH, lambda, tau, scheme) +% +% Constrained spherical deconvolution: +% +% deconvolves the axially symmetric response function 'R_RH' +% (in RH coefficients) from the surface 'S_SH' (in SH +% coefficients) to give the surface 'F_SH' (in SH coefficients), +% by constraining the corresponding amplitudes of 'F_SH' +% calculated along the directions given by 'scheme') to be +% non-negative. The optional parameters 'lambda' and 'tau' +% correspond to the regularisation weight (1 by default) and the +% threshold on the FOD amplitude used to identify negative lobes +% (0.1 by default). + + + +if ~exist('lambda'), lambda = 1; end +if ~exist('tau'), tau = 0.1; end + + +% guess appropriate value of lmax (assuming no super-resolution): +lmax = lmax_for_SH (S_SH); +if scheme.lmax < lmax + lmax = scheme.lmax; + S_SH(nSH_for_lmax(lmax)+1:end,:) = []; +end + + +% build forward spherical convolution matrix up to lmax: +fconv = []; +for l = 0:2:lmax + fconv = [ fconv; R_RH(l/2+1)*ones(2*l+1,1) ]; +end +fconv = [ diag(fconv) zeros(size(fconv,1),size(scheme.sh,2)-size(fconv,1)) ]; + + +% generate initial FOD estimate, truncated at lmax = 4: +F_SH = fconv\S_SH; +F_SH (nSH_for_lmax(4)+1:end,1) = 0; + + +% set threshold on FOD amplitude used to identify 'negative' values: +threshold = tau*mean (scheme.sh*F_SH); + + +% scale lambda to account for differences in the number of +% SH coefficients and number of mapped directions; +lambda = lambda * size(fconv,1)*R_RH(1)/size(scheme.sh,1); + + +% main iteration loop: +k = []; +for num_it = 1:50 + A = scheme.sh*F_SH; + k2 = find (A < threshold); + if size(k2,1) + size (fconv,1) < size(scheme.sh,2) + disp ('too few negative directions identified - failed to converge'); + return; + end + if size(k) == size(k2), if k == k2, return; end; end + k = k2; + M = [ fconv; lambda*scheme.sh(k,:) ]; + S = [ S_SH; zeros(size(k,1),1) ]; + F_SH = M\S; +end + +disp ('maximum number of iterations exceeded - failed to converge'); diff --git a/matlab/CSD/dir300.txt b/matlab/CSD/dir300.txt new file mode 100644 index 0000000..a7d7421 --- /dev/null +++ b/matlab/CSD/dir300.txt @@ -0,0 +1,300 @@ + 0.0000000e+00 0.0000000e+00 1.0000000e+00 + -9.9987560e-01 -2.6532597e-06 -1.5773019e-02 + -6.8010937e-01 6.6563465e-01 3.0721615e-01 + -5.2889610e-01 2.9051096e-02 8.4818922e-01 + -6.6922575e-02 -6.4608458e-01 7.6032630e-01 + 9.8690777e-01 1.1303241e-01 1.1505099e-01 + -8.9625014e-01 3.3586072e-01 2.8971239e-01 + -9.9015526e-01 1.0606501e-01 9.1338844e-02 + -2.3383570e-01 1.8841521e-01 9.5384515e-01 + -6.5073275e-02 8.8710289e-01 4.5696164e-01 + 2.1098611e-01 -9.2461705e-01 3.1712486e-01 + -2.2451976e-01 9.7285312e-01 -5.6104198e-02 + 6.3308282e-01 -7.7230629e-01 5.2432273e-02 + -7.1113101e-02 9.7532153e-01 2.0902353e-01 + -7.7254497e-01 -3.5898443e-01 5.2374083e-01 + 4.1556590e-01 1.4201578e-01 8.9840776e-01 + 5.5003720e-01 -7.2319126e-01 4.1767628e-01 + 1.2457513e-01 -5.1299763e-01 8.4930234e-01 + 5.9189328e-01 7.3464224e-01 3.3160689e-01 + 2.1062288e-01 -2.1154906e-01 9.5440295e-01 + -4.5110365e-01 -7.8460181e-01 4.2532986e-01 + 7.7303521e-01 -3.8080569e-01 5.0734957e-01 + 9.2129162e-01 3.5854283e-01 1.5056160e-01 + -5.6108959e-01 7.5537652e-01 3.3850376e-01 + -4.6962489e-01 3.2253892e-01 8.2184007e-01 + 3.4697589e-01 -1.5204366e-01 9.2546769e-01 + 7.4613669e-01 6.6106615e-01 7.9193314e-02 + -8.9558399e-01 4.2077334e-01 -1.4449606e-01 + 5.9009479e-01 -6.1861083e-01 5.1875696e-01 + -2.4260958e-02 -9.0289669e-01 4.2917242e-01 + -3.5469146e-01 2.5983108e-01 8.9815465e-01 + 7.0112317e-01 6.2993034e-01 3.3408692e-01 + 6.4920411e-01 4.9868689e-01 5.7432170e-01 + -4.6875123e-01 -5.9128660e-01 6.5624115e-01 + -4.9906670e-01 8.4096928e-01 2.0905287e-01 + 6.3347818e-01 -7.1670442e-01 2.9161647e-01 + -9.6347278e-01 7.5538878e-02 2.5693204e-01 + 8.7480531e-02 6.8258209e-01 7.2555416e-01 + 1.8927853e-02 7.7696898e-01 6.2925427e-01 + 8.3754009e-01 -4.7362951e-01 2.7239985e-01 + 3.7844995e-03 9.9687975e-01 7.8844409e-02 + -6.4163194e-02 5.2045615e-01 8.5147430e-01 + 9.1397131e-01 1.9404277e-01 3.5637598e-01 + 7.5910686e-01 4.0238830e-01 5.1170346e-01 + -8.2045943e-01 4.5099565e-01 3.5135345e-01 + 6.8453960e-01 -5.0179064e-01 5.2878322e-01 + -7.8367408e-02 3.8647218e-01 9.1896562e-01 + -8.5350255e-01 -3.3736445e-01 3.9713805e-01 + 3.1088091e-01 8.9565992e-01 3.1803517e-01 + -9.3920299e-02 2.4392349e-01 9.6523588e-01 + -9.5779598e-01 2.1226440e-01 1.9383160e-01 + 4.3507720e-01 -8.8054517e-01 1.8801069e-01 + -4.3140148e-01 8.3365815e-01 3.4482874e-01 + -4.5929096e-01 -1.0370157e-01 8.8221188e-01 + 3.7014383e-01 -9.2721456e-01 5.7155163e-02 + 3.4095580e-01 6.3826340e-01 6.9019488e-01 + 9.5284581e-01 -2.8430713e-01 1.0608632e-01 + -9.4758086e-01 -6.3471393e-02 3.1314836e-01 + 7.2034271e-01 5.3155755e-01 4.4559280e-01 + 4.9977745e-01 -5.8898098e-01 6.3507787e-01 + 4.9469530e-01 8.6539488e-01 7.9801384e-02 + -7.7732006e-01 -4.6857582e-01 4.1977402e-01 + 7.8935132e-02 -7.4395652e-01 6.6354951e-01 + -2.1699526e-01 -7.6169167e-01 6.1052343e-01 + -6.4979398e-01 5.4160992e-01 5.3331648e-01 + 6.9663676e-02 -2.6707259e-01 9.6115514e-01 + 4.0231781e-01 -4.0199595e-01 8.2252030e-01 + -7.6664868e-01 6.4126049e-01 -3.2168123e-02 + -6.8327748e-01 1.3658237e-01 7.1727062e-01 + 2.1740663e-01 7.1787700e-01 6.6135238e-01 + -8.4357378e-01 3.2251507e-01 4.2938015e-01 + -7.6411358e-01 -5.6766123e-01 3.0641666e-01 + 1.5103686e-01 8.1203597e-01 5.6372462e-01 + 4.7718503e-02 2.9726674e-01 9.5360129e-01 + -8.1864737e-02 -9.9533545e-01 5.1044135e-02 + -7.1813042e-02 -7.5298409e-01 6.5410844e-01 + -2.0792770e-01 4.7153058e-01 8.5698599e-01 + -9.6278993e-01 -1.7253664e-01 2.0800639e-01 + 9.2157824e-01 -3.8819196e-01 7.4632673e-04 + 1.5962730e-01 -3.7846507e-01 9.1174740e-01 + -6.1252019e-01 6.5551610e-01 4.4172124e-01 + -2.5017014e-01 -3.2402069e-01 9.1237355e-01 + 1.5778142e-01 9.8429738e-01 7.9143471e-02 + -5.8579709e-01 -5.9553681e-01 5.4970690e-01 + 7.3218361e-01 -9.2384509e-03 6.8104464e-01 + 2.2566664e-01 -7.0846911e-01 6.6868983e-01 + 9.8564873e-01 -3.0269518e-02 1.6607330e-01 + -1.5797351e-01 7.1264829e-01 6.8350332e-01 + 4.2340502e-01 6.9792150e-01 5.7761039e-01 + -9.2188449e-01 -3.8745685e-01 -2.4836707e-03 + -3.4446997e-01 -7.7330789e-01 5.3229254e-01 + 9.1546684e-01 -3.1531313e-01 2.4999620e-01 + 9.4521362e-03 -3.9914848e-01 9.1683758e-01 + -5.5992158e-01 5.0794439e-01 6.5458408e-01 + 5.4101987e-01 1.7847143e-01 8.2185488e-01 + -5.7321139e-01 -6.9469748e-01 4.3453897e-01 + 7.7312490e-01 1.2334775e-01 6.2214405e-01 + 8.2160657e-01 -5.5231544e-01 1.4110384e-01 + -5.1009778e-02 6.4276720e-01 7.6436139e-01 + 6.0548499e-03 9.4218155e-01 3.3504814e-01 + 8.4613085e-01 3.0244822e-01 4.3884809e-01 + 4.1175173e-01 -7.9841749e-01 4.3930630e-01 + 3.8082029e-02 -8.3462061e-01 5.4950723e-01 + 2.9391993e-01 -9.3691772e-01 1.8919898e-01 + -7.0979827e-01 -1.1998845e-01 6.9411036e-01 + -4.5817610e-01 4.6128803e-01 7.5979472e-01 + -5.3066753e-01 6.2927212e-01 5.6781033e-01 + -8.2693917e-01 -5.3518132e-01 1.7248933e-01 + -3.4836048e-01 -9.3523428e-01 -6.3101721e-02 + -3.9654811e-01 4.8214914e-02 9.1674692e-01 + -4.8786435e-01 7.3654101e-01 4.6850369e-01 + 1.8798456e-01 3.4657361e-01 9.1899322e-01 + -2.9995445e-01 6.5903156e-01 6.8971352e-01 + -5.5190779e-01 -3.6967899e-01 7.4748594e-01 + -9.8759054e-01 -3.2713701e-02 1.5360577e-01 + 4.0320849e-01 8.9348108e-01 1.9777379e-01 + -2.2179533e-01 3.3373972e-01 9.1620120e-01 + 2.4137899e-02 1.5173608e-01 9.8812627e-01 + 5.7655616e-01 3.0951213e-01 7.5616482e-01 + -4.7212106e-01 1.6959413e-01 8.6506620e-01 + 6.8610717e-01 2.2543313e-01 6.9169130e-01 + -4.3618790e-01 -8.9817146e-01 5.5028517e-02 + -6.9702199e-01 -7.1504732e-01 5.3550699e-02 + -5.6889403e-01 8.1889973e-01 7.5913225e-02 + 6.4830669e-01 9.4920496e-02 7.5543930e-01 + -1.1663744e-01 9.6128428e-02 9.8851152e-01 + -5.4652008e-01 -7.7854067e-01 3.0852912e-01 + -3.2077146e-01 -9.2823883e-02 9.4259715e-01 + 8.4234898e-01 1.8644395e-02 5.3860986e-01 + -3.6873303e-01 -2.2947140e-01 9.0076569e-01 + -2.0412410e-01 -1.8845748e-01 9.6063371e-01 + -3.1829498e-01 -8.5509328e-01 4.0927227e-01 + 4.7029482e-01 8.2450781e-01 3.1465800e-01 + -4.3489629e-01 5.8973842e-01 6.8049527e-01 + 4.9084641e-01 -8.1335632e-01 3.1228400e-01 + -9.1573628e-01 -3.0837445e-01 2.5755050e-01 + -4.0013062e-01 7.0423229e-01 5.8647452e-01 + -8.1266652e-01 -5.8194170e-01 3.0281697e-02 + 7.0348340e-01 -6.9253675e-01 1.5969959e-01 + 5.6894509e-01 4.4539885e-01 6.9131856e-01 + -5.8201514e-01 2.3004000e-01 7.7996152e-01 + 4.6506226e-01 -7.0080224e-01 5.4091896e-01 + 6.2351680e-01 -5.0969352e-02 7.8014673e-01 + 6.2156980e-01 -4.3790363e-01 6.4953167e-01 + 4.5876725e-01 5.4643934e-01 7.0066872e-01 + -9.2558730e-01 3.5016235e-01 1.4378621e-01 + -2.4522706e-01 -9.6852955e-01 4.2593437e-02 + -2.5460069e-01 -9.2304929e-01 2.8837215e-01 + -9.8771476e-01 1.4244848e-01 -6.4249387e-02 + -8.8756343e-01 -8.2148963e-02 4.5330200e-01 + -5.0394286e-03 -9.8354916e-01 1.8057037e-01 + -8.9734056e-02 -9.4963285e-01 3.0024198e-01 + -3.5441191e-01 8.0669190e-01 4.7290631e-01 + 4.9750362e-01 -4.7176148e-01 7.2796378e-01 + 5.8347153e-01 -1.9525999e-01 7.8831117e-01 + 9.1412655e-01 -2.0347793e-01 3.5066990e-01 + 3.6642672e-01 -5.3790945e-01 7.5920016e-01 + 7.6942436e-01 -4.9406851e-01 4.0482398e-01 + -3.3235345e-01 -9.2956315e-01 1.5954164e-01 + -8.6019855e-01 4.8438633e-01 1.5946266e-01 + 5.0728527e-01 -8.5993872e-01 5.6276579e-02 + 5.0092258e-01 7.3737586e-01 4.5315938e-01 + 2.8077128e-01 1.0132112e-01 9.5441161e-01 + -3.9812605e-01 -8.7241002e-01 2.8354261e-01 + -3.2958602e-01 5.3650394e-01 7.7687617e-01 + -6.4059814e-01 -2.4980861e-01 7.2610584e-01 + -7.7129786e-01 3.0377497e-01 5.5930348e-01 + 2.9923150e-01 -3.2106234e-01 8.9854298e-01 + 5.4075794e-01 6.0319966e-01 5.8628578e-01 + -7.5004334e-01 -2.4166011e-01 6.1565849e-01 + -9.5630717e-01 -2.7598725e-01 9.6476036e-02 + -8.3975950e-01 -2.2283910e-01 4.9512294e-01 + -5.0303232e-01 -8.4533867e-01 1.7989167e-01 + -8.4956167e-01 -4.4171094e-01 2.8833385e-01 + -2.9217294e-01 8.9354391e-01 3.4090212e-01 + -5.0022643e-01 -2.5221460e-01 8.2834855e-01 + 2.1303264e-01 6.0692881e-01 7.6567259e-01 + 5.3017459e-01 -3.3505017e-01 7.7888143e-01 + 8.5411829e-01 4.6470453e-01 2.3352012e-01 + -8.4438370e-01 3.9159019e-02 5.3430584e-01 + 2.4851188e-01 -4.6668796e-02 9.6750394e-01 + -8.5254200e-01 5.2260722e-01 7.3362610e-03 + -6.2642474e-01 -7.5821528e-01 1.8083593e-01 + -2.5497214e-01 4.0345205e-02 9.6610635e-01 + -9.1450143e-01 5.7242495e-02 4.0051271e-01 + 6.1595611e-01 6.3986075e-01 4.5953922e-01 + -7.8251434e-01 5.6551560e-01 2.6050606e-01 + -9.6650091e-01 -2.5088228e-01 -5.4167150e-02 + 2.6656208e-01 -4.6304810e-01 8.4529942e-01 + 7.9936401e-01 -1.1653188e-01 5.8943830e-01 + 6.7764304e-01 7.0577999e-01 2.0657810e-01 + -4.7091713e-01 -6.9333452e-01 5.4545788e-01 + -1.7372231e-01 -8.9450003e-01 4.1193476e-01 + -6.2299641e-01 7.5580340e-01 2.0158544e-01 + -1.4908344e-01 9.8573262e-01 7.8136599e-02 + -4.3844964e-01 8.9557017e-01 7.5604116e-02 + 9.6199159e-01 -1.7440823e-01 2.1012844e-01 + -5.7819330e-01 -4.8670180e-01 6.5483881e-01 + -7.2554791e-01 5.5798332e-01 4.0278388e-01 + -1.1806859e-01 8.0971990e-01 5.7481605e-01 + 7.7687737e-01 2.6505428e-01 5.7114603e-01 + -2.2061733e-01 9.5302915e-01 2.0751730e-01 + -6.8277196e-01 -5.8870784e-01 4.3271876e-01 + 4.3746062e-01 2.8550001e-01 8.5271211e-01 + 8.2764081e-02 -6.3460483e-01 7.6839236e-01 + 8.1642844e-01 4.3769062e-01 3.7665836e-01 + -8.6027563e-01 1.7924856e-01 4.7727958e-01 + 2.2778643e-01 -5.9481304e-01 7.7091555e-01 + -6.6203048e-01 -6.8072893e-01 3.1356620e-01 + 2.9852101e-01 7.7882080e-01 5.5165512e-01 + 6.9950809e-01 -1.5553657e-01 6.9749323e-01 + 8.5129413e-02 8.8816882e-01 4.5156299e-01 + 1.4012595e-01 5.5467127e-02 9.8857884e-01 + 3.8789194e-01 -5.5861853e-03 9.2168793e-01 + -3.4450701e-01 -6.7781663e-01 6.4952255e-01 + -9.6785233e-01 2.4807440e-01 4.1484419e-02 + 8.4358126e-01 -2.4874428e-01 4.7591695e-01 + 8.8295758e-01 -1.0226035e-01 4.5817980e-01 + 5.6771878e-01 -8.0239785e-01 1.8399207e-01 + 8.6211742e-01 4.9927628e-01 8.6468212e-02 + 3.3565856e-01 5.1911431e-01 7.8603668e-01 + 3.7666781e-01 8.1994945e-01 4.3105020e-01 + 1.2565505e-01 -8.8994913e-01 4.3840775e-01 + -1.9321556e-01 5.9855530e-01 7.7743122e-01 + -5.7606130e-01 3.7477380e-01 7.2642823e-01 + -2.1184502e-01 -6.6010331e-01 7.2068391e-01 + -6.8742055e-01 -4.8358141e-01 5.4185054e-01 + -6.7321088e-01 -3.6980966e-01 6.4033423e-01 + -9.8942343e-01 -1.3804185e-01 4.4561566e-02 + 6.4252036e-02 4.3647698e-01 8.9741825e-01 + 8.5497051e-01 1.6167212e-01 4.9283623e-01 + -9.2006623e-01 1.9549221e-01 3.3950099e-01 + 5.1922924e-01 3.2249631e-02 8.5402632e-01 + -3.4338074e-01 4.0303748e-01 8.4832214e-01 + -3.1808519e-02 -1.5840157e-01 9.8686228e-01 + 3.2813101e-01 -7.6045724e-01 5.6038811e-01 + 9.4840757e-01 -6.1606786e-02 3.1101074e-01 + 3.6635607e-01 -6.5416429e-01 6.6170410e-01 + 9.5144071e-01 2.2362676e-01 2.1154584e-01 + 1.6692391e-01 2.0301334e-01 9.6484299e-01 + -5.8423790e-01 -1.3111487e-01 8.0092132e-01 + -6.7244964e-01 4.1564161e-01 6.1241615e-01 + 6.8163324e-01 3.6406555e-01 6.3469080e-01 + -9.0997675e-01 -2.0090322e-01 3.6273986e-01 + -1.7052709e-01 -5.5182734e-01 8.1633761e-01 + 3.2396891e-01 3.8807249e-01 8.6281162e-01 + -2.5084638e-02 -5.2944547e-01 8.4797303e-01 + -3.2717030e-01 -5.6886097e-01 7.5455735e-01 + 2.7188025e-01 -8.5417465e-01 4.4324576e-01 + 2.0284939e-01 4.8232839e-01 8.5218041e-01 + 9.1209127e-01 4.9932887e-02 4.0693515e-01 + 2.3348163e-01 8.6452524e-01 4.4506454e-01 + -4.4839453e-01 -4.7898550e-01 7.5466234e-01 + 1.8542359e-01 -8.0760188e-01 5.5981898e-01 + 6.1607721e-02 -9.4799215e-01 3.1227450e-01 + -7.8073085e-01 1.5944306e-01 6.0418312e-01 + 4.3293218e-01 -2.5840667e-01 8.6359465e-01 + -7.3462853e-01 -6.5280632e-01 1.8483732e-01 + 8.0908917e-02 9.7473364e-01 2.0820201e-01 + 7.7452513e-02 5.6591947e-01 8.2081439e-01 + -5.6837327e-01 -8.2144162e-01 4.6749282e-02 + 3.5504054e-01 -8.7910064e-01 3.1800672e-01 + -2.1296200e-01 8.5872417e-01 4.6609010e-01 + 1.4600890e-01 -9.7149605e-01 1.8675337e-01 + 3.0560075e-01 2.4762680e-01 9.1939608e-01 + -6.8103193e-01 2.8019046e-01 6.7652703e-01 + 8.9425906e-01 3.3355344e-01 2.9840046e-01 + -1.6852105e-01 -9.7041672e-01 1.7289317e-01 + 7.7804975e-01 5.9223223e-01 2.0952224e-01 + 8.5080189e-01 -3.6506473e-01 3.7797340e-01 + 9.6077719e-01 8.2204647e-02 2.6485768e-01 + 1.6300072e-01 9.3066173e-01 3.2756603e-01 + -1.3859895e-01 -4.2593405e-01 8.9407523e-01 + 4.5256145e-01 4.2082592e-01 7.8618934e-01 + 1.0969636e-01 -1.0382971e-01 9.8852724e-01 + -7.8596367e-01 6.0750385e-01 1.1489205e-01 + -1.4054462e-01 -5.4315342e-02 9.8858336e-01 + -2.8181020e-01 -4.5531714e-01 8.4455273e-01 + -2.6225973e-01 7.6625692e-01 5.8657495e-01 + -9.0142964e-01 -4.0776841e-01 1.4542876e-01 + -7.5605259e-01 4.3641027e-01 4.8778126e-01 + 6.7922834e-01 -6.1695319e-01 3.9751430e-01 + -1.1125695e-01 -8.3722522e-01 5.3542116e-01 + -9.3634650e-02 -2.9264787e-01 9.5162481e-01 + -6.9225216e-01 7.1782601e-01 7.4247939e-02 + -7.5516647e-01 1.8930439e-02 6.5525968e-01 + -6.4786322e-01 -1.4011059e-03 7.6175540e-01 + 4.8275911e-01 -1.1429693e-01 8.6826255e-01 + 6.5101165e-01 -2.9823361e-01 6.9802618e-01 + 7.5724424e-01 -2.6110475e-01 5.9866975e-01 + 5.6237478e-01 8.0261605e-01 1.9885194e-01 + 2.5866335e-01 9.4789350e-01 1.8598703e-01 + -4.0106683e-01 -3.6428226e-01 8.4050213e-01 + -2.9750629e-01 9.5168984e-01 7.6002965e-02 + -8.0786687e-01 -1.0198259e-01 5.8047453e-01 + -7.3734632e-02 9.9589560e-01 -5.2489540e-02 + 7.5399735e-01 -5.9978026e-01 2.6786496e-01 + -1.4519667e-01 9.3043639e-01 3.3646107e-01 + 6.3791183e-01 7.6649572e-01 7.4517191e-02 + -3.6421278e-01 9.0785255e-01 2.0773251e-01 diff --git a/matlab/CSD/dir60.txt b/matlab/CSD/dir60.txt new file mode 100644 index 0000000..36f6fee --- /dev/null +++ b/matlab/CSD/dir60.txt @@ -0,0 +1,60 @@ + 0.0000000e+00 0.0000000e+00 1.0000000e+00 + -9.7004112e-01 -2.5740912e-06 2.4294080e-01 + -8.4571568e-01 -5.2991791e-01 6.2864846e-02 + -6.1394875e-01 7.8236409e-01 1.0475379e-01 + 4.0015280e-01 1.4266285e-02 9.1633739e-01 + -7.0113183e-01 3.6790252e-01 6.1078793e-01 + 6.7177236e-01 6.6554687e-01 3.2522185e-01 + 9.7122843e-01 -2.3793627e-01 -1.0083502e-02 + 5.1039732e-01 -7.2183743e-01 4.6738132e-01 + 4.2077842e-01 8.8127892e-01 -2.1515806e-01 + 4.1396420e-01 8.7047469e-01 2.6628453e-01 + 6.3312871e-01 7.7390796e-01 1.4645803e-02 + -4.4750841e-01 8.0117811e-01 3.9730324e-01 + 8.5678598e-01 1.6604159e-01 4.8820895e-01 + 1.7729414e-01 6.2534035e-01 7.5994489e-01 + -8.8996732e-01 3.2243762e-01 3.2247814e-01 + -1.4406899e-01 2.9780156e-01 9.4369400e-01 + -2.0303787e-02 9.6378174e-01 2.6591823e-01 + -7.5305681e-01 -2.3756212e-01 6.1357125e-01 + 6.9182236e-01 4.4255356e-01 5.7055076e-01 + -8.3930460e-01 7.4246842e-02 5.3856773e-01 + -7.0982752e-01 5.9908498e-01 3.7046197e-01 + 8.7451093e-01 4.0953500e-01 2.5983017e-01 + 6.4554767e-01 1.6320186e-01 7.4607866e-01 + 8.4955423e-01 -1.6681307e-01 5.0043083e-01 + 2.0242088e-01 -8.8679494e-01 4.1547626e-01 + 2.0940392e-01 9.7753798e-01 2.3864061e-02 + -1.5379272e-01 5.9354358e-01 7.8997077e-01 + 7.0547055e-01 -6.7966368e-01 2.0091936e-01 + -3.7597172e-01 -7.6504580e-01 5.2282902e-01 + 4.3965934e-01 -4.3555616e-01 7.8548742e-01 + 9.4585905e-02 -9.8880799e-01 1.1537879e-01 + 4.3941563e-01 -8.7993373e-01 1.8063922e-01 + -6.6587629e-02 -7.6261776e-01 6.4341297e-01 + -3.1987386e-01 9.3930993e-01 1.2400629e-01 + -3.2952073e-01 1.9918247e-02 9.4393821e-01 + -6.6954126e-01 -6.7360360e-01 3.1300590e-01 + -4.5843826e-01 3.0962803e-01 8.3304553e-01 + -1.8082861e-01 -2.7832060e-01 9.4331260e-01 + -6.2109330e-01 2.1095873e-02 7.8345266e-01 + -1.5117089e-01 8.2334345e-01 5.4704015e-01 + 2.5542998e-01 -6.8932086e-01 6.7793235e-01 + 6.3411711e-01 -1.6864943e-01 7.5462100e-01 + 2.7399825e-02 -5.2135890e-01 8.5289750e-01 + -4.6075617e-01 5.9504794e-01 6.5849959e-01 + 4.5526589e-01 6.7747534e-01 5.7771977e-01 + 1.7833113e-01 8.4472563e-01 5.0461531e-01 + 9.7277754e-01 -1.0194304e-02 2.3151658e-01 + 2.0668467e-01 -2.5599243e-01 9.4432480e-01 + -2.9842819e-01 -5.5587085e-01 7.7585322e-01 + -5.9254346e-01 -5.2821377e-01 6.0817962e-01 + -8.4010355e-01 5.3800912e-01 6.9081263e-02 + 1.8761945e-01 2.7140254e-01 9.4400191e-01 + 4.4152002e-01 4.2237795e-01 7.9161666e-01 + -4.9317235e-01 -2.8615786e-01 8.2151976e-01 + 8.7665696e-01 -4.0134475e-01 2.6532051e-01 + -9.7357068e-01 -2.2837893e-01 1.7863258e-03 + -8.9226915e-01 -3.1901843e-01 3.1950430e-01 + -1.2446894e-01 -9.2516730e-01 3.5857070e-01 + 6.9118721e-01 -4.5559735e-01 5.6097353e-01 diff --git a/matlab/CSD/equidistribute.m b/matlab/CSD/equidistribute.m new file mode 100644 index 0000000..daba28a --- /dev/null +++ b/matlab/CSD/equidistribute.m @@ -0,0 +1,44 @@ +function X = equidistribute(N) +% X = equidistribute(N) +% uses the formula in [saff:dmp:1997] to generate equidistributed +% points on the sphere. +% INPUT: N is the number of points, default=12 +% +% OUTPUT: X is the set of points as a Nxd matrix, one point per row +% if no output is specified, the points are plotted using scatter3. +% REFERENCE +% @Article{saff:dmp:1997, +% author = {Saff, E. B. and Kuijlaars, A. B. J.}, +% title = {Distributing Many Points on a Sphere}, +% journal = {Math. Intell.}, +% year = {1997}, +% volume = {19}, +% number = {1}, +% pages = {5--11}, +%} + + +X = zeros(N,3); + +for k=1:N + h = -1 + 2*(k-1)/(N-1); + theta(k) = acos(h); + if k==1 | k==N + phi(k) = 0; + else + phi(k) = mod(phi(k-1) + 3.6/sqrt(N*(1-h^2)),2*pi); + end; + X(k,:) = [ cos(phi(k))*sin(theta(k)), ... + sin(phi(k))*sin(theta(k)), ... + cos(theta(k)) ]; +end; + +%if nargout == 0 + %Z = zeros(size(X)); + %[SX,SY,SZ] = sphere; + %scatter3(X(:,1),X(:,2),X(:,3),'filled') + %hold on + %sph2 = surf(SX,SY,SZ); + %set(sph2, 'FaceColor', [ 1 1 0 ]); + %axis vis3d +%end diff --git a/matlab/CSD/eval_ALP.m b/matlab/CSD/eval_ALP.m new file mode 100644 index 0000000..0800147 --- /dev/null +++ b/matlab/CSD/eval_ALP.m @@ -0,0 +1,15 @@ +function s = eval_ALP(l, el) + +% syntax: s = eval_ALP(l, el) +% +% evaluates the Associated Legendre Polynomial at elevations 'el' +% for harmonic order l. + + s = legendre(l, cos(el')); + for m = 0:l + s(m+1,:) = s(m+1,:).*sqrt((2*l+1)*factorial(l-m) / ((4*pi)*factorial(l+m))); + end + + if l + s = [ s(end:-1:2,:); s ]; + end diff --git a/matlab/CSD/eval_DT.m b/matlab/CSD/eval_DT.m new file mode 100644 index 0000000..29a0027 --- /dev/null +++ b/matlab/CSD/eval_DT.m @@ -0,0 +1,35 @@ +function S = eval_DT (FA, b, scheme, ev_el, ev_az) + +% function S = eval_DT (FA, b, scheme, ev_el, ev_az) +% +% Evaluate the signal amplitude along the directions specified +% in 'scheme', assuming a diffusion tensor model with the +% specified FA, using a b-value of 'b' x10^3 s/mm^2 and a +% mean ADC of 900 x10^6 mm^2/s. Optionally, the tensor can be +% oriented along the direction [ ev_el ev_az ]. + + +if ~exist('ev_el') + ev_el = 0; + ev_az = 0; +end + +a = FA/sqrt(3-2*FA^2); +D = 0.9*[ 1-a 0 0; 0 1-a 0; 0 0 1+2*a ]; +R_az = [ cos(ev_az) -sin(ev_az) 0 + sin(ev_az) cos(ev_az) 0 + 0 0 1 ]; +R_el = [ cos(ev_el) 0 sin(ev_el) + 0 1 0 + -sin(ev_el) 0 cos(ev_el) ]; + +D = R_az*R_el*D*R_el'*R_az'; + +C = s2c([ scheme.el scheme.az 1+0*scheme.az ]); +X = C(:,1); +Y = C(:,2); +Z = C(:,3); + +S = exp(-b*[X.^2 Y.^2 Z.^2 2.*X.*Y 2.*X.*Z 2.*Y.*Z] * ... + [ D(1,1) D(2,2) D(3,3) D(1,2) D(1,3) D(2,3) ]'); + diff --git a/matlab/CSD/eval_SH.m b/matlab/CSD/eval_SH.m new file mode 100644 index 0000000..aa3f36a --- /dev/null +++ b/matlab/CSD/eval_SH.m @@ -0,0 +1,14 @@ +function s = eval_SH(l, el, az) + +% syntax: s = eval_SH(l, el, az) +% +% Evaluates the lth order spherical harmonic coefficients at +% positions [ el az ]. + +s = ones(size(az,1),1); + +if l > 0 + s = [ sin(az*(l:-1:1)) s cos(az*(1:l)) ]; +end + +s = eval_ALP(l, el).*s'; diff --git a/matlab/CSD/gen_delta.m b/matlab/CSD/gen_delta.m new file mode 100644 index 0000000..b310157 --- /dev/null +++ b/matlab/CSD/gen_delta.m @@ -0,0 +1,13 @@ +function SH = gen_delta(el, az, lmax) + +% function SH = gen_delta(el, az, lmax) +% +% Generate the SH coefficients for a delta function pointing +% along [ el az ] up to harmonic order 'lmax'. + + +SH = []; + +for l = 0:2:lmax + SH = [ SH; eval_SH(l, el, az) ]; +end diff --git a/matlab/CSD/gen_scheme.m b/matlab/CSD/gen_scheme.m new file mode 100644 index 0000000..c27d449 --- /dev/null +++ b/matlab/CSD/gen_scheme.m @@ -0,0 +1,45 @@ +function scheme = gen_scheme(N, lmax) + +% function scheme = gen_scheme(N, lmax) +% +% Generate a set of orientations in the required format, along +% with the corresponding SH transform information up to +% harmonic order 'lmax'. +% +% If N is a string, it will attempt to load the specified +% file. +% +% If N is a number, a scheme with the specified number of +% directions will be generated using the equidistribute.m +% script (note that these are not perfectly uniformly +% distributed). +% +% If N is a nx3 matrix, it will assume that each row provides +% an [ x y z ] vector pointing along the desired direction. +% + +if ischar(N) + N = load(N); +end + +if size(N,1) == 1 & size(N,2) == 1 + P = c2s(equidistribute(N)); +elseif size(N,2) >= 3 + n = sqrt(sum(N(:,1:3).^2,2)); + k = find(n); + X = N(k,1:3)./repmat(n(k),1,3); + P = c2s(X); +end + +scheme.el = P(:,1); +scheme.az = P(:,2); + +scheme.sh = []; +scheme.lmax = lmax; + +for l = 0:2:lmax + scheme.sh = [ scheme.sh eval_SH(l, scheme.el, scheme.az)' ]; +end + +scheme.vert= s2c([ scheme.el scheme.az 1+0*scheme.az]); +scheme.mesh = convhulln(scheme.vert); diff --git a/matlab/CSD/lmax_for_SH.m b/matlab/CSD/lmax_for_SH.m new file mode 100644 index 0000000..a61ead0 --- /dev/null +++ b/matlab/CSD/lmax_for_SH.m @@ -0,0 +1,7 @@ +function lmax = lmax_for_SH (SH) + +% function lmax = lmax_for_SH (SH) +% +% returns lmax given 'SH', a vector of even SH coefficients + +lmax = 2*(floor(sqrt(1+8*size(SH,1))-3)/4); diff --git a/matlab/CSD/nSH_for_lmax.m b/matlab/CSD/nSH_for_lmax.m new file mode 100644 index 0000000..db8ca1d --- /dev/null +++ b/matlab/CSD/nSH_for_lmax.m @@ -0,0 +1,8 @@ +function n = nSH_for_lmax (lmax) + +% function n = nSH_for_lmax (lmax) +% +% returns the number of even SH coefficients for a +% given harmonic order 'lmax' + +n = (lmax+1)*(lmax+2)/2; diff --git a/matlab/CSD/noisify.m b/matlab/CSD/noisify.m new file mode 100644 index 0000000..70bf2a3 --- /dev/null +++ b/matlab/CSD/noisify.m @@ -0,0 +1,11 @@ +function S = noisify(S, noise) + +% function S = noisify(S, noise) +% +% Add quadrature noise to signals S, with standard deviation +% 'noise'. + +Nx = noise*randn(size(S,1),1); +Ny = noise*randn(size(S,1),1); +S = sqrt((S+Nx).^2 + Ny.^2); + diff --git a/matlab/CSD/plot_RH.m b/matlab/CSD/plot_RH.m new file mode 100644 index 0000000..2f0aea7 --- /dev/null +++ b/matlab/CSD/plot_RH.m @@ -0,0 +1,8 @@ +function plot_RH(RH, scheme) + +% function plot_RH(RH, scheme) +% +% plot surface given by RH coefficients supplied in 'RH' along +% the set of directions in 'scheme' + +plot_SH (sconv (RH, gen_delta(0, 0, 2*(size(RH,1)-1))), scheme); diff --git a/matlab/CSD/plot_SH.m b/matlab/CSD/plot_SH.m new file mode 100644 index 0000000..f4fcf37 --- /dev/null +++ b/matlab/CSD/plot_SH.m @@ -0,0 +1,12 @@ +function plot_SH (SH, scheme, varargin) + +% function plot_SH (SH, scheme) +% +% plot surface given by SH coefficients supplied in 'SH' along +% the set of directions in 'scheme' + +if (nargin < 3) + plot_amp (SH2amp (SH, scheme), scheme); +else + plot_amp (SH2amp (SH, scheme), scheme, [ 1 1 0 ], 1, varargin{1}); +end \ No newline at end of file diff --git a/matlab/CSD/plot_amp.m b/matlab/CSD/plot_amp.m new file mode 100644 index 0000000..adaa126 --- /dev/null +++ b/matlab/CSD/plot_amp.m @@ -0,0 +1,78 @@ +function plot_amp(S, scheme, colour, transparency, ax) + +% function plot_amp(S, scheme, transparency) +% +% Plot amplitudes 'S' for the set of directions given +% in 'scheme', with optional colour and transparency +% specified. + + +% %set(gcf, 'DefaultAxesCameraViewAngleMode', 'manual', ... +% 'DefaultAxesCameraViewAngle', 20, ... +% 'DefaultAxesCameraTarget', [ 0 0 0 ], ... +% 'DefaultAxesCameraPosition', 6*range*[0 0 1], ... +% 'DefaultAxesVisible', 'on', ... +% 'DefaultAxesBox', 'on', ... +% 'DefaultAxesXLim', [ -range range ], ... +% 'DefaultAxesYLim', [ -range range ], ... +% 'DefaultAxesZLim', [ -range range ]); + + +if ~exist('colour') + colour = [ 1 1 0 ]; +end + +if ~exist('transparency') + transparency = 1; +end + +if ~exist('ax') + main_fig = figure(); + + set(main_fig,'Units','normalized') + + set(main_fig, 'Position', [0.3 0.25 0.4 0.5]); + set(main_fig, 'DoubleBuffer', 'on'); + set(main_fig, 'Name', 'Amplitude plot'); + + cameratoolbar('Show'); + cameratoolbar('SetMode','orbit'); + clf + set(gcf, 'Color', [1 1 1]) +else + subplot(ax); + +end + +range = 1.5*max(S); +negcolour = [ 1 1 1 ]; + +S2 = -S; +S(find(S<0)) = 0; +S2(find(S2<0)) = 0; + +V = scheme.vert .* (S*[ 1 1 1 ]); +V2 = scheme.vert .* (S2*[ 1 1 1 ]); + + +h = patch('Vertices', V, 'Faces', scheme.mesh); +set(h, 'LineStyle', 'None', ... + 'FaceLighting', 'Phong', ... + 'FaceColor', colour, ... + 'FaceAlpha', transparency); + +h2 = patch('Vertices', V2, 'Faces', scheme.mesh); +set(h2, 'LineStyle', 'None', ... + 'FaceLighting', 'Phong', ... + 'FaceColor', negcolour, ... + 'FaceAlpha', transparency); + +light('position', [1 1 1]); + +ylabel('y'); +xlabel('x'); +zlabel('z'); + +if (~exist('ax')) + drawnow +end diff --git a/matlab/CSD/read_mrtrix.m b/matlab/CSD/read_mrtrix.m new file mode 100644 index 0000000..e2ae5b6 --- /dev/null +++ b/matlab/CSD/read_mrtrix.m @@ -0,0 +1,154 @@ +function image = read_mrtrix (filename) + +% function: image = read_mrtrix (filename) +% +% returns a structure containing the header information and data for the MRtrix +% format image 'filename' (i.e. files with the extension '.mif' or '.mih'). + +image.comments = {}; + +f = fopen (filename, 'r'); +if (f<1) + disp (['could not open file ' filename ]); + return +end +L = fgetl(f); +if ~strncmp(L, 'mrtrix image', 12) + fclose(f); + disp ([filename ' is not in MRtrix format']); + return +end + +transform = []; +DW_scheme = []; + +while 1 + L = fgetl(f); + if ~ischar(L), break, end; + L = strtrim(L); + if strcmp(L, 'END'), break, end; + d = strfind (L,':'); + if isempty(d) + disp (['invalid line in header: ''' L ''' - ignored']); + else + key = lower(strtrim(L(1:d(1)-1))); + value = strtrim(L(d(1)+1:end)); + if strcmp(key, 'dim') + image.dim = str2num(char(split_strings (value, ',')))'; + elseif strcmp(key, 'vox') + image.vox = str2num(char(split_strings (value, ',')))'; + elseif strcmp(key, 'layout') + image.layout = value; + elseif strcmp(key, 'datatype') + image.datatype = value; + elseif strcmp(key, 'labels') + image.labels = split_strings (value, '\'); + elseif strcmp(key, 'units') + image.units = split_strings (value, '\'); + elseif strcmp(key, 'offset') + image.offset = value; + elseif strcmp(key, 'transform') + transform(end+1,:) = str2num(char(split_strings (value, ',')))'; + elseif strcmp(key, 'comments') + image.comments{end+1} = value; + elseif strcmp(key, 'conv_type') + image.conv_type = value; + elseif strcmp(key, 'num_points') + image.num_points = value; + elseif strcmp(key, 'num_segments') + image.num_segments = value; + elseif strcmp(key, 'strands_file') + image.strands_file = value; + elseif strcmp(key, 'interpolation') + image.interpolation = value; + elseif strcmp(key, 'interpolation_extent') + image.interpolation_extent = value; + elseif strcmp(key, 'purpose') + image.purpose = value; + elseif strcmp(key, 'response_coeffs') + image.response_coeffs = value; + elseif strcmp(key, 'datetime') + image.datetime = value; + elseif strcmp(key, 'type') + image.type = value; + elseif strcmp(key, 'file') + file = value; + elseif strcmp(key, 'dw_scheme') + DW_scheme(end+1,:) = str2num(char(split_strings (value, ',')))'; + else + disp (['unknown key ''' key ''' - ignored']); + end + end +end +fclose(f); + + +if ~isempty(transform) + image.transform = transform; + image.transform(4,:) = [ 0 0 0 1 ]; +end + +if ~isempty(DW_scheme) + image.DW_scheme = DW_scheme; +end + +if ~isfield (image, 'dim') || ~exist ('file') || ... + ~isfield (image, 'layout') || ~isfield (image, 'datatype') + disp ('critical entries missing in header - not reading data') + return +end + +layout = split_strings(image.layout, ','); +order = (abs(str2num (char(layout)))+1)'; + +[ file, offset ] = strtok(file); +if isempty(offset), offset = 0; else offset = str2num(char(offset)); end +[f,g] = fileparts(filename); +if strcmp(file,'.'), file = filename; else file = fullfile (f, file); end + +datatype = lower(image.datatype); +byteorder = datatype(end-1:end); + +if strcmp(byteorder, 'le') + f = fopen (file, 'r', 'l'); + datatype = datatype(1:end-2); +elseif strcmp(byteorder, 'be') + f = fopen (file, 'r', 'b'); + datatype = datatype(1:end-2); +else + if strcmp(datatype, 'bit') + datatype = 'bit1'; + f = fopen(file, 'r', 'b'); + else + f = fopen(file, 'r'); + end +end + +if (f<1) + disp (['error opening ' filename ]); + return +end + +fseek (f, offset, -1); +image.data = fread (f, inf, datatype); +fclose (f); + +order(order)= 1:size(order,2); +image.data = reshape (image.data, image.dim(order)); +image.data = ipermute (image.data, order); +for i=1:size(order,2) + if layout{i}(1) == '-' + image.data = flipdim(image.data, i); + end +end + + + + +function S = split_strings (V, delim) + S = {}; + while size(V,2) > 0 + [R, V] = strtok(V,delim); + S{end+1} = R; + end + diff --git a/matlab/CSD/readme.txt b/matlab/CSD/readme.txt new file mode 100644 index 0000000..761e552 --- /dev/null +++ b/matlab/CSD/readme.txt @@ -0,0 +1,77 @@ +Here is a sample session to give you a feel for how things work. + +First, we need to generate 3 different sets of directions ('schemes'). + +The first one, 'pscheme', is used for plotting the surfaces, and is +generated at a pretty high resolution (8000 vertices here). We also +specify a value of 'lmax' which at least as high as we're going to use: +>> pscheme = gen_scheme (8000, 16); + +The second one is the actual DW scheme used, or that we're about to +simulate. In this case, it is read from file, and 'lmax' is set to +a value that makes sense for that scheme (in this case, lmax = 8 as +the number of parameters would be too high for lmax = 10): +>> DW_scheme = gen_scheme ('dir60.txt', 8); + +This last scheme is the one along which FOD values will be calculated, +so that negative values can be identified. It is used only with the +constrained version. The value of lmax in this case will instruct the +CSD method of the desired output harmonic order. Thus, setting lmax to +a value greater than can be reconstructed with 'standard' spherical +deconvolution will make the CSD method use super-resolution. +>> HR_scheme = gen_scheme ('dir300.txt', 8); + +Here, we simulate two diffusion tensors crossing at 45°, assuming each +has FA = 0.8, and a b-value of 3000. The DW signal is computed along the +directions of 'DW_scheme': +>> S = eval_DT (0.8, 3, DW_scheme, pi/2, 0) + eval_DT (0.8, 3, DW_scheme, pi/2, pi/4); + +Add quadrature noise (here, SNR = 20, sd = 0.05) to the simulated +DW signals and convert to SH coefficients: +>> S_SH = amp2SH (noisify (S, 0.05), DW_scheme); + +Create the SH coefficients for a response function computed from the +tensor model (FA = 0.8, b-value = 3000). Here, the high-resolution +'pscheme' direction set is used, as it should produce robust results. +In practice, this response function can/should be measured directly +from the data itself. +>> R_SH = amp2SH (eval_DT (0.8, 3, pscheme), pscheme); + +Convert the SH coefficients of the response function to RH coefficients: +>> R_RH = SH2RH (R_SH); + +Now we can perform the spherical deconvolution itself, and plot the +results in each case: + +First, 'standard' unfiltered spherical deconvolution: +>> F_SH_unfiltered = sdeconv (R_RH, S_SH); +>> plot_SH (F_SH_unfiltered, pscheme) + +Next, 'standard' filtered spherical deconvolution. Note that the +filtering coefficients are supplied as their reciprocals - the +filter coefficients here are actually [ 1 1 1 0.1 0.01 inf inf inf ] +(the last four correspond to lmax > 8 and are unused): +>> F_SH_filtered = sdeconv (R_RH.*[1 1 1 2 10 0 0 0 0 ]', S_SH); +>> plot_SH (F_SH_filtered, pscheme) + +Next, constrained spherical deconvolution. Here, we need to supply +a set of directions along which the FOD will be evaluated. This +function can also take two additional optional arguments to set +the value of lambda and tau (type 'help csdeconv' for more info). +The optional return variable 'num_it' gives the number of iterations +performed: +>> [ F_SH_csd, num_it ] = csdeconv (R_RH, S_SH, HR_scheme); +>> plot_SH (F_SH_csd, pscheme) + +Finally, super-resolved constrained spherical deconvolution. This is +the same as above, but this time we set the 'lmax' parameter for +'HR_scheme' to a value greater than can normally be handled with +'standard' spherical deconvolution: +>> HR_scheme = gen_scheme ('dir300.txt', 12); +>> [ F_SH_srcsd, num_it ] = csdeconv (R_RH, S_SH, HR_scheme); +>> plot_SH (F_SH_srcsd, pscheme) + +Have fun! +Cheers, + +Donald. diff --git a/matlab/CSD/s2c.m b/matlab/CSD/s2c.m new file mode 100644 index 0000000..0e214f1 --- /dev/null +++ b/matlab/CSD/s2c.m @@ -0,0 +1,8 @@ +function X = s2c(S) + +% Convert spherical coordinates to the equivalent cartesian coordinates. +% Assumes S = [ el az r ], and returns X = [ X Y Z ]. + +X = [ S(:,3).*cos(S(:,2)).*sin(S(:,1)), ... + S(:,3).*sin(S(:,2)).*sin(S(:,1)), ... + S(:,3).*cos(S(:,1)) ]; diff --git a/matlab/CSD/sconv.m b/matlab/CSD/sconv.m new file mode 100644 index 0000000..6247014 --- /dev/null +++ b/matlab/CSD/sconv.m @@ -0,0 +1,16 @@ +function S_SH = sconv (R_RH, F_SH) + +% function S_SH = sconv (R_RH, F_SH) +% +% convolves the axially symmetric response function 'R_RH' +% (in RH coefficients) with the surface 'F_SH' (in SH +% coefficients) to give the surface 'S_SH' (in SH coefficients). + +b = []; +lmax = lmax_for_SH (F_SH); + +for l = 0:2:lmax + b = [ b; R_RH(l/2+1)*ones(2*l+1,1) ]; +end + +S_SH = b.*F_SH; diff --git a/matlab/CSD/sdeconv.m b/matlab/CSD/sdeconv.m new file mode 100644 index 0000000..b1f56bf --- /dev/null +++ b/matlab/CSD/sdeconv.m @@ -0,0 +1,17 @@ +function F_SH = sdeconv(R_RH, S_SH) + +% function F_SH = sdeconv(R_RH, S_SH) +% +% deconvolves the axially symmetric response function 'R_RH' +% (in RH coefficients) from the surface 'S_SH' (in SH +% coefficients) to give the surface 'F_SH' (in SH coefficients). + +b = []; +lmax = lmax_for_SH (S_SH); + +for l = 0:2:lmax + b = [ b; ones(2*l+1,1)./R_RH(l/2+1) ]; +end + +F_SH = b.*S_SH; + diff --git a/matlab/add_2d_vox_lines_to_plot.m b/matlab/add_2d_vox_lines_to_plot.m new file mode 100644 index 0000000..5b299fc --- /dev/null +++ b/matlab/add_2d_vox_lines_to_plot.m @@ -0,0 +1,43 @@ +function add_2d_vox_lines_to_plot(vox_size, num_voxels, colour, offset) +% function plot_vox_lines(vox_size) + + if ~exist('vox_size','var') + vox_size = 0.15; + end + + if ~exist('num_voxels','var') + num_voxels = 3; + end + + if ~exist('colour','var') + colour = 'white'; + end + + if ~exist('offset','var') + offset = 0; + end + + half_vox_size = vox_size/2; + + hold on; + + start_edge = -half_vox_size*num_voxels; + end_edge = half_vox_size*num_voxels; + + for row_pos = start_edge:vox_size:end_edge + for col_pos = start_edge:vox_size:end_edge + + line_mat = [row_pos, col_pos, start_edge; row_pos, col_pos, end_edge] + offset; + + for dim_i = 0:1 + + plot(line_mat(:,mod(1+dim_i,3)+1),line_mat(:,mod(2+dim_i,3)+1), 'Color', colour); + + end + + end + end + + hold off; + +end \ No newline at end of file diff --git a/matlab/add_colour_key.m b/matlab/add_colour_key.m new file mode 100644 index 0000000..aafd124 --- /dev/null +++ b/matlab/add_colour_key.m @@ -0,0 +1,40 @@ +function add_colour_key(bundle_indices, colours) + +global colours_of_bundles + +if ~exist('bundle_indices','var') + bundle_indices=[0:size(colours_of_bundles,1)-1]; +end + +if isempty(bundle_indices) + return +end + +if exist('colours','var') + + if isempty(colours) || (max(bundle_indices) >= size(colours,1)) + set_bundle_colours(max(bundle_indices)); + colours = colours_of_bundles; + end + +else + colours = colours_of_bundles; +end + + +unique_indices = sort(unique(bundle_indices)); + +h = figure(); + +set(h,'Units','normalized'); +set(h, 'Position', [0.0 0.05 0.05 0.9]); +set(h, 'Name', 'Colour Key'); + +colours2 = reshape(colours, size(colours,1),1,3); + +image(1, [0:1:(length(unique_indices)-1)], colours2((unique_indices+1),:,:)); + +set(gca, 'YTick', [0:1:(length(unique_indices)-1)]); +set(gca, 'YTickLabel', unique_indices); +set(gca, 'XTick', []); +set(get(gca,'YLabel'),'String','Bundle Index'); \ No newline at end of file diff --git a/matlab/add_isotropic_region_to_plot.m b/matlab/add_isotropic_region_to_plot.m new file mode 100644 index 0000000..c2d9393 --- /dev/null +++ b/matlab/add_isotropic_region_to_plot.m @@ -0,0 +1,24 @@ +function add_isotropic_region_to_plot(isotropic_regions) + + for (isotropic_region_i = 1:size(isotropic_regions,1)) + + centre = isotropic_regions(isotropic_region_i, 1:3)'; + radius = isotropic_regions(isotropic_region_i, 4); + + num_faces = round(radius * 100); + + [X, Y, Z] = sphere(num_faces); + + X = X * radius + centre(1); + Y = Y * radius + centre(2); + Z = Z * radius + centre(3); + + h = surf(X, Y, Z); + + set(h,'facecolor', [0.5 0.5 0.5]); + set(h, 'FaceAlpha', 0.5); + end + + + +end \ No newline at end of file diff --git a/matlab/add_lines_to_plot.m b/matlab/add_lines_to_plot.m new file mode 100644 index 0000000..f0b540a --- /dev/null +++ b/matlab/add_lines_to_plot.m @@ -0,0 +1,18 @@ +function add_lines_to_plot(tcks, colours, bundle_indices) +% Adds lines to voxel plot. + + num_tcks = length(tcks); + + hold on; + + for tck_i = 1:num_tcks + + h = plot3(tcks{tck_i}(:,1), tcks{tck_i}(:,2), tcks{tck_i}(:,3)); + + set(h, 'Color', colours(bundle_indices(tck_i)+1,:)); + + end + + hold off; + +end diff --git a/matlab/add_sphere_to_plot.m b/matlab/add_sphere_to_plot.m new file mode 100644 index 0000000..94f7580 --- /dev/null +++ b/matlab/add_sphere_to_plot.m @@ -0,0 +1,56 @@ +function add_sphere_to_plot(sphere_radius, transparency, props, num_divisions, centre) + + if ~exist('num_divisions', 'var') + num_divisions = 100; + end + + if ~exist('centre', 'var') + centre = [0;0;0]; + end + + if ~exist('transparency','var') + transparency = 0.25; + end + + + if sphere_radius == -1 + + if exist('props', 'var') + + if isfield(props, 'prior_end_on_sphere_radius') + sphere_radius = str2double(props.prior_end_on_sphere_radius); + elseif isfield(props, 'prior_end_out_sphere_radius') + sphere_radius = str2double(props.prior_end_out_sphere_radius); + elseif isfield(props, 'prior_end_in_sphere_radius') + sphere_radius = str2double(props.prior_end_in_sphere_radius); + else + %Do nothing. + return; + end + end + end + + + if sphere_radius ~= 0 + + num_faces = round(sphere_radius * num_divisions); + + [X, Y, Z] = sphere(num_faces); + + X = X * sphere_radius + centre(1); + Y = Y * sphere_radius + centre(2); + Z = Z * sphere_radius + centre(3); + + hold on; + + h = surf(X, Y, Z); + + hold off; + + set(h,'facecolor', [0.5 0.5 0.5]); + set(h,'FaceAlpha', transparency); + set(h,'edgecolor', 'none'); + end + + +end \ No newline at end of file diff --git a/matlab/add_strands_to_plot.m b/matlab/add_strands_to_plot.m new file mode 100644 index 0000000..98b120b --- /dev/null +++ b/matlab/add_strands_to_plot.m @@ -0,0 +1,7 @@ +function add_strands_to_plot(strands, radii, colours, bundle_indices, varargin) + + tcks = strands2tcks(strands); + + add_tcks_to_plot(tcks, radii, colours, bundle_indices, varargin{:}); + +end \ No newline at end of file diff --git a/matlab/add_tcks_to_plot.m b/matlab/add_tcks_to_plot.m new file mode 100644 index 0000000..5d7a7f5 --- /dev/null +++ b/matlab/add_tcks_to_plot.m @@ -0,0 +1,178 @@ +function add_tcks_to_plot(tcks, radii, colours, bundle_indices, num_tube_corners) + + if ~exist('num_tube_corners','var') + num_tube_corners = 12; + end + + hold on; + + for tck_i = 1:length(tcks) + + tck = tcks{tck_i}; + + num_control_points = size(tck,1); + + segs = tck(2:num_control_points,:) - tck(1:num_control_points-1,:); + + norm_segs = zeros(size(segs)); + + length_segs = sqrt(dot(segs,segs,2)); + + zero_length_segs = find(length_segs == 0.0); + + if (size(zero_length_segs,1) >= 1) + length_segs(zero_length_segs) = 0.0001; + segs(zero_length_segs) = 0.0001; + tck(zero_length_segs) = tck(zero_length_segs) + 0.0001; + end + + norm_segs(:,1) = segs(:,1) ./ length_segs; + norm_segs(:,2) = segs(:,2) ./ length_segs; + norm_segs(:,3) = segs(:,3) ./ length_segs; + + consec_segs_align = dot(norm_segs(1:num_control_points-2,:), norm_segs(2:num_control_points-1,:),2); + + count = 0; + while (1) + + ref_vector = rand(1,3); + + [t,n,b] = frame( tck(:,1),tck(:,2),tck(:,3), ref_vector); + + if (all(~isnan(n))) + break; + end + + if (count > 100) + error(['likely nan values in tck ' num2str(tck_i-1) '!']); + end + + count = count + 1; + end + + + + X = zeros(num_control_points, num_tube_corners); + Y = zeros(num_control_points, num_tube_corners); + Z = zeros(num_control_points, num_tube_corners); + + theta = 0:(2*pi/(num_tube_corners-1)):(2*pi); + + count = 0; + + for point_i = 1:num_control_points + + if (point_i == 1) + w = tck(1, :) + n(1,:); + n_prime = n(1,:); + b_prime = b(1,:); + + else + + mu = dot(t(point_i,:), tck(point_i,:) - w, 2) / dot(t(point_i,:), segs(point_i-1,:),2); + + w_proj = w + mu * segs(point_i-1, :); + + n_prime = w_proj - tck(point_i,:); + + n_prime = n_prime ./ norm(n_prime); + + b_prime = cross( t(point_i,:), n_prime); + + b_prime = b_prime ./ norm(b_prime); + + w = tck(point_i,:) + n_prime; + + end + + X(point_i,:) = tck(point_i, 1) + radii(tck_i) * ( n_prime(1,1) * cos(theta) + b_prime(1,1) * sin(theta)); + Y(point_i,:) = tck(point_i, 2) + radii(tck_i) * ( n_prime(1,2) * cos(theta) + b_prime(1,2) * sin(theta)); + Z(point_i,:) = tck(point_i, 3) + radii(tck_i) * ( n_prime(1,3) * cos(theta) + b_prime(1,3) * sin(theta)); + + + end + + h = surf(X,Y,Z); + + set(h,'facecolor', colours(bundle_indices(tck_i)+1,:)); + set(h,'edgecolor', 'none'); + + if (mod(tck_i,25) == 0) + fprintf('.'); + end + + end + + hold off; + +end + + + +function [t,n,b]=frame(x,y,z,vec) + +% FRAME Calculate a Frenet-like frame for a polygonal space curve +% [t,n,b]=frame(x,y,z,v) returns the tangent unit vector, a normal +% and a binormal of the space curve x,y,z. The curve may be a row or +% column vector, the frame vectors are each row vectors. +% +% This function calculates the normal by taking the cross product +% of the tangent with the vector v; if v is chosen so that it is +% always far from t the frame will not twist unduly. +% +% If two points coincide, the previous tangent and normal will be used. +% +% Written by Anders Sandberg, asa@nada.kth.se, 2005 + + + N=size(x,1); + if (N==1) + x=x'; %' + y=y'; %' + z=z'; %' + N=size(x,1); + end + + t=zeros(N,3); + b=zeros(N,3); + n=zeros(N,3); + + p=[x y z]; + + for i=2:(N-1) + t(i,:)=(p(i+1,:)-p(i-1,:)); + tl=norm(t(i,:)); + if (tl>0) + t(i,:)=t(i,:)/tl; + else + t(i,:)=t(i-1,:); + end + end + + t(1,:)=p(2,:)-p(1,:); + t(1,:)=t(1,:)/norm(t(1,:)); + + t(N,:)=p(N,:)-p(N-1,:); + t(N,:)=t(N,:)/norm(t(N,:)); + + for i=2:(N-1) + n(i,:)=cross(t(i,:),vec); + nl=norm(n(i,:)); + if (nl>0) + n(i,:)=n(i,:)/nl; + else + n(i,:)=n(i-1,:); + end + end + + n(1,:)=cross(t(1,:),vec); + n(1,:)=n(1,:)/norm(n(1,:)); + + n(N,:)=cross(t(N,:),vec); + n(N,:)=n(N,:)/norm(n(N,:)); + + for i=1:N + b(i,:)=cross(t(i,:),n(i,:)); + b(i,:)=b(i,:)/norm(b(i,:)); + end +end \ No newline at end of file diff --git a/matlab/add_tracts_to_plot.m b/matlab/add_tracts_to_plot.m new file mode 100644 index 0000000..5958919 --- /dev/null +++ b/matlab/add_tracts_to_plot.m @@ -0,0 +1,78 @@ +function add_tracts_to_plot (tracts, colours, intensities, base_widths, tube_corners, num_length_sections, fixed_transparency, colour_indices ) + + + if ~exist('tube_corners', 'var') + tube_corners = 12; + end + + if tube_corners < 1 + error (['''tube_corners'' option must be greater than 1 (' num2str(tube_corners) ').']); + end + + if ~exist('num_length_sections', 'var') + num_length_sections = 100; + end + + if ~exist('fixed_transparency', 'var') + fixed_transparency = 1.0; + end + + if ~exist('colour_indices', 'var') + colour_indices = []; + end + + if isempty(colour_indices) + colour_indices = [0:1:(size(tracts,1)-1)]; + end + + + if nargin > 8 + error(['Incorrect number of arguments (' num2str(nargin) '). Cannot have more than 8']); + end + + num_tracts = size(tracts,1); + + hold on; + + for tract_i=1:num_tracts + + if base_widths(tract_i) == 0 + disp(['Warning!! Base width of tract ' num2str(tract_i) ' is zero.']); + end + + X = zeros(num_length_sections, tube_corners); + Y = zeros(num_length_sections, tube_corners); + Z = zeros(num_length_sections, tube_corners); + + theta = 0:(2*pi/(tube_corners-1)):(2*pi); + + backbone = fourier2tck(tracts{tract_i,1}, num_length_sections); + axis1 = fourier2tck(tracts{tract_i,2}, num_length_sections); + axis2 = fourier2tck(tracts{tract_i,3}, num_length_sections); + + count = 0; + + for point_i = 1:num_length_sections + + X(point_i,:) = backbone(point_i, 1) + base_widths(tract_i) * ( axis1(point_i,1) * cos(theta) + axis2(point_i,1) * sin(theta)); + Y(point_i,:) = backbone(point_i, 2) + base_widths(tract_i) * ( axis1(point_i,2) * cos(theta) + axis2(point_i,2) * sin(theta)); + Z(point_i,:) = backbone(point_i, 3) + base_widths(tract_i) * ( axis1(point_i,3) * cos(theta) + axis2(point_i,3) * sin(theta)); + + end + + h = surf(X,Y,Z); + + set(h,'facecolor', colours(colour_indices(tract_i)+1,:)); + set(h,'edgecolor', 'none'); + + if fixed_transparency ~= 0 + set(h, 'FaceAlpha', fixed_transparency); + else + set(h,'FaceAlpha', intensities(tract_i)); + end + + end + + hold off; + +end \ No newline at end of file diff --git a/matlab/add_vox_lines_to_plot.m b/matlab/add_vox_lines_to_plot.m new file mode 100644 index 0000000..265325e --- /dev/null +++ b/matlab/add_vox_lines_to_plot.m @@ -0,0 +1,43 @@ +function add_vox_lines_to_plot(vox_size, num_voxels, colourize) +% function plot_vox_lines(vox_size) + + if ~exist('colourize') + colourize = true; + end + + label_contrast = 0.8; + + half_vox_size = vox_size/2; + + hold on; + + start_edge = -half_vox_size*num_voxels; + end_edge = half_vox_size*num_voxels; + + base_colour = [.75,.75,.75]; + + for row_pos = start_edge:vox_size:end_edge + for col_pos = start_edge:vox_size:end_edge + + line_mat = [row_pos, col_pos, start_edge; row_pos, col_pos, end_edge]; + + for dim_i = 0:2 + + colour = base_colour; + + if colourize && (row_pos == start_edge) && (col_pos == start_edge) + colour = [0.5,0.5,0.5]; + colour(dim_i+1) = label_contrast; + end + + plot3(line_mat(:,mod(0+dim_i,3)+1),line_mat(:,mod(1+dim_i,3)+1),line_mat(:,mod(2+dim_i,3)+1), 'Color', colour); + + + end + + end + end + + hold off; + +end \ No newline at end of file diff --git a/matlab/btsplot.m b/matlab/btsplot.m new file mode 100644 index 0000000..fb06fc8 --- /dev/null +++ b/matlab/btsplot.m @@ -0,0 +1,25 @@ +function fig = btsplot(varargin) + + if nargin == 0 + error('No arguments supplied'); + end + + filename = varargin{1}; + + if file_extension(filename) == 'str' + fig = plot_strands(varargin{:}); + elseif file_extension(filename) == 'sst' + fig = plot_strand_sets(varargin{:}); + elseif file_extension(filename) == 'tct' + fig = plot_tracts(varargin{:}); + elseif file_extension(filename) == 'tst' + fig = plot_tract_sets(varargin{:}); + elseif file_extension(filename) == 'tck' + fig = plot_tcks(varargin{:}); + elseif file_extension(filename) == 'mif' + fig = plot_image(varargin{:}); + else + error(['Unrecognised extension, ''' file_extension(filename) '''.']); + end + +end \ No newline at end of file diff --git a/matlab/circle_stddev.m b/matlab/circle_stddev.m new file mode 100644 index 0000000..124b4ea --- /dev/null +++ b/matlab/circle_stddev.m @@ -0,0 +1,23 @@ + + +samp_period = 0.001; + +x = [-1:samp_period:1]'; +y = [-1:samp_period:1]'; + +[X,Y] = meshgrid(x,y); + +R = X.^2 + Y.^2; + +ind = find(R>1); + +X(ind) = []; + +x = X(:); + +% hist(x,100); + +std(x) + + + diff --git a/matlab/concatenate_strands.m b/matlab/concatenate_strands.m new file mode 100644 index 0000000..7f55a62 --- /dev/null +++ b/matlab/concatenate_strands.m @@ -0,0 +1,13 @@ +function concat_strands = concatenate_strands(strands) + + num_strands = size(strands,1); + + concat_strands = []; + + for strand_i = 1:num_strands + + concat_strands = [concat_strands; strands{strand_i}]; + + end + +end \ No newline at end of file diff --git a/matlab/concatenate_tracts.m b/matlab/concatenate_tracts.m new file mode 100644 index 0000000..1587c67 --- /dev/null +++ b/matlab/concatenate_tracts.m @@ -0,0 +1,13 @@ +function concat_tracts = concatenate_tracts(tracts) + + num_tracts = size(tracts,1); + + concat_tracts = []; + + for tract_i = 1:num_tracts + concat_tracts = [concat_tracts; tracts{tract_i,1}]; + concat_tracts = [concat_tracts; tracts{tract_i,2}]; + concat_tracts = [concat_tracts; tracts{tract_i,3}]; + end + +end \ No newline at end of file diff --git a/matlab/create_movie_of_samples.m b/matlab/create_movie_of_samples.m new file mode 100644 index 0000000..692fe52 --- /dev/null +++ b/matlab/create_movie_of_samples.m @@ -0,0 +1,99 @@ +function A = create_movie_of_samples(directory_name, varargin) + + + description = 'Creates a movie from a sample directory'; + + arguments = {'directory_name', 'The directory name which contains the samples'}; + + options = {... + ...% 'strand_radius ', 0.02, 'float', 'Radii of the plotted strands';... + }; + + supplied_options = parse_options(options, varargin); + + for option_i = 1:size(supplied_options,1) + if strcmp(supplied_options{option_i,3}, 'string') + eval([supplied_options{option_i,1} ' = ''' supplied_options{option_i,2} ''';']); + else + + if ~isstr(supplied_options{option_i,2}) + supplied_options{option_i,2} = mat2str(supplied_options{option_i,2}); + end + + eval([supplied_options{option_i,1} ' = ' supplied_options{option_i,2} ';']); + end + end + + + if help_display + display_help_message(description, arguments, options); + return; + end + + filenames = list_filenames(directory_name, '0000', '.frr'); + + + + plot_strands(cell2mat(filenames(1))); + + +% 2) Resize the figure window to size of movie required. +set(gcf,'Units','pixels') +winsize = get(gcf,'Position') + +% +% 3) Record the size of the plot window: +% + +% +% 4) Adjust size of this window to include the whole figure window (if you require the axes, title and axis labels +% in the movie): +% +% >> winsize(1:2) = [0 0]; +% +% 5) Set the number of frames: +% + + num_samples=length(filenames) + +% +% 6) Create the MATLAB movie matrix: +% + A=moviein(num_samples,gcf,winsize) +% +% 7) Fix the features of the plot window (ensures each frame of the movie is the same size): +% +% set(fig1,'NextPlot','replacechildren') + + +% +% 8) Within a loop, plot each picture and save to MATLAB movie matrix: +% + for sample_i=1:num_samples + + plot_strands(cell2mat(filenames(sample_i))); + + % add axis label, legends, titles, etc. in here + A(:,sample_i)=getframe(gcf,winsize); + + end +% +% This procedure creates a movie stored in a special format that is only readable in MATLAB. The first thing you will want to do is to play the movie: +% + movie(gcf,A,30,3,winsize) +% +% where fig1 is the figure handle, A is the movie matrix, 30 is the number of times to repeat movie, 3 is the number of frames per second and winsize is the size of the movie window. You can also save this movie to a file to be loaded another time or on another machine running MATLAB: +% + save([directory_name '.mat'],'A'); +% +% and to reload: +% +% >> load filename.mat +% +% +% +% + + + +end \ No newline at end of file diff --git a/matlab/create_uniform_strands.m b/matlab/create_uniform_strands.m new file mode 100644 index 0000000..1a6fd9e --- /dev/null +++ b/matlab/create_uniform_strands.m @@ -0,0 +1,73 @@ +function create_uniform_strands(output_dir, varargin) +% +% PURPOSE: Initialise a number of straight strands evenly distributed around a sphere. +% +% ARGUMENTS: +% +% output_directory The directory that the newly created strands will be saved to +% +% OPTIONS (name, description, type, default): +% +% -num_strands +% number of strands to be created +% int +% 16 +% +% -strand_length +% The v1 magnitude of the fourier descriptors of the strands +% float +% 0.053 + + + description = 'Initialise a number of straight strands evenly distributed around a sphere.'; + + arguments = {'output_directory', 'The directory that the newly created strands will be saved to'}; + + options = {... + 'num_strands ', 16, 'int', 'number of strands to be created';... + 'strand_length ', 0.2755, 'float', 'The v1 magnitude of the fourier descriptors of the strands';... + }; + + supplied_options = parse_options(options, varargin); + + for option_i = 1:size(supplied_options,1) + if strcmp(supplied_options{option_i,3}, 'string') + eval([supplied_options{option_i,1} ' = ''' supplied_options{option_i,2} ''';']); + else + + if ~isstr(supplied_options{option_i,2}) + supplied_options{option_i,2} = mat2str(supplied_options{option_i,2}); + end + + eval([supplied_options{option_i,1} ' = ' supplied_options{option_i,2} ';']); + end + end + + + if help_display + display_help_message(description, arguments, options); + return; + end + + + degree_1s = strand_length * equidistribute(num_strands*2); + + degree_1s_z = degree_1s(:,3); + + positive_degree_1s_z = find(degree_1s_z >= 0); + + degree_1s = degree_1s(positive_degree_1s_z,:); + + + for strand_i = 1:num_strands + + strand = [0 0 0; degree_1s(strand_i,:); 0 0 0]; + + + save([output_dir '/strand_' num2str(strand_i) '.frr.txt'], 'strand', '-ASCII'); + + end + + + +end \ No newline at end of file diff --git a/matlab/diffusion_weight_example.m b/matlab/diffusion_weight_example.m new file mode 100644 index 0000000..ec62ec7 --- /dev/null +++ b/matlab/diffusion_weight_example.m @@ -0,0 +1,175 @@ +N = 10000; +sigma_incr = 0.1; +sigma_N = 5; +output_path = '/data/home/tclose/Documents/Tractography/florey_student_talk/images/normal'; +resolution = 300; +container_size = 0.35; + + +close all; +fig_num = 1; + +x_limits = [-3.5*sigma_incr*sigma_N, 3.5*sigma_incr*sigma_N]; + +y_limits = [0, 1/(sigma_incr*sqrt(2*pi))]; + +background = [0 1 0]; + + + +%set(gca, 'visible', 'off'); + +% xlabel(''); +% +% colormap('gray'); +% caxis([-2 -1]); +background = [0 1 0]; +whitebg(background); +set(gcf, 'Color', background); +% set(gca,'XColor', [1 1 1]); +% set(gca,'YColor', [1 1 1]); +% set(gca,'ZColor', [1 1 1]); +% +% set(gca, 'FontSize', 18); + +set(gcf,'PaperUnits','centimeters'); + +set(gcf, 'PaperSize', [8 8]); +set(gcf, 'PaperPosition', [0 0 8 8]); + +%set(gca, 'visible', 'off'); +set(gca, 'Outerposition', [0 0 1 1]); +set(gca, 'Position', [0.1 0.15 .8 .8]); + +set(gcf,'InvertHardCopy','off'); + +count = 1; + +range = 3.5*sigma_incr*sigma_N; +incr = range/N; + +k = [-range:incr:range]; + +% k = [-k(end:-1:1), 0, k]; + +k_index = [0:1:N-1]; + +container_size_N = round(container_size * (N/range)); + +odd_index = k_index(find(mod(k_index ./ container_size_N, 2) >= 1))+1; + +even_index = k_index(find(mod(k_index ./ container_size_N, 2) < 1))+1; + +k_index(even_index) = mod(k_index(even_index), container_size_N); + +k_index(odd_index) = container_size_N - mod(k_index(odd_index), container_size_N)-1; + +k_index = k_index + 1; + +k_index = [-k_index(end:-1:1),0,k_index] + container_size_N+1; + +folded_k = [-container_size:incr:container_size]; + + +for sigma = sigma_incr:sigma_incr:(sigma_incr*sigma_N) + + gauss_kernel = 1/(sigma*sqrt(2*pi)) * exp(- (k.^2) / (2 *sigma^2)); + + folded_gauss_kernel = zeros(1,2*container_size_N+1); + + for i = 1:size(k_index,2) + folded_gauss_kernel(k_index(i)) = folded_gauss_kernel(k_index(i)) + gauss_kernel(i); + end + + +% figure(fig_num); fig_num = fig_num + 1; +% plot(k, gauss_kernel, 'color', [0.7383,0.6523,0.9570], 'LineWidth', 2); + plot(folded_k, folded_gauss_kernel, 'color', [0.7383,0.6523,0.9570], 'LineWidth', 2); + + xlim(x_limits); + ylim(y_limits); + + + axis('off'); + + path = [output_path '-' num2str(count)]; + + print(gcf, '-dpng', ['-r' num2str(resolution) ' '], path); + + cdata = imread([path '.png']); + % + imwrite(cdata, [path '.png'], 'png', 'BitDepth', 16, 'transparency', background) + + count = count + 1; + +end + + +return; + + +init_img = ones(N,N,3) * 0.5; + +figure(fig_num); fig_num = fig_num + 1; +image(init_img); +pause; + +b2w = -.5:(1/(N-1)):.5; +grad_img = repmat(b2w, N, 1); +grad_img = cat(3, grad_img, grad_img, grad_img); + +img = init_img + grad_img; + +figure(fig_num); fig_num = fig_num + 1; +image(img); +pause; + +img = init_img - grad_img; + +figure(fig_num); fig_num = fig_num + 1; +image(img); +pause; + + + + + + + + +for sigma = sigma_incr:sigma_incr:(sigma_incr*sigma_N) + + Sigma = sigma * N; + k = -3*Sigma:1:(3*Sigma+1); + + ext_b2w = (-.5 - 3.1 * sigma):(1/(N-1)):(.5 + 3.1 * sigma); + + gauss_kernel = 1/(Sigma*sqrt(2*pi)) * exp(- (k.^2) / (2 * Sigma^2)); + + diff_b2w = conv(gauss_kernel, ext_b2w); + + trim_N = (size(diff_b2w,2) - N)/2; + + diff_b2w = diff_b2w(floor(trim_N):(end-ceil(trim_N)-1)); + + diff_img = repmat(diff_b2w, N, 1); + diff_img = cat(3, diff_img, diff_img, diff_img); + + size(diff_img) + size(init_img) + img = init_img + diff_img; + + img(find(img > 1.0)) = 1.0; + img(find(img < 0)) = 0; + + + figure(fig_num); fig_num = fig_num + 1; + image(img); + pause; + +end + +img = diff_img - grad_img; + +figure(fig_num); fig_num = fig_num + 1; +image(diff_img); \ No newline at end of file diff --git a/matlab/display_reference_sphere.m b/matlab/display_reference_sphere.m new file mode 100644 index 0000000..3d1dbe6 --- /dev/null +++ b/matlab/display_reference_sphere.m @@ -0,0 +1,24 @@ +function display_reference_sphere(sphere_radius, face_alpha) + + centre = [0; 0; 0]; + + num_faces = round(sphere_radius * 100); + + [X, Y, Z] = sphere(num_faces); + + X = X * sphere_radius + centre(1); + Y = Y * sphere_radius + centre(2); + Z = Z * sphere_radius + centre(3); + + hold on; + + h = surf(X, Y, Z); + + hold off; + + set(h,'facecolor', [0.5 0.5 0.5]); + set(h, 'FaceAlpha', face_alpha); + set(h,'edgecolor', 'none') + + +end \ No newline at end of file diff --git a/matlab/eval_response_coeffs.m b/matlab/eval_response_coeffs.m new file mode 100644 index 0000000..9990cc6 --- /dev/null +++ b/matlab/eval_response_coeffs.m @@ -0,0 +1,20 @@ +function S = eval_response_coeffs(response_coeff, scheme, eig_v) + +%Normalise and ensure that eig_v is 3x1 +eig_v = reshape((eig_v ./ norm(eig_v)),3,1); + +%Convert gradient scheme to cartesian coordinates +grad_C = s2c([ scheme.el scheme.az 1+0*scheme.az ])'; + +%Tile eig_v to match gradient scheme size +eig_v = repmat(eig_v , 1, size(grad_C,2)); + +%Get the cosine(angle) between the gradients and the principle eigenvector +cos_angle = dot(grad_C, eig_v)'; + +%Evaluate the signal functions from the response coefficients and the +%cosine angles +S = response_coeff(1) + response_coeff(2) * cos_angle.^2 + ... + response_coeff(3) * cos_angle.^4 + response_coeff(4) * cos_angle.^6+... + response_coeff(5) * cos_angle.^8; + diff --git a/matlab/example_tract.m b/matlab/example_tract.m new file mode 100644 index 0000000..44bc025 --- /dev/null +++ b/matlab/example_tract.m @@ -0,0 +1,198 @@ +function example_tract + + + function prep_figure_for_save(cam_orbit, limits) + + xlim(limits(1,:)); + ylim(limits(2,:)); + zlim(limits(3,:)); + + daspect ([ 1 1 1 ]); + camorbit(cam_orbit(1),cam_orbit(2)); + + cameratoolbar('Show'); + cameratoolbar('SetMode','orbit'); + + light + lighting gouraud; + + end + + close all; + + +% Set defaults + + red_colour = [ 0.7, 0.2, 0.2]; + grey_colour = [0.7,0.7,0.7]; + green_colour = [0.2,0.7,0.2]; + blue_colour = [0.2,0.2,0.7]; + + num_width_sections = 6; + + strand_radii = 0.005; + + cam_orbit = [70, -65]; + + def_dlimit = .275; + + data_limits = [-def_dlimit, def_dlimit; -def_dlimit, def_dlimit; -def_dlimit, def_dlimit]; + + + +% Load data + + [tract, prop_keys, prop_value] = load_tracts('/home/tclose/Data/Tractography/poster/example/deform.tct'); + base_width = get_properties(prop_keys, prop_value, 'base_width', 0.01); + + backbone = load_strands('/home/tclose/Data/Tractography/poster/example/backbone.str'); + back_to_strand1 = load_strand_sets('poster/example/back_to_strand1.sst'); + back_to_strand2 = load_strand_sets('poster/example/back_to_strand2.sst'); + strand1_about_back = load_strand_sets('poster/example/str1_about_back.sst'); + strand2_about_back = load_strand_sets('poster/example/str2_about_back.sst'); + + +% Backbone + + back_fig = my_figure('Backbone'); + + add_strands_to_plot(backbone, strand_radii, red_colour , [0]); + + prep_figure_for_save(cam_orbit, data_limits); + + save_figure_for_poster('/home/tclose/Documents/Tractography/ismrm/images/backbone'); + + + + % Backbone to Strand1 + + back_to_str1_fig = my_figure('Backbone to Strand1'); + + add_strands_to_plot(backbone, strand_radii, red_colour , [0]); + + for set_i = 2:size(back_to_strand1,1) + add_strands_to_plot(back_to_strand1{set_i}, strand_radii, grey_colour , [0]); + end + + prep_figure_for_save(cam_orbit, data_limits); + + save_figure_for_poster('/home/tclose/Documents/Tractography/ismrm/images/back_to_str1'); + + + + % Backbone to Strand2 + + back_to_str2_fig = my_figure('Backbone to Strand2'); + + + add_strands_to_plot(backbone, strand_radii, red_colour , [0]); + + + for set_i = 2:size(back_to_strand2,1) + add_strands_to_plot(back_to_strand2{set_i}, strand_radii, grey_colour , [0]); + end + + prep_figure_for_save(cam_orbit, data_limits); + + + save_figure_for_poster('/home/tclose/Documents/Tractography/ismrm/images/back_to_str2'); + + + + +% Strand1 about Backbone + + num_strands = size(strand1_about_back,1); + + half = floor(num_strands / 2); + + str1_about_back_fig = my_figure('Strand1 about Backbone'); + + add_strands_to_plot(backbone, strand_radii, red_colour , [0]); + + for set_i = [1:half, (half+2):num_strands] + add_strands_to_plot(strand2_about_back{set_i}, strand_radii, grey_colour , [0]); + end + + prep_figure_for_save(cam_orbit, data_limits); + + save_figure_for_poster('/home/tclose/Documents/Tractography/ismrm/images/str1_about_back'); + + + +% Strand2 about Backbone + + num_strands = size(strand2_about_back,1); + + half = floor(num_strands / 2); + + str2_about_back_fig = my_figure('Strand2 about Backbone'); + + add_strands_to_plot(backbone, strand_radii, red_colour , [0]); + + for set_i = [1:half, (half+2):num_strands] + add_strands_to_plot(strand1_about_back{set_i}, strand_radii, grey_colour , [0]); + end + + prep_figure_for_save(cam_orbit, data_limits); + + + save_figure_for_poster('/home/tclose/Documents/Tractography/ismrm/images/str2_about_back'); + + + + +% Tract Strands + + + + [strands, bundle_indices] = tracts2strands(tract, base_width, num_width_sections); + + num_strands = length(strands); + + bundle_colours = repmat(grey_colour, num_strands,1); + + central_strand_index = (num_strands-1)/2+1; + + + for strand_i = 31:39 + bundle_colours(strand_i,:) = blue_colour; + end + + for strand_i = [3,9,17,26,44,53,61,67] + bundle_colours(strand_i,:) = green_colour; + end + + bundle_colours(central_strand_index,:) = red_colour; + + +% set_bundle_colours(num_strands); +% +% global colours_of_bundles; +% bundle_colours = colours_of_bundles; + + + tract_fig = my_figure('Tract Strands'); + + + add_strands_to_plot(strands, repmat(strand_radii, num_strands,1), bundle_colours, [0:1:num_strands-1]); + + + prep_figure_for_save(cam_orbit, data_limits); + + + save_figure_for_poster('/home/tclose/Documents/Tractography/ismrm/images/tract_strands'); + + + +% Whole Tract + + tract_fig = my_figure('Whole Tract'); + + add_tracts_to_plot(tract, grey_colour, 1.0, base_width,0,100,64); + + prep_figure_for_save(cam_orbit, data_limits); + + save_figure_for_poster('/home/tclose/Documents/Tractography/ismrm/images/whole_tract'); + +end \ No newline at end of file diff --git a/matlab/fourier2tck.m b/matlab/fourier2tck.m new file mode 100644 index 0000000..51443c1 --- /dev/null +++ b/matlab/fourier2tck.m @@ -0,0 +1,30 @@ +function tck = fourier2tck(fourier, varargin) +% function tck = fourier2tck(fourier, [num_points=50]) +% +% converts fourier descriptors into a track of num_points length. +% + +if (nargin == 2) + num_points = varargin{1}; +else + num_points = 100; +end + +degree = size(fourier,1); + +k = [0:1:(num_points-1)]'./(num_points-1); + + +if (degree < 1) + error('Fourier coefficients have degree of less than 1'); +end + +psi = ones(num_points,1); + +for (d = [1:(degree-1)]) + + psi = [psi, sqrt(2) * cos(pi * k * d)]; + +end + +tck = psi * fourier; \ No newline at end of file diff --git a/matlab/fourier_descr_matrix.m b/matlab/fourier_descr_matrix.m new file mode 100644 index 0000000..18468ec --- /dev/null +++ b/matlab/fourier_descr_matrix.m @@ -0,0 +1,20 @@ +function psi = fourier_descr_matrix(num_samples, degree, include_endpoints) + + + if include_endpoints + k = [0:1:(num_samples-1)]'./(num_samples-1); + else + k = [1:num_samples]'./(num_samples+1); + end + + if (degree >= 0) + psi = ones(num_samples,1); + end + + for (d = [1:(degree-1)]) + + psi = [psi, sqrt(2) * cos(pi * k * d)]; + + end + +end \ No newline at end of file diff --git a/matlab/get_num_section_properties.m b/matlab/get_num_section_properties.m new file mode 100644 index 0000000..f614f12 --- /dev/null +++ b/matlab/get_num_section_properties.m @@ -0,0 +1,33 @@ +function [num_length_sections, num_width_sections] = get_num_section_properties(properties, style) + + if isfield(properties, 'exp_num_segments') + num_length_sections = str2double(properties.exp_num_segments); + elseif isfield(properties, 'exp_num_length_sections') + num_length_sections = str2double(properties.exp_num_length_sections); + else + disp('Warning!! Did not find number of length samples, using defaults.'); + num_length_sections = 50; + end + + need_width_sections = false; + + if (strfind('lines', style) == 1) + need_width_sections = true; + elseif (strfind('tubes', style) == 1) + need_width_sections = true; + end + + if need_width_sections + if isfield(properties, 'exp_num_strands') + num_width_sections = str2double(properties.exp_num_strands); + elseif isfield(properties, 'exp_num_width_sections') + num_width_sections = str2double(properties.exp_num_width_sections); + else + disp('Warning!! Did not find number of width samples, using defaults.'); + num_width_sections = 2; + end + else + num_width_sections = []; + end + +end diff --git a/matlab/get_obs_img_dims.m b/matlab/get_obs_img_dims.m new file mode 100644 index 0000000..c347bb8 --- /dev/null +++ b/matlab/get_obs_img_dims.m @@ -0,0 +1,46 @@ +function [dim] = get_observed_dims(properties) + + if isfield(properties, 'exp_num_segments') + obs_image_location = properties.obs_image; + else + disp('Warning!! Did not observed image location field of using number of voxels default (3).'); + num_length_sections = 3; + end + + f = fopen (filename, 'r'); + if (f<1) + disp (['Warning!! could not open observed image file ''' filename ''' to determine number of voxels']); + return + end + L = fgetl(f); + if ~strncmp(L, 'mrtrix image', 12) + fclose(f); + disp ([filename ' is not in MRtrix format']); + return + end + + dim = []; + + while 1 + L = fgetl(f); + if ~ischar(L), break, end; + L = strtrim(L); + if strcmp(L, 'END'), break, end; + d = strfind (L,':'); + if ~isempty(d) + key = lower(strtrim(L(1:d(1)-1))); + value = strtrim(L(d(1)+1:end)); + if strcmp(key, 'dim') + dim = str2num(char(split_strings (value, ',')))'; + break; + end + end + + fclose(f); + + + if isempty(dim) + + + +end diff --git a/matlab/get_observed_dims.m b/matlab/get_observed_dims.m new file mode 100644 index 0000000..384a061 --- /dev/null +++ b/matlab/get_observed_dims.m @@ -0,0 +1,62 @@ +function [dims, true_location] = get_observed_properties(properties) + + if isfield(properties, 'obs_image') + obs_image_location = properties.obs_image; + else + disp('Warning!! Did not find observed image location field of using image dimensions default (3x3x3).'); + dims = [3 3 3]; + return; + end + + f = fopen (obs_image_location, 'r'); + if (f<1) + disp (['Warning!! could not open observed image file ''' obs_image_location ''' to determine image dimensions']); + dims = [3,3,3]; + return + end + L = fgetl(f); + if ~strncmp(L, 'mrtrix image', 12) + fclose(f); + disp (['Warning!! observed image file ''' obs_image_location ''' is not in MRtrix format, could not determine image dimensions.']); + dims = [3 3 3]; + return + end + + dims = []; + + while 1 + L = fgetl(f); + if ~ischar(L), break, end; + L = strtrim(L); + if strcmp(L, 'END'), break, end; + d = strfind (L,':'); + if ~isempty(d) + key = lower(strtrim(L(1:d(1)-1))); + value = strtrim(L(d(1)+1:end)); + if strcmp(key, 'dim') + dims = str2num(char(split_strings (value, ',')))'; + break; + end + end + end + + fclose(f); + + if isempty(dims) + disp('Warning!! Observed image location did not specifiy image dimensions.'); + dims = [3 3 3]; + end + + + +end + + + +function S = split_strings (V, delim) + S = {}; + while size(V,2) > 0 + [R, V] = strtok(V,delim); + S{end+1} = R; + end +end \ No newline at end of file diff --git a/matlab/get_observed_properties.m b/matlab/get_observed_properties.m new file mode 100644 index 0000000..1a1d7a6 --- /dev/null +++ b/matlab/get_observed_properties.m @@ -0,0 +1,69 @@ +function [dims, true_location] = get_observed_properties(properties) + + true_location = []; + + if isfield(properties, 'obs_image') + obs_image_location = properties.obs_image; + else + disp('Warning!! Did not find observed image location field of using image dimensions default (3x3x3).'); + dims = [3 3 3]; + return; + end + + f = fopen (obs_image_location, 'r'); + if (f<1) + disp (['Warning!! could not open observed image file ''' obs_image_location ''' to determine image dimensions']); + dims = [3,3,3]; + return + end + L = fgetl(f); + if ~strncmp(L, 'mrtrix image', 12) + fclose(f); + disp (['Warning!! observed image file ''' obs_image_location ''' is not in MRtrix format, could not determine image dimensions.']); + dims = [3 3 3]; + return + end + + dims = []; + + while 1 + L = fgetl(f); + if ~ischar(L), break, end; + L = strtrim(L); + if strcmp(L, 'END'), break, end; + d = strfind (L,':'); + if ~isempty(d) + key = lower(strtrim(L(1:d(1)-1))); + value = strtrim(L(d(1)+1:end)); + if strcmp(key, 'dim') + dims = str2num(char(split_strings (value, ',')))'; + elseif strcmp(key, 'state_location') + true_location = char(split_strings (value, ',')); + end + end + end + + fclose(f); + +% if isempty(dims) +% disp('Warning!! Observed image location did not specifiy image dimensions.'); +% dims = [3 3 3]; +% end +% +% if isempty(true_location) +% disp('Warning!! Observed image location did not specifiy inital location.'); +% end + + + +end + + + +function S = split_strings (V, delim) + S = {}; + while size(V,2) > 0 + [R, V] = strtok(V,delim); + S{end+1} = R; + end +end \ No newline at end of file diff --git a/matlab/get_properties.m b/matlab/get_properties.m new file mode 100644 index 0000000..ca213cf --- /dev/null +++ b/matlab/get_properties.m @@ -0,0 +1,53 @@ +function values = get_properties(keys, all_values, key, varargin) + + if nargin >= 4 + default_value = varargin{1}; + + else + default_value = []; + end + + if nargin >= 5 + num_rows = varargin{2}; + else + num_rows = 0; + end + + if nargin == 6 + datatype = varargin{3}; % Defaults to double but can also be 'string'. + else + datatype = 'double'; + end + + key_i = strmatch(key, keys, 'exact'); + + if ~isempty(key_i) + + if strcmp(datatype, 'double') + values = str2double(all_values(:, key_i)); + + elseif strcmp(datatype, 'string') + values = all_values(:, key_i); + + else + error(['Unrecognised dataype ''' datatype '''']); + + end + + else + + if size(default_value) == [1 1]; %If the default value is a scalar make a vector the size of the number of rows with each element equal to the default value + values = ones(num_rows,1) * default_value; + + elseif (size(default_value,1) == num_rows) || (size(keys,1) == 0) % Else if the default value + values = default_value; + + else + error(['Size of default value (' num2str(size(default_value,1)) ') does not match number of rows (' num2str(num_rows) '), and alternatively is not a scalar']); + + end + + end + + +end \ No newline at end of file diff --git a/matlab/grad_scheme.mat b/matlab/grad_scheme.mat new file mode 100644 index 0000000..b38056e Binary files /dev/null and b/matlab/grad_scheme.mat differ diff --git a/matlab/gradient_calc_validation.m b/matlab/gradient_calc_validation.m new file mode 100644 index 0000000..13da7ad --- /dev/null +++ b/matlab/gradient_calc_validation.m @@ -0,0 +1,523 @@ +function gradient_calc_validation + +%----------------------------------------------------% +%----------------------------------------------------% +% Constants % +%----------------------------------------------------% +%----------------------------------------------------% + +%Number of 'time' (free parameter of the strand parameterisation) samples. +T = 20 + +%Degree of Fourier Descriptors +D = 3 + +%DW sample orientations +U = [ 0.9413 -0.0407 -0.3351; + -0.8846 -0.3834 -0.2654; + -0.1714 -0.7779 0.6046; + 0.4040 -0.2802 -0.8708; + 0.1593 -0.7891 0.5932; + 0.1960 -0.3076 0.9311; + -0.0815 0.2989 0.9508; + 0.2384 0.7604 0.6042; + 0.6346 0.7660 -0.1025; + 0.9924 -0.1223 -0.0151; + 0.2629 -0.5636 -0.7831; + 0.1511 0.9332 0.3260; + -0.4723 -0.7962 -0.3783; + 0.3909 0 0.9204; + 0.6807 0.5251 0.5108; + 0.2602 -0.9654 -0.0149; + 0.5118 -0.2842 0.8107; + 0.6354 0.4318 -0.6402; + 0.5055 -0.8350 -0.2174; + 0.3404 -0.5611 0.7545; + -0.3686 -0.8923 0.2605; + -0.4293 -0.5237 -0.7358; + 0.7402 -0.0887 0.6665; + -0.7366 -0.5749 0.3561; + -0.6702 0.4612 -0.5815; + -0.8144 -0.2115 -0.5404; + 0.0739 0.9973 0; + -0.1919 0.9231 0.3332; + -0.7180 -0.6653 -0.2047; + 0.2784 -0.9094 0.3090; + -0.5392 0.8337 -0.1189; + -0.5836 -0.2303 -0.7787; + -0.0742 -0.5672 -0.8203; + -0.4803 0.7237 -0.4955; + -0.0686 0 -0.9976; + 0.6979 -0.6031 -0.3863; + -0.0887 0.7850 0.6131; + 0.6301 -0.0634 -0.7739; + -0.2544 -0.3018 -0.9188; + -0.9045 -0.2937 0.3093; + 0.9044 -0.4125 0.1089; + 0.4737 0.2298 -0.8502; + 0.2616 0.0001 -0.9652; + 0.3362 0.5345 -0.7754; + 0.9786 0.2057 0; + 0.1428 0.3091 -0.9402; + 0.5723 -0.4776 -0.6666; + -0.0492 -0.9405 0.3361; + 0.9566 0.0391 0.2889; + 0.7269 -0.6210 0.2932; + -0.0076 0.5804 -0.8143; + 0.8580 0.5109 -0.0530; + -0.3915 -0.9169 -0.0770; + 0.4133 -0.7417 -0.5283; + 0.7995 0.1435 -0.5833; + 0.8747 -0.2627 0.4072; + -0.4816 -0.7070 0.5179; + -0.7969 0.2592 0.5457; + 0.7540 -0.6540 -0.0621; + -0.8983 0.3722 0.2335]; + + %Pregenerated Fourier Descriptor basis set; + PSI = fourier_descr_matrix(T, D, 0); + + %Pregenerated derived Fourier Descriptor w.r.t 'time' basis set + dPSI = d_fourier_descr_matrix(T, D, 0); + + %Signal response model coefficients +% Resp = [0.3475; -1.6274; 3.2524; -3.0952; 1.1302]; + + Resp = [0.264387; -1.50073; 1.89986; -1.28088; 0.366885]; + + %Voxel centre + VOX = [0.0, 0.0, 0.0]; + + %Gaussian blur standard deviation + ALPHA = 1.0; + + + +%----------------------------------------------------% +%----------------------------------------------------% +% Default Indices % +%----------------------------------------------------% +%----------------------------------------------------% + + +% %Response coefficient index + j = 4; + +% %Strand free parameter, 'time', index. + t = 10 +% +% %Strand degree index + m = 2 +% +% %Strand spatial dimension index + d = 1 +% +% %DW Sample orientation index + i = 1 +% +% %Voxel index + n = 1 + + +%----------------------------------------------------% +%----------------------------------------------------% +% Primary Functions % +%----------------------------------------------------% +%----------------------------------------------------% + + %Point 't', along strand path. + function lambda_t = Lambda(V,t) + + lambda = PSI * V; + + lambda_t = lambda(t,:)'; + + end + + %Gradient w.r.t V(m,d) + function dlambda_t = dLambda(V,t,m) + + dlambda_t = PSI(t,m); + + end + + + %Tangent at point 't' along strand path + function glambda_t = GLambda(V,t) + + glambda = dPSI * V; + + glambda_t = glambda(t,:)'; + + end + + %Gradient w.r.t V(m,d) + function dglambda_t = dGLambda(V,t,m) + + dglambda_t = dPSI(t,m); + + end + + + + %Signal response model coefficient 'j' + function r = R(j) + + r = Resp(j+1); + + end + + %Voxel n + function x = X(n) + + x = VOX(n,:)'; + + end + + + %Gaussian smoothing kernel normalising scalar. + function scalar = ConvScalar + + scalar = 1/( sqrt(2) * pi * ALPHA ); + + end + + +%----------------------------------------------------% +%----------------------------------------------------% +% Secondary Functions % +%----------------------------------------------------% +%----------------------------------------------------% + + + % %tang_dw_dot% Dot product between strand tangent and DW-sample orientation 'i'. + function rho_ti = Rho(V, t, i) + + rho_ti = U(i,:) * GLambda(V,t); + + end + + + %Gradient w.r.t V(m,d) + function drho_ti = dRho(V, t, i, d, m) + + drho_ti = U(i,d) * dGLambda(V,t,m); + + end + + + % %param_speed2% (Parameterisation speed)^2 at point 't' along strand path + function zeta_t = Zeta(V, t) + + zeta_t = GLambda(V,t)' * GLambda(V,t); + + end + + %Gradient w.r.t V(m,d) + function dzeta_t = dZeta(V, t, d, m) + + gLambda_Vt = GLambda(V,t); + + dzeta_t = 2 * dGLambda(V,t,m) * gLambda_Vt(d); + + end + + % %strand_to_vox_disp% Displacement along dimension 'd', between voxel 'n' and point 't' along strand path, + %normalised by the standard deviation of the Gaussian smoothing kernel. + function delta_t = Delta(V, t, n, d) + + lambda_Vt = Lambda(V, t); + Xn = X(n); + delta_t = (lambda_Vt(d) - Xn(d))/ALPHA; + + end + + %Gradient w.r.t V(m,d) + function ddelta_t = dDelta(V, t, n, d, m) + + ddelta_t = dLambda(V,t,m)/ALPHA; + + end + + + +%----------------------------------------------------% +%----------------------------------------------------% +% Tertiary Functions % +%----------------------------------------------------% +%----------------------------------------------------% + + + + + %Dot product between strand tangent and DW-sample orientation 'i'. + function qrho_ti = QRho(V, t, i) + + qrho_ti = Rho(V,t,i) ^ (2*j); + + end + + + %Gradient w.r.t V(m,d) + function dqrho_ti = dQRho(V, t, i, d, m) + + dqrho_ti = dRho(V,t,i,d,m) * (2*j) * Rho(V,t,i) ^ (2*j-1); + + end + + + %(Parameterisation speed)^2 at point 't' along strand path + function qzeta_t = QZeta(V, t) + + qzeta_t = Zeta(V,t) ^ ( (1-2*j)/2 ); + + end + + %Gradient w.r.t V(m,d) + function dqzeta_t = dQZeta(V, t, d, m) + + dqzeta_t = dZeta(V,t,d,m) * ( (1-2*j)/2 ) * Zeta(V,t) ^ ( (-1-2*j)/2 ); + + end + + %Displacement along dimension 'd', between voxel 'n' and point 't' along strand path, + %normalised by the standard deviation of the Gaussian smoothing kernel. + function qdelta_t = QDelta(V, t, n, d) + + qdelta_t = exp(-Delta(V,t,n,d)^2); + + end + + %Gradient w.r.t V(m,d) + function dqdelta_t = dQDelta(V, t, n, d, m) + + dqdelta_t = -2 * dDelta(V,t,n,d,m) * Delta(V,t,n,d) * exp (-Delta(V,t,n,d)^2); + + end + + + + +%----------------------------------------------------% +%----------------------------------------------------% +% Partial Functions % +%----------------------------------------------------% +%----------------------------------------------------% + + + %Signal component due to the 'j'th response harmonic from a point 't' along the strand that shows up in + % the 'i'th DW-sample orientation, at a voxel 'n', displaced along dimension 'd' + function q = Q(V,t,j,i,n,d) + + q = R(j) * ConvScalar * QRho(V,t,i) * QZeta(V,t) * QDelta(V,t,n,d); + + end + + %Gradient w.r.t V(m,d) + function q = dQ(V,t,j,i,n,d,m) + + q = R(j) * ConvScalar * (dQRho(V,t,i,d,m) * QZeta(V,t) * QDelta(V,t,n,d) + QRho(V,t,i) * dQZeta(V,t,d,m) * QDelta(V,t,n,d) + QRho(V,t,i) * QZeta(V,t) * dQDelta(V,t,n,d,m)); + + end + + + %Signal component due to the 'j'th response harmonic from a point 't' along the strand that shows up in + % the 'i'th DW-sample orientation, at a voxel 'n', displaced along dimension 'd' + function q = seg_signal(V,t,j,i) + + + q = R(j) * QRho(V,t,i) * QZeta(V,t); + + end + + %Gradient w.r.t V(m,d) + function q = seq_gradient(V,t,j,i,n,d,m) + + q = dQRho(V,t,i,d,m) ;%* QZeta(V,t);%R(j) * ... + QRho(V,t,i) * dQZeta(V,t,d,m)); + + end + + + +%----------------------------------------------------% +%----------------------------------------------------% +% Partial Functions % +%----------------------------------------------------% +%----------------------------------------------------% + + + + +% function q_complete = Q_complete(V,i,n) +% +% q_complete = 0; +% +% for t = 1:T +% +% for j = 0:1:(size(Resp,1)-1) +% +% for d = 1:3 +% +% q_complete = q_complete + Q(V,t,j,i,n,d); +% +% end +% +% end +% +% end +% +% +% end +% +% +% function dq_complete = dQ_complete(V,i,n) +% +% dq_complete = zeros(size(V)); +% +% for m = 1:size(V,1) +% +% for d = 1:3 +% +% for t = 1:T +% +% for j = 0:1:(size(Resp,1)-1) +% +% dq_complete(m,d) = dq_complete(m,d) + dQ(V,t,j,i,n,d,m); +% +% end +% +% end +% +% end +% +% end +% +% end + +%----------------------------------------------------% +%----------------------------------------------------% +% Validation % +%----------------------------------------------------% +%----------------------------------------------------% + +% %small increment + h = 0.000001; + + + %Strand Fourier Descriptor (Chung, 2008) coefficients + V_INIT = [ -0.00957484, -0.00342075, -0.02118;... + -0.209237, 0.0614428, -0.0497531;... + 0.00225339, 0.00672736, 0.0199366 ] + + + + M = size(V_INIT,1) +% +% Q_complete_ = Q_complete(V_INIT,i,n) +% +% dQ_complete_ref = zeros(M,3); +% +% for m = 1:M +% for d = 1:3 +% +% Vh = V_INIT; +% Vh(m,d) = Vh(m,d) + h; +% +% dQ_complete_ref(m,d) = (Q_complete(Vh,i,n) - Q_complete(V_INIT,i,n))/h; +% +% end +% end +% +% dQ_complete_ref +% +% dQ_complete_ = dQ_complete(V_INIT,i,n) + + + + H = zeros(D,3); + H(m,d) = h; + Vh = V_INIT + H + + +disp('-------------- Response coeff ------------'); + + R(j) + +disp('-------------- Segment -----------------'); + + Lambda_Vt = Lambda(V_INIT,t) + + GLambda_Vt = GLambda(V_INIT,t) + + + +disp('------------- Complete Function ------------------'); + +% Evaluation of the signal component. + Q_Vtjind = Q(V_INIT,t,j,i,n,d) + +% Evalutation of the estimated gradient. + dQ_Vtjindm_ref = ( Q(Vh,t,j,i,n,d) - Q(V_INIT,t,j,i,n,d))/h + + +% Evaluation of the calculated gradient. + dQ_Vtjindm = dQ(V_INIT,t,j,i,n,d,m) + +disp('--------------- Rho ----------------'); + +% %Evaluation of the calculated gradient. + Rho_Vti = Rho(V_INIT,t,i) + + +% %Evalutation of the estimated gradient. +% dRho_Vtindm_ref = ( Rho(Vh,t,i) - Rho(V_INIT,t,i))/h + +% %Evaluation of the calculated gradient. + dRho_Vtindm = dRho(V_INIT,t,i,d,m) + + +disp('--------------- Zeta ----------------'); + + Zeta_Vt = Zeta(V_INIT,t) + +% %Evalutation of the estimated gradient. +% dZeta_Vt_ref = ( Zeta(Vh,t) - Zeta(V_INIT,t))/h +% +% %Evaluation of the calculated gradient. + dZeta_Vtdm = dZeta(V_INIT,t,d,m) +% + +disp('--------------- Delta ----------------'); + +% %Evalutation of the estimated gradient. +% dDelta_Vtnd_ref = ( Delta(Vh,t,n,d) - Delta(V_INIT,t,n,d))/h +% +% %Evaluation of the calculated gradient. + dDelta_Vtndm = dDelta(V_INIT,t,n,d,m) + +disp('--------------- Q Rho ----------------'); + + QRho_Vti = QRho(V_INIT, t,i) + +% %Evaluation of the calculated gradient. + dQRho_Vtindm = dQRho(V_INIT,t,i,d,m) + +disp('-------------- QZeta -----------------'); + + QZeta_Vt = QZeta(V_INIT,t) + +% %Evaluation of the calculated gradient. + dQZeta_Vtdm = dQZeta(V_INIT,t,d,m) + + +disp('-------------- Segment Gradient (minus interpolation)-----------'); + + seg_signal_Vtji = seg_signal(V_INIT,t,j,i) + + seg_gradient_Vtjindm = seq_gradient(V_INIT,t,j,i,n,d,m) + + seg_gradient_Vtjindm_ref = (seg_signal(Vh,t,j,i) - seg_signal(V_INIT,t,j,i))/h + + +end + diff --git a/matlab/imaging_gradient_demo.m b/matlab/imaging_gradient_demo.m new file mode 100644 index 0000000..0fbd889 --- /dev/null +++ b/matlab/imaging_gradient_demo.m @@ -0,0 +1,37 @@ +close all; + +N = 100; +sigma = 0.05 * N; + + +kernel_extent = 3; + +kernel_size = ceil(sigma * kernel_extent) + +gauss_kernel = zeros(2 * kernel_size + 1); + +for i = 1:size(gauss_kernel,1) + + ker_t = kernel_extent * (i - kernel_size - 1)/kernel_size; + + gauss_kernel(i) = 1/(sigma * sqrt(2) * pi ) * exp(- ker_t^2/(2 * sigma^2)); +end + + +plot(gauss_kernel); + +return; + +initial = [0:1/(N-1):1]; +final = [1:-1/(N-1):0]; + +% G = repmat(row, M, 1); + + +imagesc(initial); +colormap('gray'); +figure; +imagesc(final); +colormap('gray'); + + diff --git a/matlab/interp_integration.m b/matlab/interp_integration.m new file mode 100644 index 0000000..54f66ca --- /dev/null +++ b/matlab/interp_integration.m @@ -0,0 +1,41 @@ +%Calculates the integration of the quartic interpolation function +% x^4 - 2 x^2 + 1, over the interval a to b. + +full = 0 + +if full + syms x_1 p_1 m_1 x_2 p_2 m_2 x_3 p_3 m_3 t + + f = ((x_1 - (p_1 + m_1 * t)) ^ 4 - 2 * (x_1 - (p_1 + m_1 * t)) ^ 2 + 1) * ... + ((x_2 - (p_2 + m_2 * t)) ^ 4 - 2 * (x_2 - (p_2 + m_2 * t)) ^ 2 + 1) * ... + ((x_3 - (p_3 + m_3 * t)) ^ 4 - 2 * (x_3 - (p_3 + m_3 * t)) ^ 2 + 1); + + f_part = ((x_1 - (p_1 + m_1 * t)) ^ 4 - 2 * (x_1 - (p_1 + m_1 * t)) ^ 2 + 1); + + disp('f = '); + + pretty(f); + + f_int = int(f, t); + + % pretty(f_int); + + % disp('f_int_simplify = '); + % + f_int = simplify(f_int); + % + % pretty(f_int); +else + + syms a_1 b_1 c_1 d_1 e_1 a_2 b_2 c_2 d_2 e_2 a_3 b_3 c_3 d_3 e_3 t + + f = (a_1 * t^4 + b_1 * t^3 + c_1 * t^2 + d_1 * t + e_1) *... + (a_2 * t^4 + b_2 * t^3 + c_2 * t^2 + d_2 * t + e_2) *... + (a_3 * t^4 + b_3 * t^3 + c_3 * t^2 + d_3 * t + e_3); + + pretty(f); + + f = collect(expand(f),t) + + +end diff --git a/matlab/legendre_coefficients.m b/matlab/legendre_coefficients.m new file mode 100644 index 0000000..ba72f00 --- /dev/null +++ b/matlab/legendre_coefficients.m @@ -0,0 +1,31 @@ +function get_response_coeffs(R) +%Takes a vector of spherical harmonic coefficients (R) from a given response +%function and calculates the corresponding coefficients for the polynomial +%expansion used in the calculation of the instantaneous signal intensity. + +R = [1 1 1 1 1]; + +if (length(R) > 5) + error('Sorry only polynomials up to order 4 have been calculated.'); +end + +p{1} = [0 0 0 0 1]; %0th order Legendre polynomial +p{2} = 1/2 * [0 0 0 3 -1]; %2nd order Legendre polynomial +p{3} = 1/8 * [0 0 35 -30 3]; %4th order Legendre polynomial +p{4} = 1/16 * [0 231 -315 105 -5]; %6th order Legendre polynomial +p{5} = 1/128 * [6435 -12012 6930 -1260 35]; %8th order Legendre polynomial + + +for (i = 1:size(p,1)) + P = [P;p{1}]; +end +%[p0;p2;p4;p6;p8]; + +P = P * sqrt((4 * size(P,1)+1)/2); + +P = P * diag(R); + +q = sum(P)' + + + diff --git a/matlab/lhist.m b/matlab/lhist.m new file mode 100644 index 0000000..c21100e --- /dev/null +++ b/matlab/lhist.m @@ -0,0 +1,8 @@ +function histo = lhist(gamma, mean, num_samples, range, bins) + +samples = tan(pi*(rand(num_samples,1)-0.5)) * gamma + mean; + +samples = samples(find(abs(samples-mean) < range)); + +histo = hist(samples, [-range:2*range/bins:range]); + diff --git a/matlab/load_extended_props.m b/matlab/load_extended_props.m new file mode 100644 index 0000000..1f4ac8e --- /dev/null +++ b/matlab/load_extended_props.m @@ -0,0 +1,32 @@ +function [keys, values] = load_extend_elem_props(location) + + keys = cell(0); + values = []; + + if exist(location) + + ext_file = fopen(location, 'r'); + header_line = fgetl(ext_file); + fclose(ext_file); + + %Seperate the header tag from the key list. + [header, key_string] = strtok(header_line,':'); + + if ~strcmp(header, '%%% Extended Properties File %%% - keys') + error(['Extended properties header tag ''%%% Extended Properties File %%% - keys'' was not found at start of extended properties file ''' location '']); + end + + %String ': ' from start of keys and trailing tab from end. + key_string = deblank(key_string(3:end)); + keys = cell(0); + + while ~isempty(key_string) + [keys{end+1}, key_string] = strtok(key_string); + + end + + values = load(location); + + end + +end \ No newline at end of file diff --git a/matlab/load_image.m b/matlab/load_image.m new file mode 100644 index 0000000..c267afe --- /dev/null +++ b/matlab/load_image.m @@ -0,0 +1,134 @@ +function image = load_image (filename) + +% function: image = load_image (filename) +% +% returns a structure containing the header information and data for the MRtrix +% format image 'filename' (i.e. files with the extension '.mif' or '.mih'). + +image.comments = {}; + +f = fopen (filename, 'r'); +if (f<1) + disp (['could not open file ' filename ]); + return +end +L = fgetl(f); +if ~strncmp(L, 'mrtrix image', 12) + fclose(f); + disp ([filename ' is not in MRtrix format']); + return +end + +transform = []; +DW_scheme = []; + +while 1 + L = fgetl(f); + if ~ischar(L), break, end; + L = strtrim(L); + if strcmp(L, 'END'), break, end; + d = strfind (L,':'); + if isempty(d) + disp (['invalid line in header: ''' L ''' - ignored']); + else + key = lower(strtrim(L(1:d(1)-1))); + value = strtrim(L(d(1)+1:end)); + if strcmp(key, 'dim') + image.dim = str2num(char(split_strings (value, ',')))'; + elseif strcmp(key, 'vox') + image.vox = str2num(char(split_strings (value, ',')))'; + elseif strcmp(key, 'dw_scheme') + DW_scheme(end+1,:) = str2num(char(split_strings (value, ',')))'; + elseif strcmp(key, 'transform') + transform(end+1,:) = str2num(char(split_strings (value, ',')))'; + elseif strcmp(key, 'comments') + image.comments{end+1} = value; + elseif strcmp(key, 'labels') + image.labels = split_strings (value, '\'); + elseif strcmp(key, 'units') + image.units = split_strings (value, '\'); + elseif strcmp(key, 'file') + file = value; + + elseif strcmp(key, 'img_dims') %do nothing; + elseif strcmp(key, 'img_vox_lengths') %do nothing; + elseif strcmp(key, 'diff_encodings') %do nothing; + elseif strcmp(key, 'img_offsets') %do nothing; % image.offset = value; + else + key = strrep(key, ' ', '_'); + eval(['image.' key ' = value;']); + end + end +end +fclose(f); + + +if ~isempty(transform) + image.transform = transform; + image.transform(4,:) = [ 0 0 0 1 ]; +end + +if ~isempty(DW_scheme) + image.DW_scheme = DW_scheme; +end + +if ~isfield (image, 'dim') || ~exist ('file') || ... + ~isfield (image, 'layout') || ~isfield (image, 'datatype') + disp ('critical entries missing in header - not reading data') + return +end + +layout = split_strings(image.layout, ','); +order = (abs(str2num (char(layout)))+1)'; + +[ file, offset ] = strtok(file); +if isempty(offset), offset = 0; else offset = str2num(char(offset)); end +[f,g] = fileparts(filename); +if strcmp(file,'.'), file = filename; else file = fullfile (f, file); end + +datatype = lower(image.datatype); +byteorder = datatype(end-1:end); + +if strcmp(byteorder, 'le') + f = fopen (file, 'r', 'l'); + datatype = datatype(1:end-2); +elseif strcmp(byteorder, 'be') + f = fopen (file, 'r', 'b'); + datatype = datatype(1:end-2); +else + if strcmp(datatype, 'bit') + datatype = 'bit1'; + f = fopen(file, 'r', 'b'); + else + f = fopen(file, 'r'); + end +end + +if (f<1) + disp (['error opening ' filename ]); + return +end + +fseek (f, offset, -1); +image.data = fread (f, inf, datatype); +fclose (f); + +order(order)= 1:size(order,2); +image.data = reshape (image.data, image.dim(order)); +image.data = ipermute (image.data, order); +for i=1:size(order,2) + if layout{i}(1) == '-' + image.data = flipdim(image.data, i); + end +end + + + + +function S = split_strings (V, delim) + S = {}; + while size(V,2) > 0 + [R, V] = strtok(V,delim); + S{end+1} = R; + end + diff --git a/matlab/load_param_evolution.m b/matlab/load_param_evolution.m new file mode 100644 index 0000000..f43406f --- /dev/null +++ b/matlab/load_param_evolution.m @@ -0,0 +1,72 @@ +function params_evolution = load_param_evolution(dir_name, strand_i, degree_i, dim_i) + + if (dim_i > 2) + error('dim_i (4th argument) cannot be larger than 2'); + end + + + strand_i = strand_i + 1; + degree_i = degree_i + 1; + dim_i = dim_i + 1; + + + + files = dir(dir_name)'; %' + + if (size(files,2) == 0) + error(['Could not load any strands from directory ' dirname ]); + end + + sample_files = cell(0); + + for file = files + + if (~file.isdir) + + if (match_file_ext(file.name, 'frr' )) + + delimeters = [strfind(file.name, '_') strfind(file.name, '.frr')]; + + if (length(delimeters) == 2 && strmatch(file.name(1:delimeters(1)), 'sample_')) + sample_files{end+1} = file.name((delimeters(1)+1):(delimeters(2)-1)); %#ok + end + + end + end + end + + + sample_files = sort(sample_files)'; + + num_samples = size(sample_files,1); + + path = [ dir_name filesep 'sample_' sample_files{1} '.frr' ]; + + fouriers = load_strands(path); + + num_strands = size(fouriers,1); + degree = size(fouriers{1,1},1); + + params_evolution = zeros(num_samples,1); + + + for sample_i = 1:num_samples + + path = [dir_name, filesep, 'sample_', sample_files{sample_i}, '.frr']; + + fouriers = load_strands(path); + + fourier = fouriers{strand_i}; + + params_evolution(sample_i) = fourier(degree_i, dim_i); + + + end + + + plot(params_evolution); + title([ dir_name, ': strand ', num2str(strand_i), ', degree ', num2str(degree_i), ', dim ', num2str(dim_i) ]); + + +end + diff --git a/matlab/load_strand_sections.m b/matlab/load_strand_sections.m new file mode 100644 index 0000000..ebbe6c8 --- /dev/null +++ b/matlab/load_strand_sections.m @@ -0,0 +1,21 @@ +function [sections, prop_keys, prop_values] = load_strand_sections(filename) + + sections = parse_strand_sections(read_fibres(filename)); + + if exist([filename 'x'], 'file') + + [prop_keys, prop_values] = read_element_properties([filename 'x']); + + if size(prop_values,1) ~= size(sections,1) + error (['Number of loaded property values (' num2str(size(prop_values,1)) ') does not match number of loaded segments (' num2str(size(sections,1)) ').']); + end + + else + + prop_keys = []; + prop_values = []; + + end + + +end \ No newline at end of file diff --git a/matlab/load_strand_sets.m b/matlab/load_strand_sets.m new file mode 100644 index 0000000..f9d5ea8 --- /dev/null +++ b/matlab/load_strand_sets.m @@ -0,0 +1,55 @@ +function [strand_sets, props, set_prop_keys, set_prop_values, elem_prop_keys, elem_prop_values] = load_strand_sets(filename, include, load_ext_props) + + if ~exist('include') + include = []; + end + + if ~exist('load_ext_props') + load_ext_props = false; + end + + [elems, props] = read_fibres(filename); + + sets = split_at_file_seperator(elems, [-inf,nan,inf]); + + num_sets = length(sets); + + + if isempty(include) + include = 1:num_sets; + num_include = num_sets; + else + num_include = size(include(:),1); + end + + strand_sets = cell(num_include,1); + + for set_i = include + strand_sets{set_i} = parse_strands(sets{set_i}); + end + + if load_ext_props && exist([filename 'x']) + [set_prop_keys, set_prop_values] = read_element_properties([filename 'x']); + set_prop_values = set_prop_values(include',:); + + else + + set_prop_keys = cell(0); + set_prop_values = cell(0); + + + end + + + if load_ext_props && exist([filename 'xx']) + [elem_prop_keys, elem_prop_values] = read_set_element_properties([filename 'xx']); + elem_prop_values = elem_prop_values(include',:); + + else + + elem_prop_keys = cell(0); + elem_prop_values = cell(0); + + end + +end \ No newline at end of file diff --git a/matlab/load_strands.m b/matlab/load_strands.m new file mode 100644 index 0000000..0745d60 --- /dev/null +++ b/matlab/load_strands.m @@ -0,0 +1,20 @@ +function [strands, props, prop_keys, prop_values] = load_strands(filename) + + [elems, props] = read_fibres(filename); + + strands = parse_strands(elems); + + if exist([filename 'x']) == 2 + [prop_keys, prop_values] = read_element_properties([filename 'x']); + else + prop_keys = cell(0); + prop_values = cell(0); + end + + + if (size(prop_values,1) ~= size(strands,1)) && size(prop_values,1) ~= 0 + error (['Number of loaded property values (' num2str(size(prop_values,1)) ') does not match number of loaded strands (' num2str(size(strands,1)) ').']); + end + + +end \ No newline at end of file diff --git a/matlab/load_tck_sets.m b/matlab/load_tck_sets.m new file mode 100644 index 0000000..69ed5d0 --- /dev/null +++ b/matlab/load_tck_sets.m @@ -0,0 +1,55 @@ +function [tck_sets, props, set_prop_keys, set_prop_values, elem_prop_keys, elem_prop_values] = load_tck_sets(filename, include, load_ext_props) + + if ~exist('include') + include = []; + end + + if ~exist('load_ext_props') + load_ext_props = false; + end + + [elems, props] = read_fibres(filename); + + sets = split_at_file_seperator(elems, [-inf,nan,inf]); + + num_sets = length(sets); + + + if isempty(include) + include = 1:num_sets; + num_include = num_sets; + else + num_include = size(include(:),1); + end + + tck_sets = cell(num_include,1); + + for set_i = include + tck_sets{set_i} = parse_tcks(sets{set_i}); + end + + if load_ext_props && exist([filename 'x']) + [set_prop_keys, set_prop_values] = read_element_properties([filename 'x']); + set_prop_values = set_prop_values(include',:); + + else + + set_prop_keys = cell(0); + set_prop_values = cell(0); + + + end + + + if load_ext_props && exist([filename 'xx']) + [elem_prop_keys, elem_prop_values] = read_set_element_properties([filename 'xx']); + elem_prop_values = elem_prop_values(include',:); + + else + + elem_prop_keys = cell(0); + elem_prop_values = cell(0); + + end + +end \ No newline at end of file diff --git a/matlab/load_tcks.m b/matlab/load_tcks.m new file mode 100644 index 0000000..be714c8 --- /dev/null +++ b/matlab/load_tcks.m @@ -0,0 +1,20 @@ +function [tcks, props, prop_keys, prop_values] = load_tcks(filename) + + [elems, props] = read_fibres(filename); + + tcks = parse_strands(elems); + + if exist([filename 'x']) == 2 + [prop_keys, prop_values] = read_element_properties([filename 'x']); + else + prop_keys = cell(0); + prop_values = cell(0); + end + + + if (size(prop_values,1) ~= size(tcks,1)) && size(prop_values,1) ~= 0 + error (['Number of loaded property values (' num2str(size(prop_values,1)) ') does not match number of loaded tracks (' num2str(size(tcks,1)) ').']); + end + + +end \ No newline at end of file diff --git a/matlab/load_tensor.m b/matlab/load_tensor.m new file mode 100644 index 0000000..b48ac1d --- /dev/null +++ b/matlab/load_tensor.m @@ -0,0 +1,49 @@ +function [tensor_matrix, labels] = load_tensor(filename) + + file = fopen(filename, 'r'); + + if (file == -1) + error([ 'Could not open file ' filename '!' ]); + end + + header_line = fgetl(file); + + fclose(file); + + %Seperate the header tag from the key list. + [preamble, header] = strtok(header_line,':'); + + if ~strcmp(preamble, '%%% Keys %%%') + error(['Did not find tensor preamble at location ''' filename '']); + end + + header = deblank(header(2:end)); + + if isempty(header) + error('No keys found in tensor file.'); + elseif isempty(regexp(header,' ', 'once')) + labels{1} = line; + else + labels = regexp(header,' ','split'); + end + + tensor_matrix = load(filename)'; + + num_elements = size(tensor_matrix,1); + + num_objects = size(tensor_matrix,2)/num_elements; + + + if num_objects == 0 + error('No elements loaded from file.') + elseif floor(num_objects) ~= num_objects + error(['Number of elements (' num2str(num_elements) ') does not divide into number of rows (' num2str(size(tensor_matrix,2)) ').']); + end + + if num_elements ~= length(labels) + error(['Number of elements (' num2str(num_elements) ') does not match number of labels (' num2str(length(labels)) ').']); + end + + tensor_matrix = reshape(tensor_matrix, num_elements, num_elements, num_objects); + +end \ No newline at end of file diff --git a/matlab/load_tract_sections.m b/matlab/load_tract_sections.m new file mode 100644 index 0000000..03fabd7 --- /dev/null +++ b/matlab/load_tract_sections.m @@ -0,0 +1,13 @@ +function [sections, prop_keys, prop_values] = load_tract_sections(filename) + + sections = parse_tract_sections(read_fibres(filename)); + + + [prop_keys, prop_values] = read_element_properties([filename 'x']); + + if size(prop_values,1) ~= size(sections,1) + error (['Number of loaded property values (' num2str(size(prop_values,1)) ') does not match number of loaded segments (' num2str(size(sections,1)) ').']); + end + + +end \ No newline at end of file diff --git a/matlab/load_tract_sets.m b/matlab/load_tract_sets.m new file mode 100644 index 0000000..e42c678 --- /dev/null +++ b/matlab/load_tract_sets.m @@ -0,0 +1,29 @@ +function [tract_sets, properties, set_prop_keys, set_prop_values, elem_prop_keys, elem_prop_values] = load_tract_sets(filename, set_indices) + + [elems, properties] = read_fibres(filename); + + sets = split_at_file_seperator(elems, [-inf,nan,inf]); + + num_sets = length(sets); + + tract_sets = cell(num_sets,1); + + for set_i =1:num_sets + tract_sets{set_i} = parse_tracts(sets{set_i}); + end + + if exist([filename 'x'],'file') + [set_prop_keys, set_prop_values] = read_element_properties([filename 'x']); + else + set_prop_keys = []; + set_prop_values = []; + end + + if exist([filename 'xx'], 'file') + [elem_prop_keys, elem_prop_values] = read_set_element_properties([filename 'xx']); + else + elem_prop_keys = []; + elem_prop_values = cell(num_sets,1); + end + +end \ No newline at end of file diff --git a/matlab/load_tracts.m b/matlab/load_tracts.m new file mode 100644 index 0000000..39f8cb8 --- /dev/null +++ b/matlab/load_tracts.m @@ -0,0 +1,20 @@ +function [tracts, props, prop_keys, prop_values] = load_tracts(filename) + + [elems, props] = read_fibres(filename); + + tracts = parse_tracts(elems); + + if exist([filename 'x']) == 2 + [prop_keys, prop_values] = read_element_properties([filename 'x']); + + if size(prop_values,1) ~= size(tracts,1) + error (['Number of loaded property values (' num2str(size(prop_values,1)) ') does not match number of loaded tracts (' num2str(size(tracts,1)) ').']); + end + + else + prop_keys = cell(0); + prop_values = cell(0); + end + +end + diff --git a/matlab/load_triples.m b/matlab/load_triples.m new file mode 100644 index 0000000..02bea5a --- /dev/null +++ b/matlab/load_triples.m @@ -0,0 +1,5 @@ +function triples = load_triples(filename) + + triples = load(filename); + +end \ No newline at end of file diff --git a/matlab/load_unzip_image.m b/matlab/load_unzip_image.m new file mode 100644 index 0000000..c11a068 --- /dev/null +++ b/matlab/load_unzip_image.m @@ -0,0 +1,8 @@ +function [image_matrix, labels] = load_unzip_image(filename) + + image = read_image(filename); + + image_matrix = image.data(:)'; + labels{1} = 'All Voxel Directions'; + +end \ No newline at end of file diff --git a/matlab/load_unzip_mcmc.m b/matlab/load_unzip_mcmc.m new file mode 100644 index 0000000..2bb4c3a --- /dev/null +++ b/matlab/load_unzip_mcmc.m @@ -0,0 +1,11 @@ +function [mcmc_matrix, labels] = load_unzip_mcmc_state(filename) + + triples_matrix = load_triples(filename)'; + + labels = cell(3,1); + + labels{1} = 'Dim 0'; + labels{2} = 'Dim 1'; + labels{3} = 'Dim 2'; + +end \ No newline at end of file diff --git a/matlab/load_unzip_mcmc_state.m b/matlab/load_unzip_mcmc_state.m new file mode 100644 index 0000000..bb24c22 --- /dev/null +++ b/matlab/load_unzip_mcmc_state.m @@ -0,0 +1,13 @@ +function [mcmc_state_matrix, labels] = load_unzip_mcmc_state(filename) + + mcmc_state_matrix = load(filename)'; + + num_elems = size(mcmc_state_matrix,1); + + labels = cell(num_elems,1); + + for state_i = 1:num_elems + labels{state_i} = ['Elem ' num2str(state_i)]; + end + +end \ No newline at end of file diff --git a/matlab/load_unzip_strand_sections.m b/matlab/load_unzip_strand_sections.m new file mode 100644 index 0000000..2aed62c --- /dev/null +++ b/matlab/load_unzip_strand_sections.m @@ -0,0 +1,6 @@ +function [section_matrix, labels] = load_unzip_strand_sections(filename) + + [sections, prop_keys, prop_values] = load_strand_sections(filename); + [section_matrix, labels] = unzip_strand_sections(sections, prop_keys, prop_values); + +end \ No newline at end of file diff --git a/matlab/load_unzip_strand_sets.m b/matlab/load_unzip_strand_sets.m new file mode 100644 index 0000000..0254713 --- /dev/null +++ b/matlab/load_unzip_strand_sets.m @@ -0,0 +1,6 @@ +function [strand_sets_matrix, labels] = load_unzip_strand_sets(filename) + + [strand_sets, ~, set_prop_keys, set_prop_values, elem_prop_keys, elem_prop_values] = load_strand_sets(filename); + [strand_sets_matrix, labels] = unzip_strand_sets(strand_sets, set_prop_keys, set_prop_values, elem_prop_keys, elem_prop_values); + +end \ No newline at end of file diff --git a/matlab/load_unzip_strands.m b/matlab/load_unzip_strands.m new file mode 100644 index 0000000..38ecead --- /dev/null +++ b/matlab/load_unzip_strands.m @@ -0,0 +1,6 @@ +function [strand_matrix, labels] = load_unzip_strands(filename) + + [strands, props, prop_keys, prop_values] = load_strands(filename); + [strand_matrix, labels] = unzip_strands(strands, prop_keys, prop_values); + +end \ No newline at end of file diff --git a/matlab/load_unzip_tensor.m b/matlab/load_unzip_tensor.m new file mode 100644 index 0000000..3344eb0 --- /dev/null +++ b/matlab/load_unzip_tensor.m @@ -0,0 +1,7 @@ +function [tensor_matrix, labels] = load_unzip_tensor(filename) + + [tensor_array, row_labels] = load_tensor(filename); + + [tensor_matrix, labels] = unzip_tensor(tensor_array, row_labels); + +end \ No newline at end of file diff --git a/matlab/load_unzip_tract_sections.m b/matlab/load_unzip_tract_sections.m new file mode 100644 index 0000000..251ecd0 --- /dev/null +++ b/matlab/load_unzip_tract_sections.m @@ -0,0 +1,6 @@ +function [section_matrix, labels] = load_unzip_tract_sections(filename) + + [sections, prop_keys, prop_values] = load_tract_sections(filename); + [section_matrix, labels] = unzip_tract_sections(sections, prop_keys, prop_values); + +end \ No newline at end of file diff --git a/matlab/load_unzip_tract_sets.m b/matlab/load_unzip_tract_sets.m new file mode 100644 index 0000000..9ab0fd2 --- /dev/null +++ b/matlab/load_unzip_tract_sets.m @@ -0,0 +1,6 @@ +function [tract_sets_matrix, labels] = load_unzip_tract_sets(filename) + + [tract_sets, ~, set_prop_keys, set_prop_values, elem_prop_keys, elem_prop_values] = load_tract_sets(filename); + [tract_sets_matrix, labels] = unzip_tract_sets(tract_sets, set_prop_keys, set_prop_values, elem_prop_keys, elem_prop_values); + +end \ No newline at end of file diff --git a/matlab/load_unzip_tracts.m b/matlab/load_unzip_tracts.m new file mode 100644 index 0000000..382f8c7 --- /dev/null +++ b/matlab/load_unzip_tracts.m @@ -0,0 +1,6 @@ +function [tract_matrix, labels] = load_unzip_tracts(filename) + + [tracts, props, prop_keys, prop_values] = load_tracts(filename); + [tract_matrix, labels] = unzip_tracts(tracts, prop_keys, prop_values); + +end \ No newline at end of file diff --git a/matlab/load_unzip_triples.m b/matlab/load_unzip_triples.m new file mode 100644 index 0000000..890a5b3 --- /dev/null +++ b/matlab/load_unzip_triples.m @@ -0,0 +1,11 @@ +function [triples_matrix, labels] = load_unzip_triples(filename) + + triples_matrix = load_triples(filename)'; + + labels = cell(3,1); + + labels{1} = 'Dim 0'; + labels{2} = 'Dim 1'; + labels{3} = 'Dim 2'; + +end \ No newline at end of file diff --git a/matlab/nfg_strands_format.m b/matlab/nfg_strands_format.m new file mode 100644 index 0000000..538de40 --- /dev/null +++ b/matlab/nfg_strands_format.m @@ -0,0 +1,68 @@ +function nfg_strands = nfg_strands_format(strands, prop_keys, prop_values, filename, varargin) + + if (nargin > 6) + error(['Incorrect number of arguments ' nargin ' expecting no more than 4']); + end + + if (nargin >= 5) + num_points = varargin{1}; + else + num_points = 100; + end + + if (nargin == 6) + strand_radius = varargin{2}; + else + strand_radius = []; + end + + already_track = strcmp(file_extension(filename),'tck'); + + strand_radius_key_i = strmatch('track_radius', prop_keys, 'exact'); + bundle_index_key_i = strmatch('bundle_index', prop_keys, 'exact'); + + + num_strands = size(strands,1); + + nfg_strands = cell(num_strands, 4); + + strand_indices = [1:num_strands]'; + + if ~isempty(strand_radius) + + strand_radii = ones(num_strands,1) * strand_radius; + + else + + if isempty(strand_radius_key_i) + error(['No strand radii loaded from extended properties, so strand radius must be provided']); + end + for strand_i = 1:num_strands + strand_radii(strand_i) = str2num(prop_values{strand_i,strand_radius_key_i}); + end + end + + if ~isempty(bundle_index_key_i) + for strand_i = 1:num_strands + bundle_indices(strand_i) = str2num(prop_values{strand_i,bundle_index_key_i}); + end + else + bundle_indices = strand_indices; + end + + + for strand_i = 1:num_strands + + if ~already_track + nfg_strands{strand_i,1} = fourier2tck(strands{strand_i}); + else + nfg_strands{strand_i,1} = strands{strand_i}; + end + nfg_strands{strand_i,2} = strand_indices(strand_i); + nfg_strands{strand_i,3} = strand_radii(strand_i); + nfg_strands{strand_i,4} = bundle_indices(strand_i); + end + + nfg_strands{end+1,1} = strrep(filename, '_', ' '); + +end \ No newline at end of file diff --git a/matlab/old/bacth_curve_prior_est.m b/matlab/old/bacth_curve_prior_est.m new file mode 100644 index 0000000..1548666 --- /dev/null +++ b/matlab/old/bacth_curve_prior_est.m @@ -0,0 +1,41 @@ +function batch_curve_prior_est(dirname) +% function batch_curve_prior_est(collection_name) +% +% Estimates the prior distribution of Fourier coefficients for a given phantom +% collection +% +% +% dirname - directory name of the strand collection + + + collection_names = dir(dirname); + + stats = []; + + if (size(collection_names,1) < 1) + error(['Did not read any collection names from ' dirname]); + else + + for (coll_i =1:size(collection_names,1)) + + collection_name = collection_names(coll_i).name; + + if (collection_name(1,1) ~= '.') + + collection_dir = [dirname '/' collection_name]; + + if (isdir(collection_dir)) + + prior_estimation(collection_dir); + + + end + end + + + end + + end + + +end \ No newline at end of file diff --git a/matlab/old/batch_curve_prior_est.m b/matlab/old/batch_curve_prior_est.m new file mode 100644 index 0000000..df66103 --- /dev/null +++ b/matlab/old/batch_curve_prior_est.m @@ -0,0 +1,41 @@ +function batch_curve_prior_est(dirname) +% function batch_curve_prior_est(dirname) +% +% Estimates the prior distribution of Fourier coefficients for a given phantom +% collection +% +% +% dirname - directory name of the strand collection + + + collection_names = dir(dirname); + + stats = []; + + if (size(collection_names,1) < 1) + error(['Did not read any collection names from ' dirname]); + else + + for (coll_i =1:size(collection_names,1)) + + collection_name = collection_names(coll_i).name; + + if (collection_name(1,1) ~= '.') + + collection_dir = [dirname '/' collection_name]; + + if (isdir(collection_dir)) + + load_fourier_coeff(collection_dir); + + + end + end + + + end + + end + + +end \ No newline at end of file diff --git a/matlab/old/batch_fourier_est.m b/matlab/old/batch_fourier_est.m new file mode 100644 index 0000000..ee2848d --- /dev/null +++ b/matlab/old/batch_fourier_est.m @@ -0,0 +1,42 @@ +function batch_fourier_est(dirname,degree) +% function batch_fourier_est(dirname) +% +% Estimates the prior distribution of Fourier coefficients for a given phantom +% collection +% +% +% dirname - name of directory that holds the strand collections +% degree - Degree of the Fourier descriptors + + + collection_names = dir(dirname); + + stats = []; + + if (size(collection_names,1) < 1) + error(['Did not read any collection names from ' dirname]); + else + + for (coll_i =1:size(collection_names,1)) + + collection_name = collection_names(coll_i).name; + + if (collection_name(1,1) ~= '.') + + collection_dir = [dirname '/' collection_name]; + + if (isdir(collection_dir)) + + load_fourier_coeff(collection_dir,degree); + + + end + end + + + end + + end + + +end \ No newline at end of file diff --git a/matlab/old/f_descript_orig.m b/matlab/old/f_descript_orig.m new file mode 100644 index 0000000..aaae118 --- /dev/null +++ b/matlab/old/f_descript_orig.m @@ -0,0 +1,24 @@ +function samples = f_descript_orig(num_samples, coeff) + +if (size(coeff,2) ~= 3) + error(['The second dimension of the coefficient matrix must be 3, it was ' num2str(size(coeff,2))]); +end + + +k = [1:num_samples]'./num_samples; + +psi = ones(num_samples,1); + +for (degree = [1:(size(coeff,1)-1)]) + + psi = [psi; sqrt(2) * cos (pi * degree *k)]; + +end + + +samples = psi * coeff; + +plot3(samples(:,1), samples(:,2), samples(:,3), 'bx'); + +cameratoolbar('Show'); +cameratoolbar('SetMode','orbit'); diff --git a/matlab/old/fernando_partial_track.m b/matlab/old/fernando_partial_track.m new file mode 100644 index 0000000..16e7b4c --- /dev/null +++ b/matlab/old/fernando_partial_track.m @@ -0,0 +1,82 @@ +% partial_track.m +% Old file: smooth_tracks.m +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% This program reads the TCK file generated with MRTRIX and generates a file with smoothed +% versions of the tracks. +% The smoothing method used is MOVING and the SPAN window must be chosen. +% Modified to read a TCK and generate a new TCK file with part of the tracks +% contained (FC-31/10/08) +% Select: input and output files, Ntracks. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +clear +%%%%%%%%%%%%%%%%% +% Parameters to select +%%%%%%%%%%%%%%%%% +% Ntracks = 10000; % Number of trakcs to be selected from the the TCK input +Ntracks = input('Number of tracks?= '); +%%%%%%%%%%%%%%%%% + +% Select TCK file to be smoothed +[fname,pname] = uigetfile('*.tck','Select TCK file'); +fidtck = fopen([pname fname],'r'); +% fidtck = fopen('/home/fercala/DWI150/150lisa/curvature/20K/wholebrain3.tck','r'); + +% Select OUTPUT file name for the smoothed TCK file +[fname2,pname2] = uiputfile('*.tck','Select OUTPUT file'); +fidout = fopen([pname2 fname2],'w'); +% fidout = fopen('/home/fercala/DWI150/150lisa/curvature/20K/wholebrain3sm.tck','w'); + +% Find file offset +temp ='abcd'; +i=1; +while 1 + temp = fgetl(fidtck); + if strcmp(temp(1:4),'file'); break; end; + i=i+1; +end; +[temp1 offset] = strtok(temp); +[temp1 offset] = strtok(offset); +offset = str2double(offset); + +% Copy header to output file +status1 = fseek(fidtck,0,-1); % rewind file +headerinfo = fread(fidtck,offset); % header info +fwrite(fidout,headerinfo); + +% Find coordinates of tracks (one at a time) +status = fseek(fidtck,offset,-1); + +ptemp = zeros(3,1); +% k = 1; + +% while (~isinf(sum(ptemp))) %repeat until Inf is found (i.e. EOF) +for k=1:Ntracks; + clear p + i=1; + while 1; + ptemp = fread(fidtck,3,'float32','ieee-le'); + if isinf(sum(ptemp)); + fwrite(fidout,ptemp,'float32','ieee-le'); % end file with Inf + fclose(fidout); + break; + elseif ~isfinite(sum(ptemp)); break; + end; + p(i,:) = ptemp; + i = i+1; + end; + if isinf(sum(ptemp)); break; end; +% figure(10), plot3(squeeze(p(:,1)),squeeze(p(:,2)),squeeze(p(:,3)),'-k'), grid on, hold on + fwrite(fidout,p','float32','ieee-le'); + fwrite(fidout,ptemp,'float32','ieee-le'); % add NaN at end of track + +% k=k+1; + disp(k); + +end; % end of TRACKS loop + +fclose('all') + + + + diff --git a/matlab/old/fourier_angles_and_lengths.m b/matlab/old/fourier_angles_and_lengths.m new file mode 100644 index 0000000..dd4f49f --- /dev/null +++ b/matlab/old/fourier_angles_and_lengths.m @@ -0,0 +1,21 @@ +filename = '../chunked_fourier_d4/090403192509-9-8-11.tck' + +strands = load_mrtrix_strands(filename); + +for (strand_i = 1:size(strands,1)) + strand = strands{strand_i,1}; + + f0 = strand(1,:)'; + f1 = strand(2,:)'; + f2 = strand(3,:)'; +% f3 = strand(4,:)'; + +% length_f0 = norm(f0) + length_f1 = norm(f1); + length_f2 = norm(f2); + + ang = 180/pi * acos(dot(f1,f2) / (length_f1 * length_f2)) - 90; + + disp(['f1 length = ' num2str(length_f1) ', f2_length = ' num2str(length_f2) ', f2/f1_length = ' num2str(length_f2/length_f1) ', f1/f2 angle = ' num2str(ang) ]); + +end \ No newline at end of file diff --git a/matlab/old/fourier_prior.m b/matlab/old/fourier_prior.m new file mode 100644 index 0000000..42dedff --- /dev/null +++ b/matlab/old/fourier_prior.m @@ -0,0 +1,32 @@ +function fourier_prior(collection_name,degree) +% function fourier_prior(dirname) +% +% Estimates the prior distribution of Fourier coefficients for a given phantom +% collection +% +% +% collection_name - name of directory that holds the strand collections +% degree - Degree of the Fourier descriptors + + + [coeffs, residuals, num_control_points]= load_fourier_coeff(collection_name, degree); + + num_strands = size(coeffs,3); + + flat_coeffs = reshape(coeffs, degree, (3 * num_strands)); + +% for (degree_i = 1:degree) +% +% figure(degree_i); +% +% hist(flat_coeffs(degree_i,:)') +% title(['Coeff ' num2str(degree_i)]); +% +% end + + figure(degree+1); + hist(residuals); + + + +end \ No newline at end of file diff --git a/matlab/old/fr_descript.m b/matlab/old/fr_descript.m new file mode 100644 index 0000000..eaae121 --- /dev/null +++ b/matlab/old/fr_descript.m @@ -0,0 +1,49 @@ +function samples = fr_descript(num_samples, coeff, varargin) +% samples = fr_descript(num_samples, coeff, [plot_type]) +% +% Args: +% +% samples - the samples, which are plotted +% num_samples - number of samples +% plot_type (optional - passed directly to plot3 (e.g. 'x' plots +% crosses instead of a line) + +if (nargin == 3) + plot_type = varargin{1}; +else + plot_type = '-'; +end + +if (size(coeff,2) ~= 3) + error('The second dimension of the coefficient matrix must be 3'); +end + +degree = size(coeff,1); + +k = [0:1:(num_samples-1)]'./(num_samples-1); + + +theta = 2 * pi * cos(k * pi) ; +phi = pi * cos(2 * k * pi); + +samples = zeros(num_samples,3); + +for (i=2:num_samples) + + samples(i,1) = (cos(theta(i)) + samples(i-1,1)); + samples(i,2) = (sin(theta(i)) + samples(i-1,2)); + samples(i,3) = (sin(phi(i)) + samples(i-1,3)); +end + + + +%figure; +plot3(samples(:,1), samples(:,2), samples(:,3), plot_type); + +cameratoolbar('Show'); +cameratoolbar('SetMode','orbit'); + +coeff +% xlim(plot_limits(1,:)); +% ylim(plot_limits(2,:)); +% zlim(plot_limits(3,:)); \ No newline at end of file diff --git a/matlab/old/mex_load_mrtrix_strands.cpp b/matlab/old/mex_load_mrtrix_strands.cpp new file mode 100644 index 0000000..10e0d49 --- /dev/null +++ b/matlab/old/mex_load_mrtrix_strands.cpp @@ -0,0 +1,116 @@ +/* + * A mex wrapper for the mrtrix load tracks function. + + Can be compiled with the following line: + + mex load_mrtrix_strands.cpp -I/data/home/tclose/Code/Tractography/mrtrix_bundle/src/mrtrix/lib -I/data/home/tclose/Code/Tractography/mrtrix_bundle/include -I/data/home/tclose/Code/Tractography/mrtrix_bundle/src/mrtrix/src -I/data/home/tclose/Code/Tractography/tractography/src -DMACOSX -DBYTE_ORDER_IS_BIG_ENDIAN -DDEBUG_EXTENSIONS + + */ + +#include +#include +#include "mex.h" +#include "app.h" +#include "math/matrix.h" +#include "math/least_squares.h" +#include "point.h" +#include "file/path.h" +#include "progressbar.h" +#include "shared.h" + + + +extern void _main(); + + +static int count_mrtrix_strands(char *filename) { + MR::DWI::Tractography::Properties properties; + std::vector tck; + + MR::DWI::Tractography::Reader reader; + + reader.open(filename, properties); + + int count = 0; + + while (reader.next(tck)) { + + if (tck.size()) { + count++; + + } + + } + + reader.close (); + + return count; +} + + +void mexFunction( + int nlhs, + mxArray *lhs[], + int nrhs, + const mxArray *prhs[] + ) +{ + double *vin1, *vin2; + + /* Check for proper number of arguments */ + + if (nrhs != 1) { + mexErrMsgTxt("MEXCPP requires one input argument (filename)."); + } + + char filename[500]; + + if (mxGetString(prhs[0], filename, 499)) { + mexErrMsgTxt("Input argument was not valid string."); + } + + int strand_count = count_mrtrix_strands(filename); + + lhs[0] = mxCreateCellMatrix(strand_count, 1); + + MR::DWI::Tractography::Properties properties; + std::vector tck; + + MR::DWI::Tractography::Reader reader; + + reader.open(filename, properties); + + int count = 0; + + while (reader.next(tck)) { + + if (tck.size()) { + + mxArray *tck_mxArray = mxCreateDoubleMatrix(3,(tck.size()), mxREAL); + + double *tck_matrix = mxGetPr(tck_mxArray); + + + for (size_t point_i = 0; point_i < tck.size(); point_i++) { + tck_matrix[point_i*3 + X] = tck[point_i][X]; + tck_matrix[point_i*3 + Y] = tck[point_i][Y]; + tck_matrix[point_i*3 + Z] = tck[point_i][Z]; + } + + mxSetCell(lhs[0], count, tck_mxArray); + + count++; + + } + + } + + reader.close (); + + + + + + + return; +} diff --git a/matlab/old/mex_oad_mrtrix_strands.mexmac b/matlab/old/mex_oad_mrtrix_strands.mexmac new file mode 100755 index 0000000..7244baa Binary files /dev/null and b/matlab/old/mex_oad_mrtrix_strands.mexmac differ diff --git a/matlab/old/p.mat b/matlab/old/p.mat new file mode 100644 index 0000000..6cb6943 Binary files /dev/null and b/matlab/old/p.mat differ diff --git a/matlab/old/p2_scheme.mat b/matlab/old/p2_scheme.mat new file mode 100644 index 0000000..d5e0e95 Binary files /dev/null and b/matlab/old/p2_scheme.mat differ diff --git a/matlab/old/plot_centre_voxel.m b/matlab/old/plot_centre_voxel.m new file mode 100644 index 0000000..ca80989 --- /dev/null +++ b/matlab/old/plot_centre_voxel.m @@ -0,0 +1,17 @@ +function centre_voxel = plot_centre_voxel(image_filename) + + load('/data/home/tclose/Code/Tractography/matlab_scripts/grad_scheme'); + load('/data/home/tclose/Code/Tractography/matlab_scripts/p_scheme'); + + + img_struct = read_image(image_filename); + img = img_struct.data; + + centre_voxel = squeeze(img(10,10,10,:)); + sh = amp2SH(centre_voxel, grad_scheme); + + plot_SH(sh, p_scheme); + + daspect([1,1,1]); + +end diff --git a/matlab/old/plot_param_evolution.m b/matlab/old/plot_param_evolution.m new file mode 100644 index 0000000..c4c626c --- /dev/null +++ b/matlab/old/plot_param_evolution.m @@ -0,0 +1,63 @@ +function params_evolution = load_param_evolution(dir_name, strand_i, degree_i, dim_i) + + + files = dir(dir_name)'; %' + + if (size(files,2) == 0) + error(['Could not load any strands from directory ' dirname ]); + end + + sample_files = cell(0); + + for file = files + + if (~file.isdir) + + if (match_file_ext(file.name, 'frr' )) + + delimeters = [strfind(file.name, '_') strfind(file.name, '.frr')]; + + if (length(delimeters) == 2 && strmatch(file.name(1:delimeters(1)), 'sample_')) + sample_files{end+1} = file.name((delimeters(1)+1):(delimeters(2)-1)); %#ok + end + + end + end + end + + + sample_files = sort(sample_files)'; + + num_samples = size(sample_files,1); + + path = [ dir_name filesep 'sample_' sample_files{1} '.frr' ]; + + path + + fouriers = load_strands(path); + + num_strands = size(fouriers,1); + degree = size(fouriers{1,1},1); + + params_evolution = zeros(num_samples); + + + for sample_i = 1:num_samples + + path = [dir_name, filesep, 'sample_', sample_files{sample_i}, '.frr']; + + fouriers = load_strands(path); + + fourier = fouriers{strand_i}; + + params_evolution(sample_i) = fourier(degree_i, dim_i); + + + end + + + plot(params_evolution); + + +end + diff --git a/matlab/old/plot_parameter_evolution.m b/matlab/old/plot_parameter_evolution.m new file mode 100644 index 0000000..a4f3cda --- /dev/null +++ b/matlab/old/plot_parameter_evolution.m @@ -0,0 +1,82 @@ +function params_evolution = load_parameter_evolution(dir_name) + + + files = dir(dir_name)'; %' + + if (size(files,2) == 0) + error(['Could not load any strands from directory ' dirname ]); + end + + sample_files = cell(0); + + for file = files + + if (~file.isdir) + + if (match_file_ext(file.name, 'frr' )) + + delimeters = [strfind(file.name, '_') strfind(file.name, '.frr')]; + + if (length(delimeters) == 2 && strmatch(file.name(1:delimeters(1)), 'sample_')) + sample_files{end+1} = file.name((delimeters(1)+1):(delimeters(2)-1)); %#ok + end + + end + end + end + + sample_files = sample_files'; + + num_samples = size(sample_files,1); + + max_decimal_places = 0; + + for file_i = 1:num_samples + + decimal_places = length(sample_files{file_i}); + + if (decimal_places > max_decimal_places) + + max_decimal_places = decimal_places; + + end + end + + for file_i = 1:num_sample_files + + decimal_places = length(sample_files{file_i}); + + for i = 1:(max_decimal_places - decimal_places + 1) + + sample_files{file_i} = ['0' sample_files{file_i}]; + + end + end + + sample_files = sort(sample_files); + + fouriers = load_strands([dirname filesep 'sample_' sample_files(1) '.frr']); + + num_strands = size(fouriers,1); + degree = size(fouriers{1,1},1); + + params_evolution = zeros(num_samples, num_strands, degree, 3); + + + for sample_i = 1:num_samples + + fouriers = load_strands([dirname filesep 'sample_' sample_files(file_i) '.frr']); + + for (strand_i = 1:num_strands) + + fourier = fouriers{strand_i,1}; + + params_evolution(sample_i, strand_i, :, :) = reshape(fourier, [1 1 size(fourier,1) 3]); + + end + + end + + +end + diff --git a/matlab/old/prior_estimation.m b/matlab/old/prior_estimation.m new file mode 100644 index 0000000..cc47902 --- /dev/null +++ b/matlab/old/prior_estimation.m @@ -0,0 +1,41 @@ +function batch_prior_estimation(dirname) +% function prior_estimation(collection_name) +% +% Estimates the prior distribution of Fourier coefficients for a given phantom +% collection +% +% +% dirname - directory name of the strand collection + + + collection_names = dir(dirname); + + stats = []; + + if (size(collection_names,1) < 1) + error(['Did not read any collection names from ' dirname]); + else + + for (coll_i =1:size(collection_names,1)) + + collection_name = collection_names(coll_i).name; + + if (collection_name(1,1) ~= '.') + + collection_dir = [dirname '/' collection_name]; + + if (isdir(collection_dir)) + + prior_estimation(collection_dir); + + + end + end + + + end + + end + + +end \ No newline at end of file diff --git a/matlab/old2/d_fourier_descr_matrix.m b/matlab/old2/d_fourier_descr_matrix.m new file mode 100644 index 0000000..784c14b --- /dev/null +++ b/matlab/old2/d_fourier_descr_matrix.m @@ -0,0 +1,20 @@ +function d_psi = d_fourier_descr_matrix(num_samples, degree, include_endpoints) + + + if include_endpoints + k = [0:1:(num_samples-1)]'./(num_samples-1); + else + k = [1:num_samples]'./(num_samples+1); + end + + if (degree >= 0) + d_psi = zeros(num_samples,1); + end + + for (d = [1:(degree-1)]) + + d_psi = [d_psi, - d * pi * sqrt(2) * sin(pi * k * d)]; + + end + +end \ No newline at end of file diff --git a/matlab/old2/f_descript.m b/matlab/old2/f_descript.m new file mode 100644 index 0000000..a835dbe --- /dev/null +++ b/matlab/old2/f_descript.m @@ -0,0 +1,82 @@ +function samples = f_descript(num_samples, coeff, varargin) +% samples = f_descript(num_samples, coeff, [plot_type]) +% +% Args: +% +% samples - the samples, which are plotted +% num_samples - number of samples +% plot_type (optional - passed directly to plot3 (e.g. 'x' plots +% crosses instead of a line) + +if (nargin == 3) + plot_type = varargin{1}; +else + plot_type = '-'; +end + +if (size(coeff,2) ~= 3) + error('The second dimension of the coefficient matrix must be 3'); +end + +degree = size(coeff,1); + +k = [0:1:(num_samples-1)]'./(num_samples-1); + + +if (degree >= 0) + psi = ones(num_samples,1); +end + +% start_point = coeff(1,:); +% end_point = coeff(1,:); + +for (d = [1:(degree-1)]) + + psi = [psi, sqrt(2) * cos(pi * k * d)]; + +% start_point = start_point + coeff(d,:); +% end_point = end_point + coeff(d,:) * cos(pi * d); +end + +samples = psi * coeff; + +%sfigure; +plot3(samples(:,1), samples(:,2), samples(:,3), plot_type); + +% = (1,:)' - 1.5 * scalars(2); +% up_lim = c(1,:)' + 1.5 * scalars(2); +% +% xlim([low_lim(1) up_lim(1)]); +% ylim([low_lim(2) up_lim(2)]); +% zlim([low_lim(3) up_lim(3)]); + +cameratoolbar('Show'); +cameratoolbar('SetMode','orbit'); +grid; +xlabel('x'); +ylabel('y'); +zlabel('z'); +coeff +% xlim(plot_limits(1,:)); +% ylim(plot_limits(2,:)); +% zlim(plot_limits(3,:)); + + +function h = sfigure(h) +% SFIGURE Create figure window (minus annoying focus-theft). +% +% Usage is identical to figure. +% +% Daniel Eaton, 2005 +% +% See also figure + +if nargin>=1 + if ishandle(h) + set(0, 'CurrentFigure', h); + else + h = figure(h); + end +else + h = figure; +end \ No newline at end of file diff --git a/matlab/old2/get_m0_coeffs.m b/matlab/old2/get_m0_coeffs.m new file mode 100644 index 0000000..6b0b376 --- /dev/null +++ b/matlab/old2/get_m0_coeffs.m @@ -0,0 +1,24 @@ +function m0 = get_m0_coeffs(SH) + +reshape(SH, length(SH),1); + + +total_index = 0; +i = 0; +indices = []; + +while (total_index < length(SH)) + + + block_size = 2 * i; + + new_index = total_index + block_size + 1; + + + indices = [indices; new_index]; + + total_index = new_index + block_size; + i = i + 1; +end + +m0 = SH(indices); \ No newline at end of file diff --git a/matlab/old2/get_response_coeffs.m b/matlab/old2/get_response_coeffs.m new file mode 100644 index 0000000..ce50dc3 --- /dev/null +++ b/matlab/old2/get_response_coeffs.m @@ -0,0 +1,66 @@ +function q = get_response_coeffs(SH) +%Takes a vector of spherical harmonic coefficients (SH) of a given signal model +%of diffusion and calculates the corresponding coefficients for the polynomial +%expansion used in the calculation of the instantaneous signal intensity. + + R = get_m0_coeffs(SH) + + max_order = 2 * (length(R)-1); + + l = [0:2:max_order]; + + if (max_order > 8) + error(['Sorry only polynomials up to Legendre polynomial order 8 have been calculated (order ' num2str(max_order) ' supplied)']); + end + + P = zeros(5); + + P(1,:) = [ 1 0 0 0 0]; %0th order Associated Legendre polynomial, m=0 + P(2,:) = 1/2 * [-1 3 0 0 0]; %2nd order Associated Legendre polynomial, m=0 + P(3,:) = 1/8 * [ 3 -30 35 0 0]; %4th order Associated Legendre polynomial, m=0 + P(4,:) = 1/16 * [-5 105 -315 231 0]; %6th order Associated Legendre polynomial, m=0 + P(5,:) = 1/128 * [35 -1260 6930 -12012 6435]; %8th order Associated Legendre polynomial, m=0 + + + %Weight the Legendre polynomials by appropriate scaling function for + %spherical harmonics. + + + normalise = diag(sqrt( (2 * l + 1) ./ (4 * pi) )); + + P = normalise * P; + + P = diag(R) * P + + q = sum(P,1)'; + + + +end + + +function m0 = get_m0_coeffs(SH) + + reshape(SH, length(SH),1); + + + total_index = 0; + i = 0; + indices = []; + + while (total_index < length(SH)) + + + block_size = 2 * i; + + new_index = total_index + block_size + 1; + + + indices = [indices; new_index]; + + total_index = new_index + block_size; + i = i + 1; + end + + m0 = SH(indices); +end \ No newline at end of file diff --git a/matlab/old2/inv_f_descript.m b/matlab/old2/inv_f_descript.m new file mode 100644 index 0000000..5f6988a --- /dev/null +++ b/matlab/old2/inv_f_descript.m @@ -0,0 +1,77 @@ +function coeff = inv_f_descript(samples, degree, varargin) +% samples = inv_f_descript(samples, degree, [plot_type]) +% +% Args: +% +% coeff - the fourier coefficients +% samples - the samples of the line to be transformed +% degree - the degree of the basis set +% plot_type (optional - passed directly to plot3 (e.g. 'x' plots +% crosses instead of a line) + +if (size(samples,2) ~= 3) + error('The second dimension of the samples matrix must be 3'); +end + +num_samples = size(samples, 1); + +if (nargin >= 3) + plot_type = varargin{1}; +else + plot_type = '-'; +end + +if (nargin == 4) + num_output_samples = varargin{2}; +else + if (num_samples > 100) + num_output_samples = num_samples; + else + num_output_samples = 100; + end +end + + + +k = [0:1:(num_samples-1)]'./(num_samples-1); + +psi = ones(num_samples,1); + + +for (d = [1:(degree-1)]) + + psi = [psi, sqrt(2) * cos(pi * k * d)]; + +end + +coeff = inv(psi' * psi) * psi' * samples; + +if (num_samples ~= num_output_samples) + psi = []; + + k = [0:1:(num_output_samples-1)]'./(num_output_samples-1); + + psi = ones(num_output_samples,1); + + for (d = [1:(degree-1)]) + + psi = [psi, sqrt(2) * cos(pi * k * d)]; + + end + +end + +new_samples = psi * coeff; + +figure(); +hold on; + +plot3(samples(:,1),samples(:,2),samples(:,3), [plot_type 'b']); + +plot3(new_samples(:,1),new_samples(:,2),new_samples(:,3), [plot_type 'g']); + +hold off; + + +cameratoolbar('Show'); +cameratoolbar('SetMode','orbit'); \ No newline at end of file diff --git a/matlab/old2/load_fourier.m b/matlab/old2/load_fourier.m new file mode 100644 index 0000000..f4121ae --- /dev/null +++ b/matlab/old2/load_fourier.m @@ -0,0 +1,43 @@ +function curve_prior_est(collection_name) +% function curve_prior_est(collection_name) +% +% Estimates the prior distribution of Fourier coefficients for a given phantom +% collection +% +% +% dirname - directory name of the strand collection + + +collection_name + + collection_names = dir(dirname); + + stats = []; + + if (size(collection_names,1) < 1) + error(['Did not read any collection names from ' dirname]); + else + + for (coll_i =1:size(collection_names,1)) + + collection_name = collection_names(coll_i).name; + + if (collection_name(1,1) ~= '.') + + collection_dir = [dirname '/' collection_name]; + + if (isdir(collection_dir)) + + prior_estimation(collection_dir); + + + end + end + + + end + + end + + +end \ No newline at end of file diff --git a/matlab/old2/load_fourier_coeff.m b/matlab/old2/load_fourier_coeff.m new file mode 100644 index 0000000..75a27a5 --- /dev/null +++ b/matlab/old2/load_fourier_coeff.m @@ -0,0 +1,127 @@ +function [coeffs, residual_vars, num_strand_cpoints, length] = load_fourier_coeff(collection_name, degree) +% function [coeffs, residual_vars, num_strand_control_points, straight_line_length] = load_fourier_coeff(collection_name, degree) +% +% Estimates the prior distribution of Fourier coefficients for a given phantom +% collection +% +% +% coeffs - A degree X 3 X num_strands matrix containing the loaded coefficients +% residual_vars - Residual variance after least squares fit +% num_strand_cpoints - Number of control points per strand +% straight_line_length - Straight-line length between strand +% endpoints +% + +% collection_name - directory name of the strand collection +% degree - Degree of the Fourier descriptors + + + collection = load_strands(collection_name); + + num_strands = size(collection,1); + + coeffs = []; + residual_vars = []; + num_strand_cpoints = []; + length = []; + + for strand_i = 1:num_strands + + strand = collection{strand_i,1}; + num_cpoints = size(strand,1); + + if (num_cpoints > degree) + + k = [0:1:(num_cpoints-1)]'./(num_cpoints-1); + + psi = ones(num_cpoints,1); + + for d = 1:(degree-1) + + psi = [psi, sqrt(2) * cos(pi * k * d)]; + + end + + C = inv(psi' * psi) * psi' * strand; + + residual = strand - psi * C; + + residual_var = sum(sum(residual.^2))/num_cpoints; + + coeffs = cat(3,coeffs,C); + + residual_vars = [residual_vars; residual_var]; + num_strand_cpoints = [num_strand_cpoints; num_cpoints]; + length = [length; norm(strand(num_cpoints,:) - strand(1,:))]; + + end + + end +end + + +function strand_collection = load_strands(dirname) + +% function strand_collection = load_strands(dirname) +% +% load_strand_collection.m +% Numerical Fibre Generator +% +% Created by Tom Close on 19/02/08. +% Copyright 2008 Tom Close. +% Distributed under the GNU General Public Licence. +% +% +% +% This file is part of 'Numerical Fibre Generator'. +% +% 'Numerical Fibre Generator' 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. +% +% 'Numerical Fibre Generator' 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 'Numerical Fibre Generator'. If not, see +% +% +% + + + num_strands = 0; + + files = dir(dirname)'; %' + + if (size(files) == [1,0]) + error(['Could not load any strands from directory ' dirname ]); + end + + for file = files + + if (~file.isdir) + + delimeters = [strfind(file.name, '_') strfind(file.name, '-') strfind(file.name, '.txt' )]; + + if (length(delimeters) == 4 && strmatch('strand', file.name)) + + num_strands = num_strands + 1; + + + strand_collection{num_strands, 1} = load([dirname filesep file.name]); + strand_collection{num_strands, 2} = str2num(file.name(delimeters(1) + 1 :delimeters(2) -1 )); + strand_collection{num_strands, 3} = str2num(file.name(delimeters(3) + 2 :delimeters(4) -1 )); + strand_collection{num_strands, 4} = str2num(file.name(delimeters(2) + 1 :delimeters(3) -1 )); + + + end + end + + end +end + + + diff --git a/matlab/old2/load_mrtrix_strands.m b/matlab/old2/load_mrtrix_strands.m new file mode 100644 index 0000000..0d60feb --- /dev/null +++ b/matlab/old2/load_mrtrix_strands.m @@ -0,0 +1,132 @@ +function strands = load_mrtrix_strands(filename, varargin) +% samples = f_descript(num_samples, coeff, [plot_type]) +% +% Args: +% +% samples - the samples, which are plotted +% num_samples - number of samples +% plot_type (optional - passed directly to plot3 (e.g. 'x' plots +% crosses instead of a line) + + if (nargin > 4) + error(['Incorrect number of arguments ' nargin ' expecting no more than 2']); + + elseif (nargin == 3) + first_strand = 1; + last_strand = varargin{2}; + + elseif (nargin == 4) + first_strand = varargin{2}; + last_strand = varargin{3}; + else + first_strand = 1; + last_strand = -1; + end + + if (nargin == 2) + strand_diameter = varargin{1}; + else + strand_diameter = 0.03; + end + + dots_i = findstr(filename,'.'); + ext = filename(dots_i(end):end); + + convert_to_tck = strcmp(ext, '.frr'); + + + file = fopen(filename,'r'); + + [fname, mode, machine_format] = fopen(file); + + + if (file == -1) + error([ 'Could not open file ' filename '!' ]); + end + + line = fgetl(file); + + if (~strcmp(line(1:13),'mrtrix tracks')) + error(['File, ' filename ' was not a valid mrtrix tracks file']); + end + + offset = 0; + datatype = []; + + for (line_i = 1:20) + line = fgetl(file); + if (strcmp(line(1:4),'file')) + offset = str2double(line(9:end)); + break +% elseif (strcmp(line(1:8),'datatype')) +% datatype = line(11:end); + end + end; + + if (~offset) + error(['"offset" property was not found after 10 lines']); + end + +% if (datatype == []) +% error(['"datatype" property was not found after 10 lines']); +% end + + + fseek(file, offset, 'bof'); + + elems = fread(file, inf, 'float32=>double', machine_format); + + + end_of_strands = find(isnan(elems)); + + end_of_strands = end_of_strands(1:3:end) - 1; +% for (i = 1: length(end_of_strands)) +% disp([ num2str(end_of_strands(i)) ', ' num2str(elems(end_of_strands(i))) ', ' num2str(elems(end_of_strands(i)+1)) ', ' num2str(elems(end_of_strands(i)+2)) ', ' num2str(elems(end_of_strands(i)+3)) ', ' num2str(elems(end_of_strands(i)+4))]) +% end + + total_number_of_strands = size(end_of_strands,1); + + if (last_strand == -1 | (last_strand > total_number_of_strands) ) + last_strand = size(end_of_strands,1); + end + + number_of_strands = last_strand - first_strand + 1; + + if (first_strand == 1) + end_of_prev_strand = -3; + else + end_of_prev_strand = end_of_strands(first_strand-1); + end + + strands = cell(number_of_strands,4); + + for (strand_i = first_strand:last_strand) + + output_strand_i = strand_i - first_strand + 1; + + strand = elems(end_of_prev_strand+4:end_of_strands(strand_i)); + + num_points = size(strand,1) / 3; + + if (num_points ~= floor(num_points)) + error(['Strand ' strand_i ' does not contain a number of elements that are divisible by 3, ' num2str(size(strand,1))]); + end + + strand = reshape(strand,3,num_points)'; + + if (convert_to_tck) + strand = fourier2tck(strand); + end + + strands{output_strand_i,1} = strand; + strands{output_strand_i,2} = strand_i-1; + strands{output_strand_i,3} = strand_diameter; + strands{output_strand_i,4} = strand_i-1; + + end_of_prev_strand = end_of_strands(strand_i); + end + + strands{end+1,1} = filename; + +end + diff --git a/matlab/old2/load_samples.m b/matlab/old2/load_samples.m new file mode 100644 index 0000000..e377ff0 --- /dev/null +++ b/matlab/old2/load_samples.m @@ -0,0 +1,238 @@ +function [samples, ext_prop_keys, ext_prop_values, initial_set, true_set, sphere_radius] = load_samples(filename, varargin) +% samples = f_descript(num_samples, coeff, [plot_type]) +% +% Args: +% +% samples - the samples, which are plotted +% + + if (nargin > 2) + error(['Incorrect number of arguments ' nargin ' expecting no more than 2']); + end + + if (nargin == 2) + sample_indices = varargin{1}; + else + sample_indices = []; + end + + + dots_i = findstr(filename,'.'); + ext = filename(dots_i(end):end); + + if ~strcmp(ext, '.tsp') + error(['File has extension ' ext ', required to be ''tsp'' for tract set samples file.']); + end + + + if any(sample_indices < 1) + error(['Sample indices must be positive integers (min index: ' num2str(min(sample_indices)) ')']); + end + + + file = fopen(filename,'r'); + + [fname, mode, machine_format] = fopen(file); + + + if (file == -1) + error([ 'Could not open file ' filename '!' ]); + end + + line = fgetl(file); + + if (~strcmp(line(1:13),'mrtrix tracks')) + error(['File, ' filename ' was not a valid mrtrix tracks file']); + end + + offset = 0; + num_points_per_set = 0; + num_tracts = 0; + degree = 0; + num_samples = 0; + true_set_provided = false; + sphere_radius = 0.39; + + for (line_i = 1:1000) + + line = fgetl(file); + + if strcmp(line(1:3), 'END') + break; + end + + if length(line) >= 4 && strcmp(line(1:4),'file') + offset = str2double(line(9:end)); + + elseif length(line) >= 18 && strcmp(line(1:18), 'num_points_per_set') + num_points_per_set = str2double(line(21:end)); + + elseif length(line) >= 8 && strcmp(line(1:8), 'set_size') + num_points_per_set = str2double(line(11:end)); + + elseif length(line) >= 11 && strcmp(line(1:11), 'num_tracts') + num_tracts = str2double(line(14:end)); + + elseif length(line) >= 5 && strcmp(line(1:5), 'count') + num_samples = str2double(line(8:end)); + + elseif length(line) >= 17 && strcmp(line(1:17), 'true_set_provided') + true_set_provided = true; + + elseif length(line) >= 22 && strcmp(line(1:22),'proposal_sphere_radius') + sphere_radius = str2num(line(25:end)); + + elseif length(line) >= 8 && strcmp(line(1:8),'datatype') + datatype = line(11:end); + + if (strcmp(datatype, 'Float32BE')) + machine_format = 'ieee-be'; + elseif (strcmp(datatype, 'Float32LE')) + machine_format = 'ieee-le'; + else + error(['Unrecognised data format ''' datatype ''', should be Float32BE or Float32LE.']); + end + + end + + end + + if (~offset || ~num_points_per_set) + error(['All required properties, ''file'' and ''num_points_per_set'', were not found after 1000 lines']); + end + + + + if any(sample_indices > num_samples) + error(['Sample index (' num2str(max(sample_indices)) ') out of range (' num2str(num_samples) ').']); + end + + fseek(file, offset, 'bof'); + + samples = cell(0,1); + + %Read true tract set if provided. + if (true_set_provided) + true_set = read_tract_set(file, num_points_per_set, machine_format); + else + true_set = []; + end + + %Read initial tract set. + initial_set = read_tract_set(file, num_points_per_set, machine_format); + + + if isempty(initial_set) + error(['No initial set was found in samples file']); + end + + %Load extended properties + [ext_prop_keys, ext_prop_values] = load_extend_elem_props([filename 'x']); + + if isempty(sample_indices) + + end_of_file = false; + + while ~end_of_file + + samples{end+1,1} = read_tract_set(file, num_points_per_set, machine_format); + + end_of_file = isempty(samples{end}); + + end + + else + + set_byte_size = num_points_per_set * 3 * 4; % times 3 for a point containing 3 numbers, and times 4 for the size of a float. + + prev_index = 0; + + for set_i = 1:length(sample_indices) + + sample_index = sample_indices(set_i); + + if (sample_index - prev_index ~= 1) + if fseek(file, offset + sample_index * set_byte_size, 'bof') < 0 + error(['Sample index (' num2str(sample_index) ') is out of range of the file']); + end + end + + samples{set_i+2,1} = read_tract_set(file, num_tracts, num_points_per_set, machine_format); + + if end_of_file + error(['End of file reached while attempting to load tract sample ' num2str(sample_indices(set_i)) '.']); + end + + prev_index = sample_index; + + end + + ext_prop_values = ext_prop_values(sample_indices,:); + + end + +end + + +function tract_set = read_tract_set(file, num_points_per_set, machine_format) + + block_size = num_points_per_set * 3; + + [block, read_count] = fread(file, block_size, 'float32=>double', machine_format); + + if isinf(block(1)) || feof(file) + tract_set = []; + return; + end + + if read_count ~= block_size + error(['''num_points_per_set'' (' num2str(num_points_per_set) ') property does not divide evenly into the size of file']); + end + + block = reshape(block, 3, num_points_per_set)'; + + tract_seperators = find(isinf(block(:,1))); + + num_tracts = size(tract_seperators,1); + + if tract_seperators(end) ~= num_points_per_set + error(['''num_points_per_set'' (' num2str(num_points_per_set) ') does not align with tract seperators ([-inf, -inf, -inf]).']); + end + + + tract_set = cell(num_tracts,3); + + tract_start_index = 1; + + for tract_i = 1:num_tracts + + tract_end_index = tract_seperators(tract_i); + + tract = block(tract_start_index:(tract_end_index-1),:); + + axes_seperators = find(isnan(tract(:,1))); + + if length(axes_seperators) ~= 3 + error (['Expected 3 axes in tract ' num2str(tract_i) ', only found ' length(axes_seperators) '.']); + end + + axes_start_index = 1; + + for axes_i = 1:3 + + axes_end_index = axes_seperators(axes_i); + + tract_set{tract_i, axes_i} = tract(axes_start_index:(axes_end_index-1),:); + + axes_start_index = axes_end_index + 1; + + end + + tract_start_index = tract_end_index + 1; + + end + +end + + + diff --git a/matlab/old2/load_strand_samples.m b/matlab/old2/load_strand_samples.m new file mode 100644 index 0000000..59707ed --- /dev/null +++ b/matlab/old2/load_strand_samples.m @@ -0,0 +1,231 @@ +function [samples, ext_prop_keys, ext_prop_values, initial_set, true_set, sphere_radius] = load_strand_samples(filename, varargin) +% samples = f_descript(num_samples, coeff, [plot_type]) +% +% Args: +% +% samples - the samples, which are plotted +% + + if (nargin > 2) + error(['Incorrect number of arguments ' nargin ' expecting no more than 2']); + end + + if (nargin == 2) + sample_indices = varargin{1}; + else + sample_indices = []; + end + + + if (nargin == 3) + convert_to_track = varargin{2}; + else + convert_to_track = false; + end + + dots_i = findstr(filename,'.'); + ext = filename(dots_i(end):end); + + if ~strcmp(ext, '.smp') + error(['File has extension ' ext ', required to be ''smp'' for strand set samples file.']); + end + + + if any(sample_indices < 1) + error(['Sample indices must be positive integers (min index: ' num2str(min(sample_indices)) ')']); + end + + + file = fopen(filename,'r'); + + [fname, mode, machine_format] = fopen(file); + + + if (file == -1) + error([ 'Could not open file ' filename '!' ]); + end + + line = fgetl(file); + + if (~strcmp(line(1:13),'mrtrix tracks')) + error(['File, ' filename ' was not a valid mrtrix tracks file']); + end + + offset = 0; + num_points_per_set = 0; + num_strands = 0; + degree = 0; + num_samples = 0; + true_set_provided = false; + sphere_radius = 0.39; + + for (line_i = 1:1000) + + line = fgetl(file); + + if strcmp(line(1:3), 'END') + break; + end + + if length(line) >= 4 && strcmp(line(1:4),'file') + offset = str2double(line(9:end)); + + elseif length(line) >= 18 && strcmp(line(1:18), 'num_points_per_set') + num_points_per_set = str2double(line(21:end)); + + elseif length(line) >= 8 && strcmp(line(1:8), 'set_size') + num_points_per_set = str2double(line(11:end)); + + elseif length(line) >= 11 && strcmp(line(1:11), 'num_strands') + num_strands = str2double(line(14:end)); + + elseif length(line) >= 5 && strcmp(line(1:5), 'count') + num_samples = str2double(line(8:end)); + + elseif length(line) >= 17 && strcmp(line(1:17), 'true_set_provided') + true_set_provided = true; + + elseif length(line) >= 22 && strcmp(line(1:22),'proposal_sphere_radius') + sphere_radius = str2num(line(25:end)); + + elseif length(line) >= 8 && strcmp(line(1:8),'datatype') + datatype = line(11:end); + + if (strcmp(datatype, 'Float32BE')) + machine_format = 'ieee-be'; + elseif (strcmp(datatype, 'Float32LE')) + machine_format = 'ieee-le'; + else + error(['Unrecognised data format ''' datatype ''', should be Float32BE or Float32LE.']); + end + + end + + end + + if (~offset || ~num_points_per_set) + error(['All required properties, ''file'' and ''num_points_per_set'', were not found after 1000 lines']); + end + + + + if any(sample_indices > num_samples) + error(['Sample index (' num2str(max(sample_indices)) ') out of range (' num2str(num_samples) ').']); + end + + fseek(file, offset, 'bof'); + + samples = cell(0,1); + + %Read true strand set if provided. + if (true_set_provided) + true_set = read_strand_set(file, num_points_per_set, machine_format, convert_to_track); + else + true_set = []; + end + + %Read initial strand set. + initial_set = read_strand_set(file, num_points_per_set, machine_format, convert_to_track); + + + if isempty(initial_set) + error(['No initial set was found in samples file']); + end + + %Load extended properties + [ext_prop_keys, ext_prop_values] = load_extend_elem_props([filename 'x']); + + if isempty(sample_indices) + + end_of_file = false; + + while ~end_of_file + + samples{end+1,1} = read_strand_set(file, num_points_per_set, machine_format, convert_to_track); + + end_of_file = isempty(samples{end}); + + end + + else + + set_byte_size = num_points_per_set * 3 * 4; %degree+1 accounts for strand divider [NaN, NaN, NaN], and 4 is size of Float32. + + prev_index = 0; + + for set_i = 1:length(sample_indices) + + sample_index = sample_indices(set_i); + + if (sample_index - prev_index ~= 1) + if fseek(file, offset + sample_index * set_byte_size, 'bof') < 0 + error(['Sample index (' num2str(sample_index) ') is out of range of the file']); + end + end + + samples{set_i+2,1} = read_strand_set(file, num_strands, num_points_per_set, machine_format, convert_to_track); + + if end_of_file + error(['End of file reached while attempting to load strand ' num2str(sample_indices(set_i)) '.']); + end + + prev_index = sample_index; + + end + + ext_prop_values = ext_prop_values(sample_indices,:); + + end + +end + + +function strand_set = read_strand_set(file, num_points_per_set, machine_format, convert_to_track) + + block_size = num_points_per_set * 3; + + [block, read_count] = fread(file, block_size, 'float32=>double', machine_format); + + if isinf(block(1)) || feof(file) + strand_set = []; + return; + end + + if read_count ~= block_size + error(['''num_points_per_set'' (' num2str(num_points_per_set) ') property does not divide evenly into the size of file']); + end + + block = reshape(block, 3, num_points_per_set)'; + + seperators = find(isnan(block(:,1))); + + num_strands = size(seperators,1); + + if seperators(end) ~= num_points_per_set + error(['''num_points_per_set'' (' num2str(num_points_per_set) ') does not align with strand seperators ([NaN, NaN, NaN]).']); + end + + strand_set = cell(num_strands,1); + + start_index = 1; + + for strand_i = 1:num_strands + + end_index = seperators(strand_i); + + strand = block(start_index:(end_index-1),:); + + if (convert_to_track) + strand_set{strand_i} = fourier2tck(strand); + else + strand_set{strand_i} = strand; + end + + start_index = end_index + 1; + + end + +end + + + diff --git a/matlab/old2/p_descript.m b/matlab/old2/p_descript.m new file mode 100644 index 0000000..c6f74fa --- /dev/null +++ b/matlab/old2/p_descript.m @@ -0,0 +1,91 @@ +function samples = p_descript(num_samples, coeff, varargin) +% samples = p_descript(num_samples, coeff, [plot_type]) +% +% Args: +% +% num_samples - number of samples +% coeff - the coefficients of the polynomial +% plot_type (optional - passed directly to plot3 (e.g. 'x' plots +% crosses instead of a line) + +if (nargin == 3) + plot_type = varargin{1}; +else + plot_type = '-'; +end + +if (size(coeff,2) ~= 3) + error('The second dimension of the coefficient matrix must be 3'); +end + +degree = size(coeff,1); + +range = ceil((num_samples - 1)/2); +num_samples = 2 * range + 1; + +t = [-range:1:range]'./ range; + + + + +t_bar = ones(size(t)); + +if (degree >= 0) + psi = ones(num_samples,1); +end + + +for (d = [1:(degree-1)]) + + t_bar = t_bar .* t; + + psi = [psi, t_bar]; + +end + +samples = psi * coeff; + +%figure; +sfigure(1); +plot3(samples(:,1), samples(:,2), samples(:,3), plot_type); + +cameratoolbar('Show'); +cameratoolbar('SetMode','orbit'); +grid; +xlabel('x'); +ylabel('y'); +zlabel('z'); + +max_lim = max(sum(coeff)); + +% xlim([-max_lim max_lim]); +% ylim([-max_lim max_lim]); +% zlim([-max_lim max_lim]); + +% xlim([-100 100]); +% ylim([-100 100]); +% zlim([-100 100]); + + + +coeff + + +function h = sfigure(h) +% SFIGURE Create figure window (minus annoying focus-theft). +% +% Usage is identical to figure. +% +% Daniel Eaton, 2005 +% +% See also figure + +if nargin>=1 + if ishandle(h) + set(0, 'CurrentFigure', h); + else + h = figure(h); + end +else + h = figure; +end diff --git a/matlab/old2/p_scheme.mat b/matlab/old2/p_scheme.mat new file mode 100644 index 0000000..d9f7acb Binary files /dev/null and b/matlab/old2/p_scheme.mat differ diff --git a/matlab/old2/plot_neighbourhood.m b/matlab/old2/plot_neighbourhood.m new file mode 100644 index 0000000..e383179 --- /dev/null +++ b/matlab/old2/plot_neighbourhood.m @@ -0,0 +1,97 @@ +function img = plot_neighbourhood(image_filename, mid_pos, figure_start, plot_limits) + + load('/data/home/tclose/Code/Tractography/matlab_scripts/grad_scheme'); + load('/data/home/tclose/Code/Tractography/matlab_scripts/p_scheme'); + + if (~exist('image_filename')) + image_filename = '~/Data/Set_of_fifty/chunked_separate_images/001-11-11-11.mif'; + end + + if (~exist('mid_pos')) + mid_pos = [1 1 1]; + end + + if (~exist('figure_start')) + figure_start = 0; + else + figure_start = figure_start - 1; + end + + if (~exist('plot_limits')) + dynamically_set_plot_limits = 1; + else + dynamically_set_plot_limits = 0; + end + + + img_struct = read_image(image_filename); + + + + if (~isfield(img_struct, 'data')) + error(['Could not read image from file ' image_filename]); + else + + img = img_struct.data; + img = img(mid_pos(1):(mid_pos(1)+2), mid_pos(2):(mid_pos(2)+2), mid_pos(3):(mid_pos(3)+2), :); + + size_of_image = size(img); + if (size_of_image(1:3) ~= [3 3 3]) + error('plot_neighbourhood currently only plots 3x3 neighbourhoods of voxels'); + end + + if (dynamically_set_plot_limits) + plot_limits = max(max(max(max(abs(img))))); + end + + if plot_limits == 0 + error('Neighbourhood contains no signal'); + end + + for (z = 1:3) + + next_fig = z+figure_start; + if (ishandle(next_fig)) + + close(next_fig); + end + + fig = figure(next_fig); + + set(fig,'Units','normalized') + + set(fig, 'Position', [0.05 + ((z-1) * 0.3), (0.55 * mod(figure_start+1,2) + 0.05) 0.3 0.375]); + set(fig, 'DoubleBuffer', 'on'); + set(fig, 'Name', 'Amplitude plot'); + + cameratoolbar('Show'); + cameratoolbar('SetMode','orbit'); + + set(fig, 'Color', [1 1 1]) + + for (y = 1:3) + + for (x = 1:3) + + + ax = subplot(3,3, (y-1)*3 + x); + +% title(['z=' num2str(z) ', y=' num2str(y) ', x=' num2str(x)]); + + set(ax, 'Xlim', [-plot_limits plot_limits]); + set(ax, 'Ylim', [-plot_limits plot_limits]); + set(ax, 'Zlim', [-plot_limits plot_limits]); + + voxel_signal = squeeze(img(x,y,z,:)); + sh = amp2SH(voxel_signal, grad_scheme); + + plot_SH(sh, p_scheme, ax); + + daspect([1,1,1]); + end + end + end + end +end + + diff --git a/matlab/old2/plot_strand_samples.m b/matlab/old2/plot_strand_samples.m new file mode 100644 index 0000000..c1429bb --- /dev/null +++ b/matlab/old2/plot_strand_samples.m @@ -0,0 +1,258 @@ +function [samples, colours_of_strands] = plot_strand_samples(varargin) +% +% PURPOSE: Plots strands from strand files, and optionally displays reference sphere and voxels +% +% ARGUMENTS: +% +% filename The filename of the strands in either .tck or .frr formats. +% +% OPTIONS (name, description, type, default): +% +% -transparency +% transparency of the plotted samples +% float +% 0.75 +% +% -include +% The indices of the strands to include in the plot +% matrix_1x: +% +% -sample_include +% The indices of the samples to include in the plot +% matrix_1x: +% +% -colours_of_strands +% Colours of the plotted strands +% matrix_:x3 +% +% -voxel_size +% Size of reference voxel +% float +% 0.15 +% +% -num_voxels +% Number of reference voxels +% int +% 3 +% +% -cube_size +% Size of reference voxel +% float +% 0 +% +% -num_segments +% Number of segments to plot for each strand. +% int +% 100 +% +% -tube_radius +% Radius of tubes to plot for each strand. +% float +% 0 +% + + global colours_of_strands; + +% The following code sets the input arguments and options as specified by the 'arguments' and 'options' cell arrays. + + description = 'Plots strands from sample files, and optionally displays reference sphere and voxels'; + + arguments = {'filename', 'The filename of the strand samples (''.smp'' format).'}; + + options = {... + 'transparency ', 0.75, 'float', 'transparency of the plotted samples';... + 'include ', [], 'matrix_1x:', 'The indices of the strands to include in the plot';... + 'sample_include ', [], 'matrix_1x:', 'The indices of the samples to include in the plot';... + 'colours_of_strands', colours_of_strands, 'matrix_:x3', 'Colours of the plotted strands';... + 'voxel_size ', 0.15, 'float', 'Size of reference voxel';... + 'num_voxels ', 3, 'int', 'Number of reference voxels';... + 'cube_size ', 0, 'float', 'Size of reference voxel';... + 'num_segments ', 100, 'int', 'Number of segments to plot for each strand.';... + 'tube_radius ', 0, 'float', 'Radius of tubes to plot for each strand.';... + ...%'sphere_radius ', 0.389711, 'float', 'Size of reference sphere'... + }; + + + parse_arguments + if (help_display) + return; + end + +% End arguments % + + + + dots_i = findstr(filename,'.'); + ext = filename(dots_i(end):end); + + if ~strcmp(ext, '.smp') + error(['Input file must be a samples file (extension ''.smp''), found file with extension ' ext '.']); + end + + [samples, ext_prop_keys, ext_prop_values, initial_set, true_set, sphere_radius] = load_strand_samples(filename); + + num_strands = size(initial_set,1); + num_samples = size(samples,1) - 1; + + if any(find(sample_include > num_samples)) + error('Selected sample indices exceed number of loaded samples'); + end + + if isempty(sample_include) + sample_include = 1:num_samples; + end + + + bundle_indices_index = find(strcmp(ext_prop_keys, 'bundle_index')); + + cdata = cell(num_samples, num_strands); + + + if ~isempty(bundle_indices_index) + +% bundle_indices_strings = ext_prop_values{bundle_indices_index}; +% +% bundle_indices = []; +% +% for sample_i = 1:size(bundle_indices_strings,1) +% bundle_indices = [bundle_indices; regexp(bundle_indices_strings,'|','split')]; %#ok +% end + + bundle_indices = ext_prop_values; + + max_bundle_index = max(max(bundle_indices))+1; + + if size(colours_of_strands,1) < max_bundle_index %#ok + colours_of_strands = rand([max_bundle_index, 3]); %#ok + display_colour_key(colours_of_strands, 0:1:(max_bundle_index-1)); %#ok + end + + for sample_i = 1:num_samples + + for strand_i = 1:num_strands + + colour_data = repmat(shiftdim(colours_of_strands(bundle_indices(sample_i, strand_i)+1,:),-1), [num_segments 1 1]); %#ok + cdata{sample_i, strand_i} = [colour_data colour_data]; + + end + + end + + else + + if size(colours_of_strands,1) < num_strands %#ok + colours_of_strands = rand([num_strands, 3]); %#ok + display_colour_key(colours_of_strands, 0:1:(num_strands-1)); %#ok + end + for sample_i = 1:num_samples + for strand_i = 1:num_strands + + colour_data = repmat(shiftdim(colours_of_strands(strand_i,:),-1), [num_segments 1 1]); %#ok + cdata{sample_i, strand_i} = [colour_data colour_data]; + + end + end + + end + + alpha_data = ones(num_segments,2) * transparency; + + main_fig = figure(); + + set(main_fig,'Units','normalized') + + set(main_fig, 'Position', [0.3 0.25 0.4 0.5]); + set(main_fig, 'DoubleBuffer', 'on'); + set(main_fig, 'Name', strrep(filename, '_', ' ')); + + cameratoolbar('Show'); + cameratoolbar('SetMode','orbit'); + campos([0 0 1]); + camup([0 1 0]); + + clf; + + whitebg(main_fig,'black'); + hold on; + + + fprintf('\n'); + disp(['Plotting ' num2str(size(sample_include,2)) ' samples.']); + + for sample_i = sample_include + + sample = samples{sample_i,1}; + +% if tube_radius > 0 +% +% display_strands(sample, colours_of_strands, include, 'strand', '3D'); +% +% else + + for strand_i = 1:num_strands + + tck = fourier2tck(sample{strand_i,1}); + + h = surface(... + 'XData', [tck(:,1) tck(:,1)],... + 'YData', [tck(:,2) tck(:,2)],... + 'ZData', [tck(:,3) tck(:,3)],... + 'CData', cdata{sample_i, strand_i},... + 'AlphaData', alpha_data,... + 'FaceColor', 'none',... + 'EdgeColor', 'flat',... + 'Marker', 'none', ... + 'LineStyle', '-', ... + 'LineWidth', 1); + view(3) + daspect ([ 1 1 1 ]); + end + + if ~mod(sample_i,25) + fprintf('.'); + end + +% end + + + + + end + + hold off; + + %set(gca, 'color', [0 0 0]); + set(gcf, 'color', [0 0 0]); + + label_handle = get(gca,'xlabel'); + set(label_handle, 'string', 'X-axis', 'color', [1 1 1]); + + label_handle = get(gca,'ylabel'); + set(label_handle, 'string', 'Y-axis', 'color', [1 1 1]); + + label_handle = get(gca,'zlabel'); + set(label_handle, 'string', 'Z-axis', 'color', [1 1 1]); + + h = get (gca, 'children'); + daspect ([ 1 1 1 ]); + + light + lighting gouraud; + + +% figure(main_fig); + + + +% if sphere_radius ~= 0 +% display_reference_sphere(sphere_radius, 0.1); +% end + + if voxel_size ~= 0 + plot_vox_lines(voxel_size,num_voxels); + end + + + samples = samples(sample_include); + +end \ No newline at end of file diff --git a/matlab/old2/plot_vox_lines.m b/matlab/old2/plot_vox_lines.m new file mode 100644 index 0000000..9832843 --- /dev/null +++ b/matlab/old2/plot_vox_lines.m @@ -0,0 +1,38 @@ +function plot_vox_lines(vox_size, num_voxels) +% function plot_vox_lines(vox_size) + + label_contrast = 0.8; + + half_vox_size = vox_size/2; + + hold on; + + start_edge = -half_vox_size*num_voxels; + end_edge = half_vox_size*num_voxels; + + base_colour = [.75,.75,.75]; + + for row_pos = start_edge:vox_size:end_edge + for col_pos = start_edge:vox_size:end_edge + + line_mat = [row_pos, col_pos, start_edge; row_pos, col_pos, end_edge]; + + for dim_i = 0:2 + + colour = base_colour; + if (row_pos == start_edge) && (col_pos == start_edge) + colour = [0.5,0.5,0.5]; + colour(dim_i+1) = label_contrast; + end + + plot3(line_mat(:,mod(0+dim_i,3)+1),line_mat(:,mod(1+dim_i,3)+1),line_mat(:,mod(2+dim_i,3)+1), 'Color', colour); + + + end + + end + end + + hold off; + +end \ No newline at end of file diff --git a/matlab/old2/plot_voxel_signal.m b/matlab/old2/plot_voxel_signal.m new file mode 100644 index 0000000..bfd3182 --- /dev/null +++ b/matlab/old2/plot_voxel_signal.m @@ -0,0 +1,17 @@ +function voxel_signal = plot_voxel_signal(image_filename, x, y, z) + + load('/data/home/tclose/Code/Tractography/matlab_scripts/grad_scheme'); + load('/data/home/tclose/Code/Tractography/matlab_scripts/p_scheme'); + + + img_struct = read_image(image_filename); + img = img_struct.data; + + voxel_signal = squeeze(img(x,y,z,:)); + sh = amp2SH(voxel_signal, grad_scheme); + + plot_SH(sh, p_scheme); + + daspect([1,1,1]); + +end diff --git a/matlab/old2/rand_f_descript.m b/matlab/old2/rand_f_descript.m new file mode 100644 index 0000000..36450c7 --- /dev/null +++ b/matlab/old2/rand_f_descript.m @@ -0,0 +1,106 @@ +function coeffs = rand_f_descript(num_samples, iterations, scalars, varargin) +%rand_f_descript(num_samples, iterations, scalars, [normalise], [plot_type]) +% +% +% rand_f_descript generates multiple plots of fourier descriptors in +% succession to give a feel for the types of curves that can be produced. +% +% The function will randomly generate a number (specified by the input +% 'iterations') of different curves and plot them in sucession (press any +% key to iterate to next plot). +% +% Coefficients are initially generated between 0 and 1 and are scaled via +% the 'scalars' input vector. Each dimension is scaled identically. If +% the optional argument normalise is set to 1 then the second degree +% coefficients (the linear length) are normalised before they are scaled. +% +% num_samples - number of samples to plot along each curve +% iterations - number of random generations +% scalars - scalars of the relative coefficient degrees +% normalise - if set to one, the coefficients are normalised +% across each degree before they are scaled. +% plot_type - passed directly to the plot function. Use 'x' to +% see placement of samples. + + +if (nargin >=4) + normalise = varargin{1}; +else + normalise = 1; +end + +if (nargin == 5) + plot_type = varargin{2}; +else + plot_type = '-'; +end + +if (size(scalars,1) < size(scalars,2)) + scalars = scalars'; +end + +degree = size(scalars,1); + +coeffs = []; + +for (i =1:iterations) + c = 2*(rand(degree, 3) - 0.5); + + length = sqrt(sum(c(2,:) * c(2,:)')); + + if (normalise) + for (d = 1:degree) + row_length = sqrt(sum(c(d,:) * c(d,:)')); + c(d,:) = c(d,:) ./row_length; + end + else + c(2,:) = c(2,:) ./ length; + end + + c = [c(:,1) .* scalars, c(:,2) .* scalars, c(:,3) .* scalars]; + i + + sfigure(1); + f_descript(num_samples, c, plot_type); +% title('Strand path'); +% +% if (degree == 4) +% figure(2); +% plotv(c); +% title('Coefficient vectors'); +% end + + + low_lim = c(1,:)' - 1.5 * scalars(2); + up_lim = c(1,:)' + 1.5 * scalars(2); + + xlim([low_lim(1) up_lim(1)]); + ylim([low_lim(2) up_lim(2)]); + zlim([low_lim(3) up_lim(3)]); + + coeffs = cat(3, coeffs,c); + + pause; + +end + + + +function h = sfigure(h) +% SFIGURE Create figure window (minus annoying focus-theft). +% +% Usage is identical to figure. +% +% Daniel Eaton, 2005 +% +% See also figure + +if nargin>=1 + if ishandle(h) + set(0, 'CurrentFigure', h); + else + h = figure(h); + end +else + h = figure; +end diff --git a/matlab/parse_properties_row.m b/matlab/parse_properties_row.m new file mode 100644 index 0000000..8ff056a --- /dev/null +++ b/matlab/parse_properties_row.m @@ -0,0 +1,15 @@ +function values = parse_properties_row(line) + + line = deblank(line); + + if isempty(line) + error('No keys found in extended properties file.'); + + elseif isempty(regexp(line,'\t', 'once')) + values{1} = line; + + else + values = regexp(line,'\t','split'); + end + +end \ No newline at end of file diff --git a/matlab/parse_strand_sections.m b/matlab/parse_strand_sections.m new file mode 100644 index 0000000..b04499f --- /dev/null +++ b/matlab/parse_strand_sections.m @@ -0,0 +1,5 @@ +function sections = parse_strand_sections(elems) + + sections = split_at_file_seperator(elems, [-inf,nan,nan]); + +end \ No newline at end of file diff --git a/matlab/parse_strands.m b/matlab/parse_strands.m new file mode 100644 index 0000000..242f1a1 --- /dev/null +++ b/matlab/parse_strands.m @@ -0,0 +1,5 @@ +function strands = parse_strands(elems) + + strands = split_at_file_seperator(elems, [nan,nan,nan]); + +end \ No newline at end of file diff --git a/matlab/parse_tcks.m b/matlab/parse_tcks.m new file mode 100644 index 0000000..367a828 --- /dev/null +++ b/matlab/parse_tcks.m @@ -0,0 +1,5 @@ +function tcks = parse_tcks(elems) + + tcks = split_at_file_seperator(elems, [nan,nan,nan]); + +end \ No newline at end of file diff --git a/matlab/parse_tract_sections.m b/matlab/parse_tract_sections.m new file mode 100644 index 0000000..f553095 --- /dev/null +++ b/matlab/parse_tract_sections.m @@ -0,0 +1,5 @@ +function sections = parse_tract_sections(elems) + + sections = split_at_file_seperator(elems, [-inf,nan,nan]); + +end \ No newline at end of file diff --git a/matlab/parse_tracts.m b/matlab/parse_tracts.m new file mode 100644 index 0000000..4a3d035 --- /dev/null +++ b/matlab/parse_tracts.m @@ -0,0 +1,26 @@ +function tracts = parse_tracts(elems) + + tract_divs = split_at_file_seperator(elems, [-inf,-inf,-inf]); + + if isempty(tract_divs) + tract_divs = split_at_file_seperator(elems, [-inf, -inf, inf]); % Legacy issue with incorrect seperators. + end + + tracts = cell(0); + + for tract_i = 1:size(tract_divs,1) + + tract_row= split_at_file_seperator(tract_divs{tract_i}, [nan,nan,nan]); + + if size(tract_row,1) ~= 3 + error([num2str(size(tract_row,1)) ' strands were loaded from ' num2str(tract_i) ' instead of 3']); + end + + for ax_i = 1:3 + tracts{tract_i,ax_i} = tract_row{ax_i}; + end + + end + +end + diff --git a/matlab/pf.m b/matlab/pf.m new file mode 100644 index 0000000..83a0fbb --- /dev/null +++ b/matlab/pf.m @@ -0,0 +1,23 @@ +function fig = pf(varargin) + + if nargin == 0 + error('No arguments supplied'); + end + + filename = varargin{1}; + + if file_extension(filename) == 'str' + fig = plot_strands(varargin{:}); + elseif file_extension(filename) == 'sst' + fig = plot_strand_sets(varargin{:}); + elseif file_extension(filename) == 'tct' + fig = plot_tracts(varargin{:}); + elseif file_extension(filename) == 'tst' + fig = plot_tract_sets(varargin{:}); + elseif file_extension(filename) == 'tck' + fig = plot_tcks(varargin{:}); + else + error(['Unrecognised extension, ''' file_extension(filename) '''.']); + end + +end \ No newline at end of file diff --git a/matlab/plot_evolution.m b/matlab/plot_evolution.m new file mode 100644 index 0000000..68a0ade --- /dev/null +++ b/matlab/plot_evolution.m @@ -0,0 +1,240 @@ +function colours_of_evolved_strands = plot_evolution(dir_name, varargin) +% +% +% PURPOSE: Plots samples from an MCMC sampling of multiple strands described by fourier components +% +% ARGUMENTS: +% +% collated_samples_dir The directory that contains the collated samples (output from 'collate samples' program). +% +% OPTIONS (name, description, type, default): +% +% -true_strands_path The path to a .frr file containing the positions of the true strands +% string +% '' +% +% -include_samples The indices of the samples to include +% matrix_:x: +% [] +% +% -include_strands The indices of the strands to include +% matrix_:x: +% [] +% +% -colours_of_evolved_strands Base colours for samples of each strand +% matrix_:x3 +% [0.228801116693986 0.363610266029849 0.983863430198537;0.616023151232531 0.815277162004599 0.0953236751558441;0.51015054259208 0.168093971458644 0.739270506551875;0.350622850963505 0.716324475389521 0.294423983509783] +% +% -start_shade Starting shade of the sample colours +% float +% 0.2 +% +% -end_shade Ending shade of the sample colours +% float +% 0.8 +% +% -line_style Show samples as an evolving line instead of plusses. +% bool +% 0 +% +% -invert_shades Invert shades on plotted colours so that shades approach white. +% bool +% 0 + + global colours_of_evolved_strands; + + + file_paths = list_filenames(dir_name, 'degree_', '.tck'); + + if length(file_paths) == 0 + error(['No files loaded from directory ' dir_name '.']); + end + + strands = load_strands(file_paths{1}); + + % If the number of previously generated strand colours is less than the number of strands, then reset it and generate again. + if (size(strands,1) - 1) > size(colours_of_evolved_strands,1) + colours_of_evolved_strands = []; + end + + + description = 'Plots samples from an MCMC sampling of multiple strands described by fourier components'; + + arguments = {'collated_samples_dir', 'The directory that contains the collated samples (output from ''collate samples'' program).'}; + + options = {... + 'true_strands_path ', [], 'string', 'The path to a .frr file containing the positions of the true strands';... + 'include_samples ', [], 'matrix_:x:', 'The indices of the samples to include';... + 'include_strands ', [], 'matrix_:x:', 'The indices of the strands to include';... + 'colours_of_evolved_strands ', colours_of_evolved_strands, 'matrix_:x3', 'Base colours for samples of each strand';... + 'start_shade ', 0.2, 'float', 'Starting shade of the sample colours';... + 'end_shade ', 1.0, 'float', 'Ending shade of the sample colours';... + 'line_style ', 0, 'bool', 'Show samples as an evolving line instead of plusses.';... + 'invert_shades ', 0, 'bool', 'Invert shades on plotted colours so that shades approach white.'... + }; + + + supplied_options = parse_options(options, varargin); + + for option_i = 1:size(supplied_options,1) + if strcmp(supplied_options{option_i,3}, 'string') + eval([supplied_options{option_i,1} ' = ''' supplied_options{option_i,2} ''';']); + else + + if ~isstr(supplied_options{option_i,2}) + supplied_options{option_i,2} = mat2str(supplied_options{option_i,2}); + end + + eval([supplied_options{option_i,1} ' = ' supplied_options{option_i,2} ';']); + end + end + + + if help_display + display_help_message(description, arguments, options); + return; + end + + + if ~isempty(true_strands_path) + true_strands = load_strands(true_strands_path); + else + true_strands = []; + end + + if line_style + style = '-'; + marker = 'none'; + else + style = 'none'; + marker = '+'; + end + + + shade_range = end_shade - start_shade; + + + + for degree_i = 1:size(file_paths,1) + + strands = load_strands(file_paths{degree_i}); + + title_name = strrep(strands{size(strands,1),1},'_', ' '); + + strands = strands(1:(size(strands,1)-1), :); + + display_colours = 0; + + if isempty(colours_of_evolved_strands) + + display_colours = 1; + + for strand_i = 1:size(strands,1) + colour = rand(1,3); + + if invert_shades + colour = [1 1 1] - colour ./ norm(colour); + else + colour = colour ./ norm(colour); + end + + colours_of_evolved_strands = [colours_of_evolved_strands ; colour]; + end + + end + + if (isempty(include_strands)) + include_strands = [1:size(strands,1)]; + end + + + fig = figure(); + + title(title_name); + set(fig,'Units','normalized') + set(fig, 'Position', [(0.05 + (degree_i-1) * 0.3) 0.25 0.3 0.5]); + set(fig, 'DoubleBuffer', 'on'); + set(fig, 'Name', strrep(file_paths{degree_i},'_',' ')); + xlabel('x-axis'); + ylabel('y-axis'); + zlabel('z-axis'); + whitebg(fig,'black'); + set(fig, 'color', [0 0 0]); + + hold on; + + if ~isempty(true_strands) + + x_components = []; + y_components = []; + z_components = []; + + for strand_i = 1:(size(true_strands,1)-1) + + true_strand = true_strands{strand_i,1}; + + x_components = [x_components; true_strand(degree_i, 1)]; + y_components = [y_components; true_strand(degree_i, 2)]; + z_components = [z_components; true_strand(degree_i, 3)]; + end + + plot3(x_components, y_components, z_components, 'o', 'MarkerEdgeColor','white', 'MarkerFaceColor','yellow', 'MarkerSize',8); + + end + + for strand_i = include_strands + + samples = strands{strand_i,1}; + + num_samples = size(samples,1); + + if (isempty(include_samples)) + include_samples = [1:num_samples]'; + + else + include_samples = sort(include_samples(find(include_samples <= num_samples)))'; + end + + num_include_samples = length(include_samples); + + if invert_shades + shades = ones(num_include_samples,1) - [end_shade:-(shade_range / (num_include_samples-1)):start_shade]'; + cdata = ones(num_include_samples, 3) - shades * ([1 1 1] - colours_of_evolved_strands(strand_i,:)); + else + shades = [start_shade:(shade_range / (num_include_samples-1)):end_shade]'; + cdata = shades * (colours_of_evolved_strands(strand_i,:)); + end + + cdata = reshape(cdata, [num_include_samples 1 3]); + + h = surface(... + 'XData',[samples(include_samples,1) samples(include_samples,1)],... + 'YData',[samples(include_samples,2) samples(include_samples,2)],... + 'ZData',[samples(include_samples,3) samples(include_samples,3)],... + 'CData',[cdata cdata],... + 'FaceColor','none',... + 'EdgeColor','flat',... + 'Marker',marker, ... + 'LineStyle',style, ... + 'LineWidth',2); + view(3) + daspect ([ 1 1 1 ]); + end + + hold off; + + + daspect ([ 1 1 1 ]); + + cameratoolbar('Show'); + cameratoolbar('SetMode','orbit'); + + + end + + if display_colours + display_colour_key(colours_of_evolved_strands); + end + + +end diff --git a/matlab/plot_explore_stats.m b/matlab/plot_explore_stats.m new file mode 100644 index 0000000..86a4c90 --- /dev/null +++ b/matlab/plot_explore_stats.m @@ -0,0 +1,71 @@ +function plot_explore_stats(varargin) +% +% PURPOSE: Plots the output statistics of a parameter-space exploration +% +% ARGUMENTS: +% +% dir_name The name of the directory that the samples are stored in. +% +% OPTIONS (name, description, type, default): +% + + description = 'Plots the output statistics of a parameter-space exploration'; + + arguments = {'dir_name', 'The name of the directory that the samples are stored in.'}; + + options = {... + 'chunk_to_plot', 1, 'int', 'Index of the chunk which will be plotted';... +...% 'strand_radius ', 0.02, 'float', 'Radii of the plotted strands';... + }; + + % Call a script called 'parse_arguments' to parse all arguments and + % options and set the desired variables. + + parse_arguments + if (help_display) return; end + + stats_types = {... + 'strong_dist';... + 'strong_px';... + ...%'strong_central_px';... + 'weak_dist';... + 'weak_px';... + ...%'weak_central_px';... + ...%'max_arc_top_dist'... + } + + stats = []; + + for stats_i = 1:length(stats_types) + + loaded_stats = load([dir_name '/' stats_types{stats_i} '.txt']); + + if size(loaded_stats,1) > 10000 + loaded_stats = loaded_stats(1:10000); + end + + stats = [stats reshape(loaded_stats, [size(loaded_stats,1) 1 size(loaded_stats,2)])]; + + end + + reshape_vector = [size(stats,1) * size(stats,3) , 1]; + + f = figure; + set(f, 'Name', 'Strong'); + + scatter(reshape(stats(:,1,:),reshape_vector), reshape(stats(:,2,:), reshape_vector)); + whitebg('black'); + + g = figure; + set(g, 'Name', 'Weak'); + scatter(reshape(stats(:,3,:),reshape_vector), reshape(stats(:,4,:), reshape_vector)); + whitebg('black'); + + + figure; + plot(stats(:,:,chunk_to_plot)); + whitebg('black'); + legend(strrep(stats_types(:), '_', ' ')); +% legend('distance', 'full-strong', 'outside-weak', 'outside-strong','central-voxel', 'b0'); + legend('Location', 'EastOutside'); +end diff --git a/matlab/plot_extend_elem_properties.m b/matlab/plot_extend_elem_properties.m new file mode 100644 index 0000000..7c82dfe --- /dev/null +++ b/matlab/plot_extend_elem_properties.m @@ -0,0 +1,102 @@ +function fig = plot_extend_elem_properties(figure_name, all_prop_keys, all_prop_values, bundle_colours, include, elem_include, fig_index, num_figures, omit_properties) +%Not implemented yet. + + if ~exist('include','var') + include = []; + end + + if ~exist('elem_include','var') + elem_include = []; + end + + if ~exist('fig_index', 'var') + fig_index = 3; + end + + if ~exist('num_figures', 'var') + num_figures = 3; + end + + if ~exist('omit_properties', 'var') + omit_properties = cell(0); + end + + if ~isempty(all_prop_keys) + + if ~isempty(omit_properties) + prop_keys = []; + + for key_i = 1:length(all_prop_keys) + + omit = 0; + + for omit_i = 1:length(omit_properties) + if strfind(omit_properties{omit_i}, all_prop_keys{key_i}) + omit = 1; + break; + end + end + + if ~omit + prop_keys{length(prop_keys)+1} = all_prop_keys{key_i}; %#ok + end + + end + else + prop_keys = all_prop_keys; + end + + if isempty(include) + include = [1:size(all_prop_values,1)]; + end + + + fig = my_figure(figure_name,fig_index,num_figures,[]); + + num_keys = length(prop_keys); + + for key_i = 1:num_keys + + key = prop_keys(key_i); + + all_props = []; + + for set_i = include + + prop_values = all_prop_values{set_i}; + + if ~isempty(elem_include) + prop_values = prop_values(elem_include+1,:); + end + + all_props = [all_props; get_properties(prop_keys, prop_values, key)']; + + end + + if strcmp(key,'tract_volume') + all_props = all_props * (pi / 0.15^2); + sum(all_props) ./ size(all_props,1) + end + + num_strands = size(all_props,2); + + subplot(num_keys,1,key_i); + set(gca, 'NextPlot', 'ReplaceChildren'); + + if isempty(elem_include) + colour_order = 1:num_strands; + else + colour_order = elem_include + 1; + end + + set(gca, 'ColorOrder', bundle_colours(colour_order,:)); + plot(include, all_props); + ylabel(strrep(key,'_',' ')); + + end + + else + disp('No extended, extended properties found'); + fig = []; + end +end diff --git a/matlab/plot_extend_properties.m b/matlab/plot_extend_properties.m new file mode 100644 index 0000000..8724c75 --- /dev/null +++ b/matlab/plot_extend_properties.m @@ -0,0 +1,63 @@ +function fig = plot_extend_elem_properties(figure_name, prop_keys, prop_values, include, fig_index, num_figures) + + + if ~exist('include', 'var') + include = []; + end + + if ~exist('fig_index', 'var') + fig_index = 2; + end + + if ~exist('num_figures', 'var') + num_figures = 3; + end + + + if ~isempty(prop_keys) + num_values = size(prop_values,1); + + if isempty(include) + include = [1:num_values]; + end + + fig = my_figure(figure_name,fig_index,num_figures,[]); + + all_props = []; + + legend_keys = cell(0); + + for key = prop_keys + +% if ~strcmp(key,'elapsed_time') + + props = get_properties(prop_keys, prop_values, key); + props = props(include); + + max_abs_value = max([abs(max(props)) abs(min(props))]); + + if (max_abs_value > 0) + sci_notation = ceil(log10(max_abs_value)); + else + sci_notation = 1; + end + + props = props ./ (10^sci_notation); + + all_props = [all_props, props]; + legend_keys(end+1) = strcat(strrep(key,'_',' '), ' x 10^{', num2str(sci_notation),'}'); + +% end + + end + + set(gca, 'NextPlot', 'ReplaceChildren'); + set(gca, 'LineStyleOrder', {'-',':','--'}); + plot(include-1, all_props); + set(gca, 'ytick', [-1:0.05:1]); + legend(legend_keys); + else + disp('No extended properties found.'); + fig = []; + end +end diff --git a/matlab/plot_extracted_features.m b/matlab/plot_extracted_features.m new file mode 100644 index 0000000..1efc37a --- /dev/null +++ b/matlab/plot_extracted_features.m @@ -0,0 +1,48 @@ +function plot_extracted_features(directory) + +global v0_norm v1_norm v2_norm dot_v1_v2 dot_v0_v1 angle_v1_v2 + +load([ directory '/angle_v1_v2.txt']); + +load([ directory '/dot_v0_v1.txt']); +load([ directory '/dot_v1_v2.txt']); +load([ directory '/v0_norm.txt']); +load([ directory '/v1_norm.txt']); +load([ directory '/v2_norm.txt']); + +figure_start = gcf + 1; + +figure(figure_start+1); +hist(v0_norm,1000) +title('v0 norm'); + +figure(figure_start+2); +hist(v1_norm,1000) +title('v1 norm'); + +figure(figure_start+3); +hist(v2_norm,1000) +title('v2 norm'); + +figure(figure_start+4); +hist(dot_v1_v2,1000) +title('dot v1 v2'); + +figure(figure_start+5); +hist(dot_v0_v1,1000) +title('dot v0 v1'); + +% figure(6); +% hist(angle_v1_v2,1000) +% title('angle v1 v2'); + +figure(figure_start+7); +hist2d(dot_v1_v2, v2_norm,100); +title('dot v1 v2 - v2 norm'); + +figure(figure_start+8); +hist2d(dot_v0_v1, v0_norm,100); +title('dot v0 v1 - v0 norm'); + + +end \ No newline at end of file diff --git a/matlab/plot_features.m b/matlab/plot_features.m new file mode 100644 index 0000000..f73e828 --- /dev/null +++ b/matlab/plot_features.m @@ -0,0 +1,276 @@ +function plot_features(features_dir, varargin) +% +% PURPOSE: Plots histograms of prior distributions collated by extract_features.cpp +% +% ARGUMENTS: +% +% features_directory The directory containing the features text files. +% +% OPTIONS (name, description, type, default): +% +% -all Plots all the features. Overrides all other flags +% bool +% 0 +% +% -v0_norm Plot the norm of the v0 vector +% bool +% 0 +% +% -v1_norm Plot the norm of the v1 vector +% bool +% 0 +% +% -v2_norm Plot the norm of the v2 vector +% bool +% 0 +% +% -dot_v1_v2 Plot the dot product of the v1 and v2 vectors +% bool +% 0 +% +% -angle_v1_v2 Plot the angle between the v1 and v2 vectors +% bool +% 0 +% +% -dot_v0_v1 Plot the dot product of the v0 and v1 vectors +% bool +% 0 + + + + if ~isdir(features_dir) + error(['Argument 1 (''' features_dir ''') is not a directory, it should be a directory containing the features text files.']); + end + + description = 'Plots histograms of prior distributions collated by extract_features.cpp'; + + arguments = {'features_directory', 'The directory containing the features text files.'}; + + options = {... + 'plot_all ', 0, 'bool', 'Plots all the features. Overrides all other flags';... + 'v0_norm ', 0, 'bool', 'Plot the norm of the v0 vector';... + 'v1_norm ', 0, 'bool', 'Plot the norm of the v1 vector';... + 'v2_norm ', 0, 'bool', 'Plot the norm of the v2 vector';... + 'dot_v1_v2 ', 0, 'bool', 'Plot the dot product of the v1 and v2 vectors';... + 'angle_v1_v2 ', 0, 'bool', 'Plot the angle between the v1 and v2 vectors';... + 'dot_v0_v1 ', 0, 'bool', 'Plot the dot product of the v0 and v1 vectors';... + 'd2_v0_v1_dot ', 0, 'bool', 'Plot the dot product of the v0 and v1 vectors against norm of v0 on a d2 histogram';... + 'd2_v1_v2_dot ', 0, 'bool', 'Plot the dot product of the v1 and v2 vectors against norm of v2 on a d2 histogram';... + 'd2_v0_v1_norm', 0, 'bool', 'Plot the v0 and v1 norms against each other in 2d histogram';... + 'd2_v1_v2_norm', 0, 'bool', 'Plot the v1 and v2 norms against each other in 2d histogram';... + 'd2_v0_v2_norm', 0, 'bool', 'Plot the v0 and v2 norms against each other in 2d histogram'... + }; + + supplied_options = parse_options(options, varargin); + + for option_i = 1:size(supplied_options,1) + if strcmp(supplied_options{option_i,3}, 'string') + eval([supplied_options{option_i,1} ' = ''' supplied_options{option_i,2} ''';']); + else + + if ~isstr(supplied_options{option_i,2}) + supplied_options{option_i,2} = mat2str(supplied_options{option_i,2}); + end + + eval([supplied_options{option_i,1} ' = ' supplied_options{option_i,2} ';']); + end + end + + + if help_display + display_help_message(description, arguments, options); + return; + end + +num_options_selected = 0; + +for option_i = 1:size(options,1) + + if eval(options{option_i,1}) + num_options_selected = num_options_selected + 1; + end + + if plot_all + eval([options{option_i} '= 1']); + end + +end + +if ~num_options_selected + error('No options selected, use ''-help'' to display possible options.'); +end + +% if ~plot_all && ~v0_norm && ~v1_norm && ~v2_norm && ~dot_v1_v2 && ~dot_v0_v1 && ~angle_v1_v2 && ~d2_v0_v1_norm && ~d2_v1_v2_norm && ~d2_v0_v2_norm && ~d2_v1_v2_dot && ~d2_v0_v1_dot +% error('No options selected, use ''-help'' to display possible options.'); +% end + +% if plot_all +% v0_norm = 1; +% v1_norm = 1; +% v2_norm = 1; +% dot_v1_v2 = 1; +% angle_v1_v2 = 1; +% dot_v0_v1 = 1; +% d2_v0_v1_dot = 1; +% d2_v1_v2_dot = 1; +% d2_v0_v1_norm = 1; +% d2_v1_v2_norm = 1; +% d2_v0_v2_norm = 1; +% end + +if v0_norm || d2_v0_v1_dot || d2_v0_v2_norm || d2_v0_v1_norm + v0_norm_data = load([ features_dir '/v0_norm.txt']); +end + +if v1_norm || d2_v0_v1_norm || d2_v1_v2_norm + v1_norm_data = load([ features_dir '/v1_norm.txt']); +end + +if v2_norm || d2_v1_v2_dot || d2_v0_v2_norm || d2_v1_v2_norm + v2_norm_data = load([ features_dir '/v2_norm.txt']); +end + +if dot_v1_v2 || d2_v1_v2_dot + dot_v1_v2_data = load([ features_dir '/dot_v1_v2.txt']); +end + +if angle_v1_v2 + angle_v1_v2_data = load([ features_dir '/angle_v1_v2.txt']); +end + +if dot_v0_v1 || d2_v0_v1_dot + dot_v0_v1_data = load([ features_dir '/dot_v0_v1.txt']); +end + + + + + +if v0_norm + f = figure(); + set(f,'Units','normalized'); + set(f, 'Position', [0.3 0.25 0.4 0.5]); + set(f, 'Name', strrep(features_dir,'_',' ')); + + hist(v0_norm_data,100); + title('v0 norm'); + +end + +if v1_norm + f = figure(); + set(f,'Units','normalized'); + set(f, 'Name', strrep(features_dir,'_',' ')); + hist(v1_norm_data,100); + set(f, 'Position', [0.3 0.25 0.4 0.5]); + title('v1 norm'); + +end + +if v2_norm + f = figure(); + set(f,'Units','normalized'); + set(f, 'Name', strrep(features_dir,'_',' ')); + hist(v2_norm_data,100); + set(f, 'Position', [0.3 0.25 0.4 0.5]); + title('v2 norm'); + +end + +if dot_v1_v2 + f = figure(); + set(f,'Units','normalized'); + set(f, 'Name', strrep(features_dir,'_',' ')); + hist(dot_v1_v2_data,100); + set(f, 'Position', [0.3 0.25 0.4 0.5]); + title('dot v1 v2'); + +end + +if angle_v1_v2 + f = figure(); + set(f,'Units','normalized'); + hist(angle_v1_v2_data,100); + set(f, 'Position', [0.3 0.25 0.4 0.5]); + title('angle v1 v2'); + +end + +if dot_v0_v1 + f = figure(); + set(f,'Units','normalized'); + set(f, 'Name', strrep(features_dir,'_',' ')); + hist(dot_v0_v1_data,100); + set(f, 'Position', [0.3 0.25 0.4 0.5]); + title('dot v0 v1'); + +end + +if d2_v0_v1_dot + f = figure(); + set(f,'Units','normalized'); + set(f, 'Name', strrep(features_dir,'_',' ')); + title('dot v0 v1 - v0 norm'); + set(f, 'Position', [0.3 0.25 0.4 0.5]); + hist2d(dot_v0_v1_data, v0_norm_data,100,100); + +% cameratoolbar('Show'); +% cameratoolbar('SetMode','orbit'); + +end + +if d2_v1_v2_dot + f = figure(); + set(f,'Units','normalized'); + + title('dot v1 v2 - v2 norm'); + set(f, 'Position', [0.3 0.25 0.4 0.5]); + set(f, 'Name', strrep(features_dir,'_',' ')); + hist2d(dot_v1_v2_data, v2_norm_data,100,100); + +% cameratoolbar('Show'); +% cameratoolbar('SetMode','orbit'); + +end + +if d2_v0_v2_norm + f = figure(); + set(f,'Units','normalized'); + set(f, 'Name', strrep(features_dir,'_',' ')); + title('v0 norm - v2 norm'); + set(f, 'Position', [0.3 0.25 0.4 0.5]); + hist2d(v0_norm_data, v2_norm_data,100,100); + +% cameratoolbar('Show'); +% cameratoolbar('SetMode','orbit'); + +end + +if d2_v1_v2_norm + f = figure(); + set(f,'Units','normalized'); + + title('v1 norm - v2 norm'); + set(f, 'Position', [0.3 0.25 0.4 0.5]); + set(f, 'Name', strrep(features_dir,'_',' ')); + hist2d(v1_norm_data, v2_norm_data,100,100); + +% cameratoolbar('Show'); +% cameratoolbar('SetMode','orbit'); + +end + +if d2_v0_v1_norm + f = figure(); + set(f,'Units','normalized'); + + title('v0 norm - v2 norm'); + set(f, 'Position', [0.3 0.25 0.4 0.5]); + set(f, 'Name', strrep(features_dir,'_',' ')); + hist2d(v0_norm_data, v1_norm_data,100,100); + +% cameratoolbar('Show'); +% cameratoolbar('SetMode','orbit'); + +end + diff --git a/matlab/plot_fibres.m b/matlab/plot_fibres.m new file mode 100644 index 0000000..d206cf5 --- /dev/null +++ b/matlab/plot_fibres.m @@ -0,0 +1,25 @@ +function fig = plot_fibres(varargin) + + if nargin == 0 + error('No arguments supplied'); + end + + filename = varargin{1}; + + if file_extension(filename) == 'str' + fig = plot_strands(varargin{:}); + elseif file_extension(filename) == 'sst' + fig = plot_strand_sets(varargin{:}); + elseif file_extension(filename) == 'tct' + fig = plot_tracts(varargin{:}); + elseif file_extension(filename) == 'tst' + fig = plot_tract_sets(varargin{:}); + elseif file_extension(filename) == 'tck' + fig = plot_tcks(varargin{:}); + elseif file_extension(filename) == 'kst' + fig = plot_tck_sets(varargin{:}); + else + error(['Unrecognised extension, ''' file_extension(filename) '''.']); + end + +end \ No newline at end of file diff --git a/matlab/plot_fisher_gradient.m b/matlab/plot_fisher_gradient.m new file mode 100644 index 0000000..e5d292d --- /dev/null +++ b/matlab/plot_fisher_gradient.m @@ -0,0 +1,200 @@ +function plot_fisher_gradient(varargin) +% +% PURPOSE: Plots the difference between the analytically calculated gradient and the numerically calculated gradient. +% +% ARGUMENTS: +% +% comparison_files The filename containing the comparison between the analytical and numerical gradients. +% +% OPTIONS (name, description, type, default): +% +% -style +% Style of the plot. +% string +% 'x' +% +% -marker_size +% Size of marker +% int +% 10 +% +% -line_width +% Width of line +% int +% 2 +% +% -param_include +% Parameters to include in the plots. +% matrix_1x: +% +% -test_include +% Tests to include in the plots. +% matrix_1x: + + + description = 'Plots the difference between the analytically calculated gradient and the numerically calculated gradient.'; + + arguments = {'comparison_files', 'The filename containing the comparison between the analytical and numerical gradients.'}; + + options = {... + 'style ', 'x', 'string', 'Style of the plot.';... + 'marker_size ', 10, 'int', 'Size of marker';... + 'line_width ', 2, 'int', 'Width of line';... + 'param_include', [], 'matrix_1x:', 'Parameters to include in the plots.';... + 'coords', [], 'matrix_:x3', 'Selected coordinates to plot.';... + 'indices', [], 'matrix_:x:', 'Selected indices to plot.';... + 'test_include', [], 'matrix_1x:', 'Tests to include in the plots.';... + }; + + + parse_arguments + if (help_display) + return; + end + +% End arguments % + + + extension = file_extension(comparison_files); + base = file_base(comparison_files); + + if ~strcmp(extension, 'tnr') + error(['Files must have ''tnr'' extension for Fisher gradients.']); + end + + base_extension = file_extension(base); + base_base = file_base(base); + + [analytic, labels] = load_tensor([base_base '.analytic.' base_extension '.' extension]); + numeric = load_tensor([base_base '.numeric.' base_extension '.' extension]); + + if any(size(analytic) ~= size(numeric)) + error(['Size of analytic (' mat2str(size(analytic)) ') does not match size of numeric (' mat2str(size(numeric)) ').']); + end + + %Ensure matrices are of the same size. + num_parameters = size(analytic,1); + num_tensors = size(analytic,3); + + if size(analytic,2) ~= num_parameters + error('Matrices not square.'); + end + + if mod(num_tensors, num_parameters) ~= 0 + error(['Number of parameters (' num2str(num_parameters) ') does not divide into number of matrices (' num2str(num_tensors) ').']); + end + + num_tests = num_tensors / num_parameters; + + if ~isempty(coords) + + analytic_block = reshape(analytic, [num_parameters, num_parameters, num_parameters, num_tests]); + numeric_block = reshape(numeric, [num_parameters, num_parameters, num_parameters, num_tests]); + + sum_ana = sum(analytic_block,4); + sum_num = sum(numeric_block,4); + + ana_bin = abs(sum_ana) > 0; + num_bin = abs(sum_num) > 0; + + tog_bin = ana_bin .* num_bin; + just_ana = ana_bin - tog_bin; + just_num = num_bin - tog_bin; + + [t1,t2,t3] = ind2sub([num_parameters,num_parameters,num_parameters],find(tog_bin)); + [a1,a2,a3] = ind2sub([num_parameters,num_parameters,num_parameters],find(just_ana)); + [n1,n2,n3] = ind2sub([num_parameters,num_parameters,num_parameters],find(just_num)); + + tog = [t1,t2,t3] + ana = [a1,a2,a3] + num = [n1,n2,n3] + + num_coords = size(coords,1); + + for coord_i=1:num_coords + + analytic = squeeze(analytic_block(coords(coord_i,1),coords(coord_i,2),coords(coord_i,3),:)); + numeric = squeeze(numeric_block(coords(coord_i,1),coords(coord_i,2),coords(coord_i,3),:)); + + my_figure( [num2str(coords(coord_i)) ' - ' labels{coords(coord_i,1)} '::' labels{coords(coord_i,2)} '::' labels{coords(coord_i,3)} ] ,coord_i,num_coords,[]); + + plot(numeric, analytic, style, 'MarkerSize', marker_size, 'LineWidth',line_width); + + set(get(gca,'xlabel'), 'string', 'numeric', 'color', [1 1 1]); + set(get(gca,'ylabel'), 'string', 'analytic', 'color', [1 1 1]); + + hold on; + + overall_max_value = max(max([numeric,analytic])) * 1.1; + overall_min_value = min(min([numeric,analytic])) * 1.1; + + plot([overall_min_value; overall_max_value], [overall_min_value; overall_max_value], '-', 'color', [0.7412 0.6549 0.9608]); + + hold off; + + end + + elseif ~isempty(indices) + + analytic_block = reshape(analytic, [num_parameters^3, num_tests]); + numeric_block = reshape(numeric, [num_parameters^3, num_tests]); + + num_indices = length(indices); + + for index_i=1:num_indices + + index = indices(index_i); + + analytic = analytic_block(index,:); + numeric = numeric_block(index,:); + + [ax1,ax2,ax3] = ind2sub([num_parameters,num_parameters,num_parameters],index); + + my_figure( [num2str(index) ' - ' labels{ax1} '::' labels{ax2} '::' labels{ax3} ] ,index_i,num_indices,[]); + + plot(numeric, analytic, style, 'MarkerSize', marker_size, 'LineWidth',line_width); + + set(get(gca,'xlabel'), 'string', 'numeric', 'color', [1 1 1]); + set(get(gca,'ylabel'), 'string', 'analytic', 'color', [1 1 1]); + + hold on; + + overall_max_value = max(max([numeric,analytic])) * 1.1; + overall_min_value = min(min([numeric,analytic])) * 1.1; + + plot([overall_min_value; overall_max_value], [overall_min_value; overall_max_value], '-', 'color', [0.7412 0.6549 0.9608]); + + hold off; + + end + + + + else + + analytic = analytic(:); + numeric = numeric(:); + + my_figure('All parameters',1,1,[]); + + plot(numeric, analytic, style, 'MarkerSize', marker_size, 'LineWidth',line_width); + + set(get(gca,'xlabel'), 'string', 'numeric', 'color', [1 1 1]); + set(get(gca,'ylabel'), 'string', 'analytic', 'color', [1 1 1]); + + hold on; + + overall_max_value = max(max([numeric,analytic])) * 1.1; + overall_min_value = min(min([numeric,analytic])) * 1.1; + + plot([overall_min_value; overall_max_value], [overall_min_value; overall_max_value], '-', 'color', [0.7412 0.6549 0.9608]); + + hold off; + + end + + disp('') + disp(['Plotted ' num2str(num_tests) ' tests.']); + disp('') + +end \ No newline at end of file diff --git a/matlab/plot_gradient.m b/matlab/plot_gradient.m new file mode 100644 index 0000000..0d460ce --- /dev/null +++ b/matlab/plot_gradient.m @@ -0,0 +1,163 @@ +function plot_gradient(varargin) +% +% PURPOSE: Plots the difference between the analytically calculated gradient and the numerically calculated gradient. +% +% ARGUMENTS: +% +% comparison_files The filename containing the comparison between the analytical and numerical gradients. +% +% OPTIONS (name, description, type, default): +% +% -style +% Style of the plot. +% string +% 'x' +% +% -marker_size +% Size of marker +% int +% 10 +% +% -line_width +% Width of line +% int +% 2 +% +% -param_include +% Parameters to include in the plots. +% matrix_1x: +% +% -test_include +% Tests to include in the plots. +% matrix_1x: + + + description = 'Plots the difference between the analytically calculated gradient and the numerically calculated gradient.'; + + arguments = {'comparison_files', 'The filename containing the comparison between the analytical and numerical gradients.'}; + + options = {... + 'style ', 'x', 'string', 'Style of the plot.';... + 'marker_size ', 10, 'int', 'Size of marker';... + 'line_width ', 2, 'int', 'Width of line';... + 'param_include', [], 'matrix_1x:', 'Parameters to include in the plots.';... + 'test_include', [], 'matrix_1x:', 'Tests to include in the plots.';... + }; + + + parse_arguments + if (help_display) + return; + end + +% End arguments % + + + extension = file_extension(comparison_files); + base = file_base(comparison_files); + + %Load numeric and analytic gradients in 'unzipped' (flattened into vectors) formats. + if strcmp(extension, 'str') + + [analytic, labels] = load_unzip_strands([base '.analytic.' extension]); + numeric = load_unzip_strands([base '.numeric.' extension]); + + elseif strcmp(extension, 'tct') + + [analytic, labels] = load_unzip_tracts([base '.analytic.tct']); + numeric = load_unzip_tracts([base '.numeric.' extension]); + + elseif strcmp(extension, 'sst') + + [analytic, labels] = load_unzip_strand_sets([base '.analytic.' extension]); + numeric = load_unzip_strand_sets([base '.numeric.' extension]); + + elseif strcmp(extension, 'tst') + + [analytic, labels] = load_unzip_tract_sets([base '.analytic.' extension]); + numeric = load_unzip_tract_sets([base '.numeric.' extension]); + + elseif strcmp(extension, 'ssc') + + [analytic, labels] = load_unzip_strand_sections([base '.analytic.' extension]); + numeric = load_unzip_strand_sections([base '.numeric.' extension]); + + elseif strcmp(extension, 'tsc') + + [analytic, labels] = load_unzip_tract_sections([base '.analytic.' extension]); + numeric = load_unzip_tract_sections([base '.numeric.' extension]); + + elseif strcmp(extension, 'trp') + + [analytic, labels] = load_unzip_triples([base '.analytic.' extension]); + numeric = load_unzip_triples([base '.numeric.' extension]); + + elseif strcmp(extension, 'mif') + + [analytic, labels] = load_unzip_image([base '.analytic.' extension]); + numeric = load_unzip_image([base '.numeric.' extension]); + + elseif strcmp(extension, 'sta') + + [analytic, labels] = load_unzip_mcmc_state([base '.analytic.' extension]); + numeric = load_unzip_mcmc_state([base '.numeric.' extension]); + + else + error(['Unrecognised extension ''' char(extension) '''.']); + end + + + %Ensure matrices are of the same size. + num_parameters = size(analytic,1); + + if num_parameters ~= size(numeric,1); + error (['Number of parameters in numeric matrix (' num2str(size(numeric,1)) ') does not match number in analytic matrix (' num2str(num_parameters) ').']); + end + + num_tests = size(analytic,2); + + if num_tests ~= size(numeric,2); + error (['Number of parameters in numeric matrix (' num2str(size(numeric,2)) ') does not match number in analytic matrix (' num2str(num_tests) ').']); + end + + %Set to display to all comparisons if not selection explicitly provided. + if isempty(param_include) + param_include = 1:num_parameters; + end + + if isempty(test_include) + test_include = 1:num_tests; + end + + num_param_include = length(param_include(:)); + + %Plot comparisons. + for param_index_i = 1:num_param_include + + param_index = param_include(param_index_i); + + numeric_param = numeric(param_index, test_include)'; + analytic_param = analytic(param_index, test_include)'; + + my_figure(labels{param_index}, param_index_i, num_param_include); + plot(numeric_param, analytic_param, style, 'MarkerSize', marker_size, 'LineWidth',line_width); + + set(get(gca,'xlabel'), 'string', 'numeric', 'color', [1 1 1]); + set(get(gca,'ylabel'), 'string', 'analytic', 'color', [1 1 1]); + + min_value = min([numeric_param; analytic_param]) * 1.1; + max_value = max([numeric_param; analytic_param]) * 1.1; + + hold on; + + plot([min_value; max_value], [min_value; max_value], '-', 'color', [0.7412 0.6549 0.9608]); + + hold off; + + end + + disp('') + disp(['Plotted ' num2str(num_tests) ' tests.']); + disp('') + +end diff --git a/matlab/plot_hessian.m b/matlab/plot_hessian.m new file mode 100644 index 0000000..b91c0a4 --- /dev/null +++ b/matlab/plot_hessian.m @@ -0,0 +1,148 @@ +function plot_hessian(varargin) +% +% PURPOSE: Plots the difference between the analytically calculated gradient and the numerically calculated gradient. +% +% ARGUMENTS: +% +% comparison_files The filename containing the comparison between the analytical and numerical gradients. +% +% OPTIONS (name, description, type, default): +% +% -style +% Style of the plot. +% string +% 'x' +% +% -marker_size +% Size of marker +% int +% 10 +% +% -line_width +% Width of line +% int +% 2 +% +% -param_include +% Parameters to include in the plots. +% matrix_1x: +% +% -test_include +% Tests to include in the plots. +% matrix_1x: + + + description = 'Plots the difference between the analytically calculated gradient and the numerically calculated gradient.'; + + arguments = {'comparison_files', 'The filename containing the comparison between the analytical and numerical gradients.'}; + + options = {... + 'style ', 'x', 'string', 'Style of the plot.';... + 'marker_size ', 10, 'int', 'Size of marker';... + 'line_width ', 2, 'int', 'Width of line';... + 'index_include', [], 'matrix_1x:', 'Parameter indices to include in the plots (overrides coord_include).';... + 'coord_include', [], 'matrix_:x:', 'Parameter coordinates to include in the plots.';... + 'test_include', [], 'matrix_1x:', 'Tests to include in the plots.';... + 'diagonal', 0, 'bool', 'Only displays diagonal components';... + 'collapse', 0, 'bool', 'Collapse all plots into single one';... + }; + + + parse_arguments + if (help_display) + return; + end + +% End arguments % + + + extension = file_extension(comparison_files); + base = file_base(comparison_files); + + if ~strcmp(extension, 'tnr') + error(['Files must have ''tnr'' extension for tensors.']); + end + + base_extension = file_extension(base); + base_base = file_base(base); + + [analytic, labels] = load_tensor([base_base '.analytic.' base_extension '.' extension]); + numeric = load_tensor([base_base '.numeric.' base_extension '.' extension]); + + if any(size(analytic) ~= size(numeric)) + error(['Size of analytic (' mat2str(size(analytic)) ') does not match size of numeric (' mat2str(size(numeric)) ').']); + end + + %Ensure matrices are of the same size. + num_parameters = size(analytic,1); + num_tests = size(analytic,3); + + if size(analytic,2) ~= num_parameters + error('Matrices not square.'); + end + + %Set to display to all comparisons if not selection explicitly provided. + if diagonal + for param_i = 1:num_parameters + coord_include(param_i,:) = [param_i param_i]; + end + + elseif ~isempty(index_include) + + [row col] = ind2sub([num_parameters, num_parameters], index_include); + + coord_include = [row' col']; + + elseif isempty(coord_include) + param_count = 1; + for row_i = 1:num_parameters + for col_i = 1:num_parameters + coord_include(param_count,:) = [row_i col_i]; + param_count = param_count +1; + end + end + end + + if isempty(test_include) + test_include = 1:num_tests; + end + + num_param_include = size(coord_include,1); + + if collapse + my_figure('All parameters'); + end + + %Plot comparisons. + for param_index_i = 1:num_param_include + + param_index = coord_include(param_index_i,:); + + numeric_param = squeeze(numeric(param_index(1), param_index(2), test_include)); + analytic_param = squeeze(analytic(param_index(1), param_index(2), test_include)); + + if ~collapse + my_figure([labels{param_index(1)}(1:end) ' :: ' labels{param_index(2)}(1:end)], param_index_i, num_param_include); + end + + plot(numeric_param, analytic_param, style, 'MarkerSize', marker_size, 'LineWidth',line_width); + + set(get(gca,'xlabel'), 'string', 'numeric', 'color', [1 1 1]); + set(get(gca,'ylabel'), 'string', 'analytic', 'color', [1 1 1]); + + min_value = min([numeric_param; analytic_param]) * 1.1; + max_value = max([numeric_param; analytic_param]) * 1.1; + + hold on; + + plot([min_value; max_value], [min_value; max_value], '-', 'color', [0.7412 0.6549 0.9608]); + + hold off; + + end + + disp('') + disp(['Plotted ' num2str(num_tests) ' tests.']); + disp('') + +end diff --git a/matlab/plot_image.m b/matlab/plot_image.m new file mode 100644 index 0000000..2dffd71 --- /dev/null +++ b/matlab/plot_image.m @@ -0,0 +1,252 @@ +function fig = plot_image(varargin) +% +% +% PURPOSE: Plots DW-MRI signals from a neighbourhood of voxels on a 3D grid +% +% +% ARGUMENTS: +% +% image_filename The filename of the generated image in .mif format. +% +% +% OPTIONS (name, description, type, default): +% +% -no_neg_values No negative values will be plotted +% bool +% 0 +% +% -corner_offset Offset of the bottom-left-back corner of the neighbourhood +% matrix_1x3 +% minus half the neighbourhood dimension length +% +% -scale_signal Scaling factor will be scaled by +% float +% automatically determined from signal +% +% -colour Colour of the non-negative lobes of the signal +% matrix_1x3 +% [1 1 0] +% +% -transparency Transparency of the lobes +% float +% 1 +% +% -neg_colour Colour of the negative lobes of the signal +% matrix_1x3 +% [1 1 1] +% +% -grad_directions Gradient encoding used. +% string +% '/data/home/tclose/Data/Gradient_directions/encoding_60.b' +% +% -plot_directions The direction encoding used for the plotting. +% string +% '/data/home/tclose/Data/Gradient_directions/encoding_8000.b' +% +% -lmax The lmax of the gradient encodings used. +% natural +% 8 +% +% + + + + description = 'Plots DW-MRI signals from a neighbourhood of voxels on a 3D grid'; + + arguments = {'image_filename', 'The filename of the generated image in .mif format.'}; + + if strfind('-help_display', arguments{1}) == 1 + + auto_offset = 'auto_scale'; + auto_scale = 'auto_offset'; + + help_display = 1; + + else + + image_filename = varargin{1}; + + img_struct = load_image(image_filename); + + if (~isfield(img_struct, 'data')) + error(['Could not read image from file ' image_filename]); + end + + img = img_struct.data; + max_intensity = max(max(max(max(abs(img(:,:,:,2:end)))))); + max_b0 = max(max(max(max(abs(img(:,:,:,1)))))); + + if max_intensity == 0 + error('Neighbourhood contains no signal'); + end + + auto_offset = [(-img_struct.vox(1) * img_struct.dim(1) * 0.5), (-img_struct.vox(2) * img_struct.dim(2) * 0.5), (-img_struct.vox(3) * img_struct.dim(3) * 0.5)]; + auto_scale = min(img_struct.vox) / ( 2.25 * max_intensity); + + + end + + options = {... + 'no_neg_values ', 0, 'bool', 'No negative values will be plotted';... + 'corner_offset ', auto_offset,... + 'matrix_1x3', 'Offset of the bottom-left-back corner of the neighbourhood';... + 'scale_signal ', auto_scale,... + 'float', 'Scaling factor will be scaled by';... + 'colour ', [1 1 0], 'matrix_1x3', 'Colour of the non-negative lobes of the signal';... + 'transparency ', 1.0, 'float', 'Transparency of the lobes';... + 'neg_colour ', [1 1 1], 'matrix_1x3', 'Colour of the negative lobes of the signal';... + 'grad_directions', '/home/tclose/Data/Tractography/diffusion/encoding/encoding_60.b',... + 'string', 'Gradient encoding used.';... + 'plot_directions', '/home/tclose/Data/Tractography/diffusion/encoding/encoding_1000.b',... + 'string', 'The direction encoding used for the plotting.';... + 'lmax ', 8, 'natural', 'The lmax of the gradient encodings used.'};... + + + + parse_arguments + if (help_display) + return; + end + + + grad_directions_mat = load(grad_directions); + plot_directions_mat = load(plot_directions); + + gradient_scheme = gen_scheme(grad_directions_mat(:,1:3), lmax); + plot_scheme = gen_scheme(plot_directions_mat(:,1:3), lmax); + + disp(''); + disp('-------------------------------'); + disp(' Image Properties: '); + disp('-------------------------------'); + if isfield (img_struct, 'num_points') + disp([' Number of points: ' num2str(img_struct.num_points)]); + elseif isfield (img_struct, 'num_segments') + disp([' Number of segments: ' num2str(img_struct.num_segments)]); + end + if isfield (img_struct, 'num_strands') + disp([' Number of strands per tract dimension: ' num2str(img_struct.num_strands) '']); + end + if isfield (img_struct, 'state_location') + disp([' State location: ''' img_struct.state_location '''']); + end + if isfield (img_struct, 'interpolation') + disp([' Interpolation type: ''' img_struct.interpolation '''']); + end + if isfield (img_struct, 'response_coeffs') + disp([' Response coefficients: ' img_struct.response_coeffs]); + end + if isfield (img_struct, 'software_version') + disp([' Software version: ' img_struct.software_version ]); + end + if isfield (img_struct, 'datetime') + disp([' Generated: ' img_struct.datetime ]); + end + disp('-------------------------------'); + + + + fig = my_figure([image_filename ': (Max: ' num2str(max_intensity) ', b=0: ' num2str(max_b0) ')'], 1, 1, [1 1 1], 1); + +% fig = figure(); +% +% set(fig,'Units','normalized') +% set(fig, 'Position', [0.3 0.25 0.4 0.5]); +% set(fig, 'DoubleBuffer', 'on'); +% whitebg(fig, 'black'); +% set(fig, 'color', [0 0 0]); +% daspect ([ 1 1 1 ]); +% +% cameratoolbar('Show'); +% cameratoolbar('SetMode','orbit'); + + set(gca, 'Xlim', [corner_offset(1) corner_offset(1) + img_struct.vox(1) * img_struct.dim(1)]); + set(gca, 'Ylim', [corner_offset(2) corner_offset(2) + img_struct.vox(2) * img_struct.dim(2)]); + set(gca, 'Zlim', [corner_offset(3) corner_offset(3) + img_struct.vox(3) * img_struct.dim(3)]); + + xlabel('x-axis'); + ylabel('y-axis'); + zlabel('z-axis'); + + hold on; + + count = 0; + + + for (z = 1:img_struct.dim(3)) + + for (y = 1:img_struct.dim(2)) + + for (x = 1:img_struct.dim(1)) + + + voxel_signal = squeeze(img(x,y,z,2:end)); + +% plot_amp(voxel_signal,gradient_scheme) + +% voxel_signal = squeeze(img(x,y,z,:)); + + voxel_signal_SH = amp2SH(voxel_signal, gradient_scheme); + + + S = SH2amp (voxel_signal_SH, plot_scheme); % The interpolated voxel signal. + + + S = S .* scale_signal; + + S2 = -S; + + S(find(S<0)) = 0; + + if no_neg_values + S2 = zeros(size(S)); + else + S2(find(S2<0)) = 0; + end + + + vox_offset = [(x-0.5) * img_struct.vox(1) (y-0.5) * img_struct.vox(2) (z-0.5) * img_struct.vox(3)] + corner_offset; + + + vox_offset = repmat(vox_offset, [size(plot_scheme.vert,1) 1]); + + + V = plot_scheme.vert .* (S*[ 1 1 1 ]) + vox_offset; + V2 = plot_scheme.vert .* (S2*[ 1 1 1 ]) + vox_offset; + + + h = patch('Vertices', V, 'Faces', plot_scheme.mesh); + set(h, 'LineStyle', 'None', ... + 'FaceLighting', 'Phong', ... + 'FaceColor', colour, ... + 'FaceAlpha', transparency); + + h2 = patch('Vertices', V2, 'Faces', plot_scheme.mesh); + set(h2, 'LineStyle', 'None', ... + 'FaceLighting', 'Phong', ... + 'FaceColor', neg_colour, ... + 'FaceAlpha', transparency); + + light('position', [1 1 1]); + + count = count + 1; + + fprintf('.'); + + end + end + end + + hold off; + + add_vox_lines_to_plot(img_struct.vox(1), img_struct.dim(1)); + + + lighting gouraud; + + fprintf('\n'); + + +end + + diff --git a/matlab/plot_peaks.m b/matlab/plot_peaks.m new file mode 100644 index 0000000..296bf7c --- /dev/null +++ b/matlab/plot_peaks.m @@ -0,0 +1,75 @@ +function plot_peaks(varargin) +% +% PURPOSE: Plots spikes in TestSpikey probability landscape. +% +% ARGUMENTS: +% +% spike_filename Filename containing the spike landscape to plot +% +% OPTIONS (name, description, type, default): +% + + description = 'Plots peaks in TestSpikey probability landscape.'; + + arguments = {'peaks_filename', 'Filename containing the spike landscape to plot'}; + + options = {... + 'image_plot ', 0, 'bool', 'Image plot instead of surface.';... + 'invert ', 0, 'bool', 'Invert the plot upside down.';... + 'extent ', 1.5, 'float', 'Extent of the peaks to plot.';... + 'resolution ', 0.01, 'float', 'Resolution of the grid';... + 'transparency ', 0.5, 'float', 'Transparency of the plot.';... + }; + + parse_arguments + if (help_display) + return; + end + +% End arguments % + + peaks = load(peaks_filename); + + num_peaks = size(peaks,1); + + grid_points = -extent:resolution:extent; + + Z = zeros(size(X)); + + for x = grid_points + + for y = grid_points + + for peak_i = 1:num_peaks + + end + + end + + end + + my_figure(peaks_filename); + + [X,Y] = meshgrid(grid_points, grid_points); + + if image_plot + + imagesc(spikes); + + else + + X = repmat([1:size(spikes,2)]',1, size(spikes,2)); + Y = repmat([1:size(spikes,1)], size(spikes,1), 1); + + h = surf(X,Y,spikes); + + set(h,'FaceAlpha', transparency); + + cameratoolbar('Show'); + cameratoolbar('SetMode','orbit'); + + end + + daspect([1 1 1]); + +end \ No newline at end of file diff --git a/matlab/plot_rank3_hessian.m b/matlab/plot_rank3_hessian.m new file mode 100644 index 0000000..57a866b --- /dev/null +++ b/matlab/plot_rank3_hessian.m @@ -0,0 +1,189 @@ +function plot_rank3_hessian(varargin) +% +% PURPOSE: Plots the difference between the analytically calculated gradient and the numerically calculated gradient. +% +% ARGUMENTS: +% +% comparison_files The filename containing the comparison between the analytical and numerical gradients. +% +% OPTIONS (name, description, type, default): +% +% -style +% Style of the plot. +% string +% 'x' +% +% -marker_size +% Size of marker +% int +% 10 +% +% -line_width +% Width of line +% int +% 2 +% +% -param_include +% Parameters to include in the plots. +% matrix_1x: +% +% -test_include +% Tests to include in the plots. +% matrix_1x: + + + description = 'Plots the difference between the analytically calculated gradient and the numerically calculated gradient.'; + + arguments = {'comparison_files', 'The filename containing the comparison between the analytical and numerical gradients.'}; + + options = {... + 'style ', 'x', 'string', 'Style of the plot.';... + 'marker_size ', 10, 'int', 'Size of marker';... + 'line_width ', 2, 'int', 'Width of line';... + 'index_include', [], 'matrix_1x:', 'Parameter indices to include in the plots (overrides coord_include).';... + 'coord_include', [], 'matrix_:x:', 'Parameter coordinates to include in the plots.';... + 'test_include', [], 'matrix_1x:', 'Tests to include in the plots.';... + 'diagonal', 0, 'bool', 'Only displays diagonal components';... + 'collapse', 0, 'bool', 'Collapse all plots into single one';... + }; + + + parse_arguments + if (help_display) + return; + end + +% End arguments % + + + extension = file_extension(comparison_files); + base = file_base(comparison_files); + + if ~strcmp(extension, 'tnr3') + error(['Files must have ''tnr3'' extension for 3 order Hessian.']); + end + + base_extension = file_extension(base); + base_base = file_base(base); + + [analytic, labels] = load_tensor([base_base '.analytic.' base_extension '.' extension]); + numeric = load_tensor([base_base '.numeric.' base_extension '.' extension]); + + if any(size(analytic) ~= size(numeric)) + error(['Size of analytic (' mat2str(size(analytic)) ') does not match size of numeric (' mat2str(size(numeric)) ').']); + end + + %Ensure matrices are of the same size. + num_parameters = size(analytic,1); + num_tensors = size(analytic,3); + + if size(analytic,2) ~= num_parameters + error('Matrices not square.'); + end + + if mod(num_tensors, num_parameters) ~= 0 + error(['Number of parameters (' num2str(num_parameters) ') does not divide into number of matrices (' num2str(num_tensors) ').']); + end + + num_tests = num_tensors / num_parameters; + + analytic = reshape(analytic, [num_parameters, num_parameters, num_parameters, num_tests]); + numeric = reshape(numeric, [num_parameters, num_parameters, num_parameters, num_tests]); + + %Set to display to all comparisons if not selection explicitly provided. + if diagonal + + coord_include = zeros(num_parameters,3); + + for param_i = 1:num_parameters + coord_include(param_i,:) = [param_i param_i, param_i]; + end + + elseif ~isempty(index_include) + + [row col depth] = ind2sub([num_parameters, num_parameters, num_parameters], index_include); + + coord_include = [row' col' depth']; + + elseif isempty(coord_include) + + coord_include = zeros(num_parameters,3); + + param_count = 1; + for row_i = 1:num_parameters + for col_i = 1:num_parameters + for depth_i = 1:num_parameters + coord_include(param_count,:) = [row_i col_i depth_i]; + param_count = param_count +1; + end + end + end + + end + + if isempty(test_include) + test_include = 1:num_tests; + end + + num_param_include = size(coord_include,1); + + if collapse + my_figure('All parameters'); + + overall_min_value = inf; + overall_max_value = -inf; + end + + + %Plot comparisons. + for param_index_i = 1:num_param_include + + param_index = coord_include(param_index_i,:); + + numeric_param = squeeze(numeric(param_index(1), param_index(2), param_index(3), test_include)); + analytic_param = squeeze(analytic(param_index(1), param_index(2), param_index(3), test_include)); + + if ~collapse + my_figure([labels{param_index(1)}(1:end) ' :: ' labels{param_index(2)}(1:end) ' :: ' labels{param_index(3)}(1:end)], param_index_i, num_param_include); + end + + plot(numeric_param, analytic_param, style, 'MarkerSize', marker_size, 'LineWidth',line_width); + + set(get(gca,'xlabel'), 'string', 'numeric', 'color', [1 1 1]); + set(get(gca,'ylabel'), 'string', 'analytic', 'color', [1 1 1]); + + min_value = min([numeric_param; analytic_param]) * 1.1; + max_value = max([numeric_param; analytic_param]) * 1.1; + + + if collapse + if min_value < overall_min_value + overall_min_value = min_value + end + + if max_value > overall_max_value + overall_max_value = max_value + end + else + hold on; + + plot([min_value; max_value], [min_value; max_value], '-', 'color', [0.7412 0.6549 0.9608]); + + hold off; + end + + end + + if collapse + hold on; + + plot([overall_min_value; overall_max_value], [overall_min_value; overall_max_value], '-', 'color', [0.7412 0.6549 0.9608]); + + hold off; + end + + disp('') + disp(['Plotted ' num2str(num_tests) ' tests.']); + disp('') + +end diff --git a/matlab/plot_samples.m b/matlab/plot_samples.m new file mode 100644 index 0000000..b23195b --- /dev/null +++ b/matlab/plot_samples.m @@ -0,0 +1,233 @@ +function [samples, colours_of_strands] = plot_samples(varargin) +% +% PURPOSE: Plots tracts from sample files, and optionally displays reference sphere and voxels +% +% ARGUMENTS: +% +% filename The filename of the samples ('.tsp' format). +% +% OPTIONS (name, description, type, default): +% +% -transparency +% transparency of the plotted samples +% float +% 0.75 +% +% -include +% The indices of the tracts to include in the plot +% matrix_1x: +% +% -sample_include +% The indices of the samples to include in the plot +% matrix_1x: +% +% -colours_of_strands +% Colours of the plotted tracts +% matrix_:x3 +% +% -voxel_size +% Size of reference voxel +% float +% 0.15 +% +% -num_voxels +% Number of reference voxels +% int +% 3 +% +% -cube_size +% Size of reference voxel +% float +% 0 +% +% -num_segments +% Number of segments to plot for each tract. +% int +% 100 +% +% -strands_plot +% Whether to plot as grid of lines instead of tubes. +% int +% 0 +% +% -sphere_radius +% Size of reference sphere +% float +% 0.389711 +% + + global colours_of_strands; + +% The following code sets the input arguments and options as specified by the 'arguments' and 'options' cell arrays. + + description = 'Plots tracts from sample files, and optionally displays reference sphere and voxels'; + + arguments = {'filename', 'The filename of the samples (''.tsp'' format).'}; + + options = {... + 'transparency ', 0.75, 'float', 'transparency of the plotted samples';... + 'include ', [], 'matrix_1x:', 'The indices of the tracts to include in the plot';... + 'sample_include ', [], 'matrix_1x:', 'The indices of the samples to include in the plot';... + 'colours_of_strands', colours_of_strands, 'matrix_:x3', 'Colours of the plotted tracts';... + 'voxel_size ', 0.15, 'float', 'Size of reference voxel';... + 'num_voxels ', 3, 'int', 'Number of reference voxels';... + 'cube_size ', 0, 'float', 'Size of reference voxel';... + 'num_segments ', 100, 'int', 'Number of segments to plot for each tract.';... + 'style ', 'strands', 'string', 'Whether to plot as grid of strands or outer boundary.';... + 'num_strands ', 0, 'int', 'Number of strands to plot along each axis. (NB: can only be used with ''-style'' option ''strands'').';... + 'sphere_radius ', 0.389711, 'float', 'Size of reference sphere'... + }; + + + parse_arguments + if (help_display) + return; + end + +% End arguments % + + + + dots_i = findstr(filename,'.'); + ext = filename(dots_i(end):end); + + if ~strcmp(ext, '.tsp') + error(['Input file must be a samples file (extension ''.tsp''), found file with extension ' ext '.']); + end + + [samples, ext_prop_keys, ext_prop_values, initial_set, true_set, sphere_radius] = load_samples(filename); + + num_tracts = size(initial_set,1); + num_samples = size(samples,1) - 1; + + if any(find(sample_include > num_samples)) + error('Selected sample indices exceed number of loaded samples'); + end + + if isempty(sample_include) + sample_include = 1:num_samples; + end + + + bundle_indices_index = find(strcmp(ext_prop_keys, 'bundle_index')); + + cdata = cell(num_samples, num_tracts); + + + if size(colours_of_strands,1) < num_tracts %#ok + colours_of_strands = rand([num_tracts, 3]); %#ok + display_colour_key(colours_of_strands, 0:1:(num_tracts-1)); %#ok + end + for sample_i = 1:num_samples + for tract_i = 1:num_tracts + + colour_data = repmat(shiftdim(colours_of_strands(tract_i,:),-1), [num_segments 1 1]); %#ok + cdata{sample_i, tract_i} = [colour_data colour_data]; + + end + end + + + alpha_data = ones(num_segments,2) * transparency; + + main_fig = figure(); + + set(main_fig,'Units','normalized') + + set(main_fig, 'Position', [0.3 0.25 0.4 0.5]); + set(main_fig, 'DoubleBuffer', 'on'); + set(main_fig, 'Name', strrep(filename, '_', ' ')); + + cameratoolbar('Show'); + cameratoolbar('SetMode','orbit'); + campos([0 0 1]); + camup([0 1 0]); + + clf; + + whitebg(main_fig,'black'); + hold on; + + + fprintf('\n'); + disp(['Plotting ' num2str(size(sample_include,2)) ' samples.']); + + for sample_i = sample_include + + sample = samples{sample_i,1}; + + for tract_i = 1:num_tracts + + if strcmp(style,'strands') + + for ax2_inc = -1:(1/num_strands):1 + + for ax3_inc = -1:(1/num_strands):1 + + strand = sample{tract_i, 1} + sample{tract_i, 2} * ax2_inc + sample{tract_i, 3} * ax3_inc; + + tck = fourier2tck(strand); + + h = surface(... + 'XData', [tck(:,1) tck(:,1)],... + 'YData', [tck(:,2) tck(:,2)],... + 'ZData', [tck(:,3) tck(:,3)],... + 'CData', cdata{sample_i, tract_i},... + 'AlphaData', alpha_data,... + 'FaceColor', 'none',... + 'EdgeColor', 'flat',... + 'Marker', 'none', ... + 'LineStyle', '-', ... + 'LineWidth', 1); + view(3) + daspect ([ 1 1 1 ]); + + end + end + end + end + + if ~mod(sample_i,25) + fprintf('.'); + end + + + end + + hold off; + + %set(gca, 'color', [0 0 0]); + set(gcf, 'color', [0 0 0]); + + label_handle = get(gca,'xlabel'); + set(label_handle, 'string', 'X-axis', 'color', [1 1 1]); + + label_handle = get(gca,'ylabel'); + set(label_handle, 'string', 'Y-axis', 'color', [1 1 1]); + + label_handle = get(gca,'zlabel'); + set(label_handle, 'string', 'Z-axis', 'color', [1 1 1]); + + h = get (gca, 'children'); + daspect ([ 1 1 1 ]); + + light + lighting gouraud; + + +% figure(main_fig); + + + + if sphere_radius ~= 0 + display_reference_sphere(sphere_radius, 0.1); + end + + if voxel_size ~= 0 + plot_vox_lines(voxel_size,num_voxels); + end + + + samples = samples(sample_include); + +end \ No newline at end of file diff --git a/matlab/plot_scan.m b/matlab/plot_scan.m new file mode 100644 index 0000000..ef715f7 --- /dev/null +++ b/matlab/plot_scan.m @@ -0,0 +1,415 @@ +function plot_scan(varargin) +% +% PURPOSE: Plots the output of 'scan_strands' +% +% ARGUMENTS: +% +% scan_filename The filename of the '.mif', '.sst', or '.tst' scan_image containing the scan. +% +% OPTIONS (name, description, type, default): +% +% -scale_range +% The range of the colour scale plot. +% matrix_1x2 +% +% -state_filename +% Filename of the states to overlay on the surface plot. +% string +% '' +% +% -include_states +% States to include in plot. +% matrix_:x: +% +% -mark_rand_samples +% Mark samples where the momentum is randomized. +% bool +% 0 +% +% -highlight_samples +% Highlight selected samples with a larger marker +% matrix_:x: +% +% -image +% Plot as a flat image instead of a surface. +% bool +% 0 +% +% -exponential +% Change plot to display the probability instead of the log probability. +% bool +% 0 +% +% -offset +% Offset the values by a constant amount (used in conjunction with '-exponential'). +% float +% 0 +% +% -transparency +% The transparency of the surface. +% float +% 0.5 + + + description = 'Plots the output of ''scan_strands'''; + + arguments = {'scan_filenames', 'The filename of the ''.mif'', ''.sst'', or ''.tst'' scan_image containing the scan.'}; + + options = {... + 'scale_range ', [], 'matrix_1x2', 'The range of the colour scale plot.';... + 'state_filename ', '', 'string' , 'Filename of the states to overlay on the surface plot.';... + 'include_states ', [], 'matrix_:x:', 'States to include in plot.';... + 'mark_rand_samples', 1, 'bool', 'Mark samples where the momentum is randomized.';... + 'highlight_samples', [], 'matrix_:x:', 'Highlight selected samples with a larger marker';... + 'image_plot ', 0, 'bool' , 'Plot as a flat image instead of a surface.';... + 'map_to_surface ', 0, 'bool' , 'Maps the probabilities on the surfaces of the scans, representing the probability due to that dimension.';... + 'exponential ', 0, 'bool' , 'Change plot to display the probability instead of the log probability.';... + 'offset ', 0, 'float' , 'Offset the values by a constant amount (used in conjunction with ''-exponential'').';... + 'transparency ', 0.5, 'float' , 'The transparency of the surface.';... + }; + + + multiple_last_arguments = 1; + + parse_arguments + if (help_display) + return; + end + +% End arguments % + + + %Expand any directories + expanded_scan_filenames = cell(0); + + for scan_i = 1:length(scan_filenames); + + if isdir(scan_filenames{scan_i}) + + filenames = dir(scan_filenames{scan_i}); + + for file_i = 1:length(filenames) + if strcmp(file_extension(filenames(file_i).name), 'mif') + expanded_scan_filenames{end+1} = [scan_filenames{scan_i}, filesep, filenames(file_i).name]; + end + + end + + else + expanded_scan_filenames{end+1} = scan_filenames{scan_i}; + end + + end + + num_scans = length(expanded_scan_filenames); + + + %If states provided preload them to save having to read the file multiple + %times. + if ~isempty(state_filename) + + if strcmp(file_extension(state_filename), 'sst') + + [sets, props, set_prop_keys, set_prop_values] = load_strand_sets(state_filename,include_states,1); + + elseif strcmp(file_extension(state_filename), 'tst') + + [sets, props, set_prop_keys, set_prop_values] = load_tract_sets(state_filename,include_states,1); + + else + error(['Unrecognised extension ''' file_extension(state_filename) '''.']); + end + + end + + %Plot the scans. + for scan_i = 1:num_scans + + scan_filename = expanded_scan_filenames{scan_i}; + + figure_name = strrep(scan_filename,'_',' '); + + if exponential + figure_name = [figure_name ' - Probability']; + else + figure_name = [figure_name ' - Log Probability']; + end + + + %If 1D scan + if strcmp(file_extension(scan_filename),'sst') || strcmp(file_extension(scan_filename),'tst') || strcmp(file_extension(scan_filename),'str') || strcmp(file_extension(scan_filename),'tct') + + [prop_keys, prop_values] = read_element_properties([scan_filename 'x']); + + scan_data = get_properties(prop_keys, prop_values, 'log_px'); + + if offset > 0 + scan_data = scan_data + offset; + end + + if exponential + scan_data = exp(scan_data); + end + + my_figure(figure_name, scan_i, num_scans); + + plot(scan_data); + + + %If 2d scan + elseif strcmp(file_extension(scan_filename), 'mif') + + scan_image = read_image(scan_filename); + + if ~isfield(scan_image, 'data') + error(['Could not load scan_image from ' scan_filename ]); + end + + scan_range1 = [-1:2/(scan_image.dim(1)-1):1]; + scan_range2 = [-1:2/(scan_image.dim(2)-1):1]; + + if offset > 0 + scan_image.data = scan_image.data + offset; + end + + if exponential + scan_image.data = exp(scan_image.data); + end + + + %Plot as a flat image. + if image_plot + + my_figure(figure_name, scan_i, num_scans); + + if isempty(scale_range) + imagesc(scan_range1, scan_range2, scan_image.data); + else + imagesc(scan_range1, scan_range2, scan_image.data, scale_range); + end + + colorbar; + + %Else plot as a surface. + else + + [X,Y] = meshgrid(scan_range1, scan_range2); + + my_figure(figure_name, scan_i, num_scans, [], 1); + + h = surf(X, Y, scan_image.data'); + + + if transparency ~= 1 + set(h,'FaceAlpha', transparency); + end + + %If states provided (i.e. a MCMC sequence) plot projection on to + %scan slice. + if ~isempty(state_filename) + + axis1 = eval(scan_image.axis1); + axis2 = eval(scan_image.axis2); + origin = eval(scan_image.origin); + + if strcmp(file_extension(state_filename), 'sst') + + num_sets = size(sets,1); + + px = get_properties(set_prop_keys, set_prop_values, 'log_px', zeros(num_sets,1), num_sets); + + proj1 = zeros(num_sets,1); + proj2 = zeros(num_sets,1); + + + for set_i = 1:num_sets + + strands = sets{set_i}; + + num_strands = size(strands,1); + + for strand_i = 1:num_strands + + strand_disp = strands{strand_i} - origin{strand_i + 2}{3}; + + proj1(set_i) = proj1(set_i) + dot(axis1{strand_i + 2}{3}(:), strand_disp(:)); + proj2(set_i) = proj2(set_i) + dot(axis2{strand_i + 2}{3}(:), strand_disp(:)); + + end + + end + + + axis1_norm2 = 0; + axis2_norm2 = 0; + + for strand_i = 1:num_strands + axis1_norm2 = axis1_norm2 + axis1{strand_i + 2}{3}(:)' * axis1{strand_i + 2}{3}(:); + axis2_norm2 = axis2_norm2 + axis2{strand_i + 2}{3}(:)' * axis2{strand_i + 2}{3}(:); + end + + proj1 = proj1 ./ axis1_norm2; + proj2 = proj2 ./ axis2_norm2; + + + elseif strcmp(file_extension(state_filename), 'tst') + + num_sets = size(sets,1); + + px = get_properties(set_prop_keys, set_prop_values, 'px', zeros(num_sets,1), num_sets); + + proj1 = zeros(num_sets,1); + proj2 = zeros(num_sets,1); + + + for set_i = 1:num_sets + + tracts = sets{set_i}; + + num_tracts = size(tracts,1); + + for tract_i = 1:num_tracts + + for strand_i = 1:3 + + strand_disp = tracts{tract_i}{strand_i} - origin{tract_i + 2}{strand_i}{3}; + + proj1(set_i) = proj1(set_i) + dot(axis1{tract_i + 2}{strand_i}{3}(:), strand_disp(:)); + proj2(set_i) = proj2(set_i) + dot(axis2{tract_i + 2}{strand_i}{3}(:), strand_disp(:)); + + end + + end + + end + + + axis1_norm2 = 0; + axis2_norm2 = 0; + + for tract_i = 1:num_tracts + + for strand_i = 1:3 + axis1_norm2 = axis1_norm2 + axis1{tract_i + 2}{strand_i}{3}(:)' * axis1{tract_i + 2}{strand_i}{3}(:); + axis2_norm2 = axis2_norm2 + axis2{tract_i + 2}{strand_i}{3}(:)' * axis2{tract_i + 2}{strand_i}{3}(:); + end + + end + + proj1 = proj1 ./ axis1_norm2; + proj2 = proj2 ./ axis2_norm2; + + + + else + error(['Unrecognised extension ''' file_extension(state_filename) '''.']); + end + + + hold on; + + %If map_to_surface option is selected, map probability values via + %bilinear interpolation to scan surface. + if map_to_surface + + for set_i = 1:num_sets + + + if (proj1(set_i) < -1) || (proj1(set_i) > 1) || (proj2(set_i) < -1) || (proj2(set_i) > 1) + + px(set_i) = 0; + + else + + + index1 = (scan_image.dim(1)-1) * (proj1(set_i) + 1)/2 + 1; + index2 = (scan_image.dim(2)-1) * (proj2(set_i) + 1)/2 + 1; + + low1 = floor(index1); + high1 = ceil(index1); + frac1 = rem(index1,1); + + low2 = floor(index2); + high2 = ceil(index2); + frac2 = rem(index2,1); + + px(set_i) = (1-frac2) * ((1-frac1) * scan_image.data(low1, low2) + frac1 * scan_image.data(high1, low2)) + ... + frac2 * ((1-frac1) * scan_image.data(low1, high2) + frac1 * scan_image.data(high1, high2)); + + end + + end + + state_plot_colour = [1 0.5 1]; + + else + + state_plot_colour = 'yellow'; + + end + + + plot3(proj1, proj2, px, 'Color', state_plot_colour); + + plot3(proj1(1), proj2(1), px(1), 'md', 'MarkerEdgeColor', 'red', 'MarkerFaceColor', 'red', 'MarkerSize', 10); + + if mark_rand_samples + + sample_period = str2double(props.sample_period); + + mark_samples = sample_period:sample_period:num_sets; + + plot3(proj1(mark_samples), proj2(mark_samples), px(mark_samples), 'mo', 'MarkerEdgeColor', 'blue', 'MarkerFaceColor', 'blue', 'MarkerSize', 5); + + end + + if ~isempty(highlight_samples) + + highlight_samples = highlight_samples + 1; + + highlight_samples = highlight_samples(highlight_samples < num_sets); + + plot3(proj1(highlight_samples), proj2(highlight_samples), px(highlight_samples), 'md', 'MarkerEdgeColor', 'green', 'MarkerFaceColor', 'green', 'MarkerSize', 8); + + end + + hold off + + + end + + end + + axis1_delim = strfind(scan_image.axis1_location,'/'); + + if isempty(axis1_delim) + axis1_basename = 0; + else + axis1_basename = scan_image.axis1_location((axis1_delim(end)+1):end); + end + + xlabel(axis1_basename); + + + axis2_delim = strfind(scan_image.axis2_location,'/'); + + if isempty(axis2_delim) + axis2_basename = 0; + else + axis2_basename = scan_image.axis2_location((axis2_delim(end)+1):end); + end + + ylabel(axis2_basename); + + + + + else + + error(['Unrecognised file_extension, ''' file_extension(scan_filename) '''.']); + + end + + end + +end diff --git a/matlab/plot_spikes.m b/matlab/plot_spikes.m new file mode 100644 index 0000000..640a804 --- /dev/null +++ b/matlab/plot_spikes.m @@ -0,0 +1,57 @@ +function plot_spikes(varargin) +% +% PURPOSE: Plots spikes in TestSpikey probability landscape. +% +% ARGUMENTS: +% +% spike_filename Filename containing the spike landscape to plot +% +% OPTIONS (name, description, type, default): +% + + description = 'Plots spikes in TestSpikey probability landscape.'; + + arguments = {'spikes_filename', 'Filename containing the spike landscape to plot'}; + + options = {... + 'image_plot ', 0, 'bool', 'Image plot instead of surface.';... + 'invert ', 0, 'bool', 'Inver the plot upside down.';... + 'transparency ', 0.5, 'float', 'Transparency of the plot.';... + }; + + parse_arguments + if (help_display) + return; + end + +% End arguments % + + spikes = load(spikes_filename); + + if invert + spikes = -spikes; + end + + my_figure(spikes_filename); + + if image_plot + + imagesc(spikes); + + else + + X = repmat([1:size(spikes,2)]',1, size(spikes,2)); + Y = repmat([1:size(spikes,1)], size(spikes,1), 1); + + h = surf(X,Y,spikes); + + set(h,'FaceAlpha', transparency); + + cameratoolbar('Show'); + cameratoolbar('SetMode','orbit'); + + end + + daspect([1 1 1]); + +end \ No newline at end of file diff --git a/matlab/plot_strand_sets.m b/matlab/plot_strand_sets.m new file mode 100644 index 0000000..fe31940 --- /dev/null +++ b/matlab/plot_strand_sets.m @@ -0,0 +1,330 @@ +function main_fig = plot_strands_sets(varargin) +% +% PURPOSE: Plots strands from strand files, and optionally displays reference sphere and voxels +% +% ARGUMENTS: +% +% strands_filename The filename of the strands in either .tck or .frr formats. +% +% OPTIONS (name, description, type, default): +% +% -strand_radius +% Radii of the plotted strands +% float +% 0.02 +% +% -num_points +% Number of points to plot along each strand. +% int +% 100 +% +% -include +% The indices of the sets to include in the plot +% matrix_:x: +% +% -last +% Overrides '-include' to only print the last tract set. +% bool +% 0 +% +% -strand_include +% The indices of the strands to include in the plot +% matrix_:x: +% +% -bundle_include +% The indices of the bundles to include in the plot +% matrix_:x: +% +% -colours_of_bundles +% Colours of the plotted strands +% matrix_:x3 +% +% -voxel_size +% Size of reference voxel +% float +% 0.15 +% +% -num_voxels +% Number of reference voxels +% int +% 3 +% +% -cube_size +% Size of reference voxel +% float +% 0 +% +% -style +% Plot to style (either 'tubes' or 'lines').. +% string +% 'lines' +% +% -properties_plot +% Do, don't or only plot the extended properties associated with the tract set (0 -> don't plot properties, 1 -> plot properties, 2 -> only plot properties). +% int +% 1 +% +% -sphere_radius +% Size of reference sphere +% float +% 0 +% +% -no_axes +% Removes axes from plot +% bool +% 0 +% +% -clean +% Removes everything else from plot +% bool +% 0 + + main_fig = -1; + + global colours_of_bundles; + + description = 'Plots strands from strand files, and optionally displays reference sphere and voxels'; + + arguments = {'strands_filename', 'The filename of the strands in either .tck or .frr formats.'}; + + options = {... + 'strand_radius ', 0.02, 'float', 'Radii of the plotted strands';... + 'num_points ', 100, 'int', 'Number of points to plot along each strand.';... + 'include ', [], 'matrix_:x:', 'The indices of the sets to include in the plot';... + 'dont_include ', [], 'matrix_:x:', 'The indices of the samples not to include in the plot';... + 'last', 0, 'bool', 'Overrides ''-include'' to only print the last tract set.';... + 'strand_include ', [], 'matrix_:x:', 'The indices of the strands to include in the plot';... + 'bundle_include ', [], 'matrix_:x:', 'The indices of the bundles to include in the plot';... + 'colours_of_bundles', colours_of_bundles, 'matrix_:x3', 'Colours of the plotted strands';... + 'voxel_size ', 0.15, 'float', 'Size of reference voxel';... + 'num_voxels ', 3, 'int', 'Number of reference voxels';... + 'cube_size ', 0, 'float', 'Size of reference voxel';... + 'happy_colours', 0, 'bool', 'Uses ''happy colours''';... + 'inv_happy_colours', 0, 'bool', 'Uses the inverse of ''happy colours''';... + 'style ', 'lines', 'string', 'Plot to style (either ''tubes'' or ''lines'')..';... + 'tube_corners ', 6, 'int', 'Change plot to ''line style''.(NB: Only relevant with ''-num_strands'' option = 0).';... + 'properties_plot', 0, 'int', 'Do, don''t or only plot the extended properties associated with the tract set (0 -> don''t plot properties, 1 -> plot properties, 2 -> only plot properties).';... + 'sphere_radius ', 0, 'float', 'Size of reference sphere';... + 'no_axes', 0, 'bool', 'Removes axes from plot';... + 'clean', 0, 'bool', 'Removes everything else from plot';... + 'no_voxline_highlight', 0, 'bool', 'Doesn''t highlight corner axes of voxel lines.';... + 'invisible', 0, 'bool', 'Makes the figure invisible (for automatically saving afterwards).'}; + + parse_arguments + if (help_display) + return; + end + + + if clean + voxel_size = 0; + sphere_radius = 0; + no_axes = 1; + end + + +% End arguments % + + if happy_colours + + if inv_happy_colours + error('Can''t use ''-happy_colours'' and ''-inv_happy_colours'' simultaneously'); + end + + load('/home/tclose/Data/Tractography/misc/comb_happy_colours.mat'); + + elseif inv_happy_colours + + load('/home/tclose/Data/Tractography/misc/inv_comb_happy_colours.mat'); + + end + + [strand_sets, props, set_prop_keys, set_prop_values, elem_prop_keys, elem_prop_values] = load_strand_sets(strands_filename, [], 1); + + num_sets = size(strand_sets,1); + + if last + + if ~isempty(dont_include) || ~isempty(include) + error('Error! -last cannot be used simultaneously with -include or -dont_include options'); + end + + include = size(strand_sets,1)-1; + + else + + if ~isempty(dont_include) + + if ~isempty(include) + error('Error! -include and -dont_include options cannot be used simultaneously'); + end + + include = 1:num_sets; + + include(dont_include) = []; + + include = include-1; + + end + + end + + if ~isempty(strand_include) + error('Cannot use ''strand_include'' and ''bundle_include simultaneously'); + end + + include = include + 1; + + + if properties_plot < 2 + + overall_max_bundle_index = 0; + + for set_i = 1:num_sets + + num_strands = size(strand_sets{set_i},1); + + if size(elem_prop_keys,2) + prop_values = elem_prop_values{set_i}; + else + prop_values = []; + end + + bundle_indices = get_properties(elem_prop_keys, prop_values, 'bundle_index', [0:1:(num_strands-1)]', num_strands); + + max_bundle_index = max(bundle_indices); + + if max_bundle_index > overall_max_bundle_index + overall_max_bundle_index = max_bundle_index; + end + end + + set_bundle_colours(overall_max_bundle_index); + + %Set up the figure. + main_fig = my_figure(strands_filename, 1, 3, [1 1 1], 1, [],[],~invisible); + + set(gcf, 'color', [0 0 0]); + + if no_axes + set(gca, 'visible', 'off') ; + else + label_handle = get(gca,'xlabel'); + set(label_handle, 'string', 'X-axis', 'color', [1 1 1]); + + label_handle = get(gca,'ylabel'); + set(label_handle, 'string', 'Y-axis', 'color', [1 1 1]); + + label_handle = get(gca,'zlabel'); + set(label_handle, 'string', 'Z-axis', 'color', [1 1 1]); + end + + daspect ([ 1 1 1 ]); + + add_sphere_to_plot(sphere_radius, props); + + if voxel_size ~= 0 + + add_vox_lines_to_plot(voxel_size,num_voxels,~no_voxline_highlight); + + end + + + light + lighting gouraud; + + + if isempty(include) + include = 1:num_sets; + end + + for set_i = include + + if size(elem_prop_keys,2) + prop_values = elem_prop_values{set_i}; + else + prop_values = []; + end + + strands = strand_sets{set_i}; + + + if ~isempty(bundle_include) + + num_strands = size(strands,1); + + bundle_indices = get_properties(elem_prop_keys, prop_values, 'bundle_index', 1:num_strands); + + strand_include = []; + + for strand_i = 1:num_strands + if any(find(bundle_include == bundle_indices(strand_i))) + strand_include = [strand_include; strand_i]; %#ok + end + end + + if isempty(strand_include) + disp('Warning! No bundles matched the given indices, returning all strands.'); + end + + end + + num_strands = size(strands,1); + + bundle_indices = get_properties(elem_prop_keys, prop_values, 'bundle_index', [0:1:(num_strands-1)]', num_strands); + radii = get_properties(elem_prop_keys, prop_values, 'tract_radius', strand_radius, num_strands); + + + if ~isempty(strand_include) + + strands = strands(strand_include); + bundle_indices = bundle_indices(strand_include); + radii = radii(strand_include); + + end + + + tcks = strands2tcks(strands); + + if strfind('tubes', style) == 1 + + add_tcks_to_plot(tcks, radii, colours_of_bundles, bundle_indices, tube_corners); + + elseif strfind('lines', style) == 1 + + add_lines_to_plot(tcks, colours_of_bundles, bundle_indices); + + else + + error(['Urecogised style option ''' style '''.']); + + end + + daspect ([ 1 1 1 ]); + + end + + fprintf('\n'); + disp(['Plotted ' num2str(num_sets) ' strand sets.']); + + end + + if properties_plot > 0 && length(include) ~= 1 + + if exist([strands_filename 'x']) + + ext_props_fig = plot_extend_elem_properties([strands_filename 'x'], set_prop_keys, set_prop_values,include); + + end + end + + if (properties_plot == 1 || properties_plot == 3) && length(include) ~= 1 + if exist([strands_filename 'xx']) + + ext_ext_props_fig = plot_extended_extend_elem_properties([strands_filename 'xx'], elem_prop_keys, elem_prop_values, colours_of_bundles, include); + + end + + end + +end \ No newline at end of file diff --git a/matlab/plot_strands.m b/matlab/plot_strands.m new file mode 100644 index 0000000..0beff50 --- /dev/null +++ b/matlab/plot_strands.m @@ -0,0 +1,251 @@ +function main_fig = plot_strands(varargin) +% +% PURPOSE: Plots strands from strand files, and optionally displays reference sphere and voxels +% +% ARGUMENTS: +% +% strands_filename The filename of the strands in either .tck or .frr formats. +% +% OPTIONS (name, description, type, default): +% +% -strand_radius +% Radii of the plotted strands +% float +% 0.02 +% +% -num_points +% Number of points to plot along each strand. +% int +% 100 +% +% -include +% The indices of the strands to include in the plot +% matrix_:x: +% +% -bundle_include +% The indices of the bundles to include in the plot +% matrix_:x: +% +% -colours_of_bundles +% Colours of the plotted strands +% matrix_:x3 +% +% -voxel_size +% Size of reference voxel +% float +% 0.15 +% +% -num_voxels +% Number of reference voxels +% int +% 3 +% +% -cube_size +% Size of reference voxel +% float +% 0 +% +% -style +% Plot to style (either 'strands' or 'lines').. +% string +% 'strands' +% +% -sphere_radius +% Size of reference sphere +% float +% 0 +% +% -no_axes +% Removes axes from plot +% bool +% 0 +% +% -clean +% Removes everything else from plot +% bool +% 0 +% +% -campos +% Position of the camera +% matrix_1:3 + + main_fig = -1; + + global colours_of_bundles; + + description = 'Plots strands from strand files, and optionally displays reference sphere and voxels'; + + arguments = {'strands_filename', 'The filename of the strands in either .tck or .frr formats.'}; + + options = {... + 'strand_radius ', 0.02, 'float', 'Radii of the plotted strands';... + 'num_points ', 100, 'int', 'Number of points to plot along each strand.';... + 'include ', [], 'matrix_:x:', 'The indices of the strands to include in the plot';... + 'bundle_include ', [], 'matrix_:x:', 'The indices of the bundles to include in the plot';... + 'colours_of_bundles', colours_of_bundles, 'matrix_:x3', 'Colours of the plotted strands';... + 'voxel_size ', 0.15, 'float', 'Size of reference voxel';... + 'num_voxels ', 3, 'int', 'Number of reference voxels';... + 'cube_size ', 0, 'float', 'Size of reference voxel';... + 'style ', 'tubes', 'string', 'Plot to style (either ''strands'' or ''lines'')..';... + 'sphere_radius ', 0, 'float', 'Size of reference sphere';... + 'sphere_transparency', 0.25, 'float', 'Transparency of reference sphere';... + 'tube_corners ', 6, 'int', 'Change plot to ''line style''.(NB: Only relevant with ''-num_strands'' option = 0).';... + 'no_axes', 0, 'bool', 'Removes axes from plot';... + 'happy_colours', 0, 'bool', 'Uses ''happy colours''';... + 'inv_happy_colours', 0, 'bool', 'Uses the inverse of ''happy colours''';... + 'clean', 0, 'bool', 'Removes everything else from plot';... + 'campos', [], 'matrix_1:3', 'Position of the camera';... + 'no_voxline_highlight', 0, 'bool', 'Doesn''t highlight corner axes of voxel lines.';... + 'invisible', 0, 'bool', 'Makes the figure invisible (for automatically saving afterwards).'}; + + + parse_arguments + if (help_display) + return; + end + + + if clean + voxel_size = 0; + sphere_radius = 0; + no_axes = 1; + end + + +% End arguments % + + if happy_colours + + if inv_happy_colours + error('Can''t use ''-happy_colours'' and ''-inv_happy_colours'' simultaneously'); + end + + load('/home/tclose/Data/Tractography/misc/comb_happy_colours.mat'); + + elseif inv_happy_colours + + load('/home/tclose/Data/Tractography/misc/inv_comb_happy_colours.mat'); + + end + + + [strands, props, prop_keys, prop_values] = load_strands(strands_filename); + + + if ~isempty(bundle_include) + + num_strands = size(strands,1); + + if ~isempty(include) + error('Cannot use ''include'' and ''bundle_include simultaneously'); + end + + bundle_indices = get_properties(prop_keys, prop_values, 'bundle_index', 0:1:(num_strands-1), num_strands); + + for strand_i = 1:num_strands + if any(find(bundle_include == bundle_indices(strand_i))) + include = [include; strand_i]; %#ok + end + end + + if isempty(include) + disp('Warning! No bundles matched the given indices, returning all strands.'); + end + + %To match 0 indexing + include = include - 1; + + end + + + if ~isempty(include) + + strands = strands(include+1); + prop_values = prop_values(include+1,:); + + end + + num_strands = size(strands,1); + + bundle_indices = get_properties(prop_keys, prop_values, 'bundle_index', [0:1:(num_strands-1)]', num_strands); + radii = get_properties(prop_keys, prop_values, 'track_radius', strand_radius, num_strands); + + add_colour_key(bundle_indices,colours_of_bundles); + + main_fig = my_figure(strrep(strands_filename,'_',''), 1, 1, [1 1 1], 1, [],[],~invisible); + + cameratoolbar('Show'); + cameratoolbar('SetMode','orbit'); + + + if strcmp(file_extension(strands_filename), 'str') + tcks = strands2tcks(strands); + elseif strcmp(file_extension(strands_filename), 'tck') + tcks = strands; + else + error (['Unrecognised extension, ''' extension(strands_filename) ''', of input file.']); + end + + if strfind('tubes', style) == 1 + + add_tcks_to_plot(tcks, radii, colours_of_bundles, bundle_indices, tube_corners); + + elseif strfind('lines', style) == 1 + + add_lines_to_plot(tcks, colours_of_bundles, bundle_indices); + + else + + error(['Urecogised style option ''' style '''.']); + + end + + + if sphere_radius ~= 0 + + add_sphere_to_plot(sphere_radius, sphere_transparency); + + end + + if voxel_size ~= 0 + + add_vox_lines_to_plot(voxel_size,num_voxels,~no_voxline_highlight); + + end + + + set(gcf, 'color', [0 0 0]); + + if no_axes + + set(gca, 'visible', 'off') ; + + else + + label_handle = get(gca,'xlabel'); + set(label_handle, 'string', 'X-axis', 'color', [1 1 1]); + + label_handle = get(gca,'ylabel'); + set(label_handle, 'string', 'Y-axis', 'color', [1 1 1]); + + label_handle = get(gca,'zlabel'); + set(label_handle, 'string', 'Z-axis', 'color', [1 1 1]); + + end + + if ~isempty(campos) + + set(gca,'CameraPosition',campos); + + end + + daspect ([ 1 1 1 ]); + + light + lighting gouraud; + + + fprintf('\n'); + disp(['Plotted ' num2str(num_strands) ' strands.']); + +end \ No newline at end of file diff --git a/matlab/plot_tck_sets.m b/matlab/plot_tck_sets.m new file mode 100644 index 0000000..4e84765 --- /dev/null +++ b/matlab/plot_tck_sets.m @@ -0,0 +1,328 @@ +function main_fig = plot_tcks_sets(varargin) +% +% PURPOSE: Plots tcks from tck files, and optionally displays reference sphere and voxels +% +% ARGUMENTS: +% +% tcks_filename The filename of the tcks in either .tck or .frr formats. +% +% OPTIONS (name, description, type, default): +% +% -tck_radius +% Radii of the plotted tcks +% float +% 0.02 +% +% -num_points +% Number of points to plot along each tck. +% int +% 100 +% +% -include +% The indices of the sets to include in the plot +% matrix_:x: +% +% -last +% Overrides '-include' to only print the last tract set. +% bool +% 0 +% +% -tck_include +% The indices of the tcks to include in the plot +% matrix_:x: +% +% -bundle_include +% The indices of the bundles to include in the plot +% matrix_:x: +% +% -colours_of_bundles +% Colours of the plotted tcks +% matrix_:x3 +% +% -voxel_size +% Size of reference voxel +% float +% 0.15 +% +% -num_voxels +% Number of reference voxels +% int +% 3 +% +% -cube_size +% Size of reference voxel +% float +% 0 +% +% -style +% Plot to style (either 'tubes' or 'lines').. +% string +% 'lines' +% +% -properties_plot +% Do, don't or only plot the extended properties associated with the tract set (0 -> don't plot properties, 1 -> plot properties, 2 -> only plot properties). +% int +% 1 +% +% -sphere_radius +% Size of reference sphere +% float +% 0 +% +% -no_axes +% Removes axes from plot +% bool +% 0 +% +% -clean +% Removes everything else from plot +% bool +% 0 + + main_fig = -1; + + global colours_of_bundles; + + description = 'Plots tcks from tck files, and optionally displays reference sphere and voxels'; + + arguments = {'tcks_filename', 'The filename of the tcks in either .tck or .frr formats.'}; + + options = {... + 'tck_radius ', 0.02, 'float', 'Radii of the plotted tcks';... + 'num_points ', 100, 'int', 'Number of points to plot along each tck.';... + 'include ', [], 'matrix_:x:', 'The indices of the sets to include in the plot';... + 'dont_include ', [], 'matrix_:x:', 'The indices of the samples not to include in the plot';... + 'last', 0, 'bool', 'Overrides ''-include'' to only print the last tract set.';... + 'tck_include ', [], 'matrix_:x:', 'The indices of the tcks to include in the plot';... + 'bundle_include ', [], 'matrix_:x:', 'The indices of the bundles to include in the plot';... + 'colours_of_bundles', colours_of_bundles, 'matrix_:x3', 'Colours of the plotted tcks';... + 'voxel_size ', 0.15, 'float', 'Size of reference voxel';... + 'num_voxels ', 3, 'int', 'Number of reference voxels';... + 'cube_size ', 0, 'float', 'Size of reference voxel';... + 'happy_colours', 0, 'bool', 'Uses ''happy colours''';... + 'inv_happy_colours', 0, 'bool', 'Uses the inverse of ''happy colours''';... + 'style ', 'lines', 'string', 'Plot to style (either ''tubes'' or ''lines'')..';... + 'tube_corners ', 6, 'int', 'Change plot to ''line style''.(NB: Only relevant with ''-num_tcks'' option = 0).';... + 'properties_plot', 0, 'int', 'Do, don''t or only plot the extended properties associated with the tract set (0 -> don''t plot properties, 1 -> plot properties, 2 -> only plot properties).';... + 'sphere_radius ', 0, 'float', 'Size of reference sphere';... + 'no_axes', 0, 'bool', 'Removes axes from plot';... + 'clean', 0, 'bool', 'Removes everything else from plot';... + 'no_voxline_highlight', 0, 'bool', 'Doesn''t highlight corner axes of voxel lines.';... + 'invisible', 0, 'bool', 'Makes the figure invisible (for automatically saving afterwards).'}; + + parse_arguments + if (help_display) + return; + end + + + if clean + voxel_size = 0; + sphere_radius = 0; + no_axes = 1; + end + + +% End arguments % + + if happy_colours + + if inv_happy_colours + error('Can''t use ''-happy_colours'' and ''-inv_happy_colours'' simultaneously'); + end + + load('/home/tclose/Data/Tractography/misc/comb_happy_colours.mat'); + + elseif inv_happy_colours + + load('/home/tclose/Data/Tractography/misc/inv_comb_happy_colours.mat'); + + end + + [tck_sets, props, set_prop_keys, set_prop_values, elem_prop_keys, elem_prop_values] = load_tck_sets(tcks_filename, [], 1); + + num_sets = size(tck_sets,1); + + if last + + if ~isempty(dont_include) || ~isempty(include) + error('Error! -last cannot be used simultaneously with -include or -dont_include options'); + end + + include = size(tck_sets,1)-1; + + else + + if ~isempty(dont_include) + + if ~isempty(include) + error('Error! -include and -dont_include options cannot be used simultaneously'); + end + + include = 1:num_sets; + + include(dont_include) = []; + + include = include-1; + + end + + end + + if ~isempty(tck_include) + error('Cannot use ''tck_include'' and ''bundle_include simultaneously'); + end + + include = include + 1; + + + if properties_plot < 2 + + overall_max_bundle_index = 0; + + for set_i = 1:num_sets + + num_tcks = size(tck_sets{set_i},1); + + if size(elem_prop_keys,2) + prop_values = elem_prop_values{set_i}; + else + prop_values = []; + end + + bundle_indices = get_properties(elem_prop_keys, prop_values, 'bundle_index', [0:1:(num_tcks-1)]', num_tcks); + + max_bundle_index = max(bundle_indices); + + if max_bundle_index > overall_max_bundle_index + overall_max_bundle_index = max_bundle_index; + end + end + + set_bundle_colours(overall_max_bundle_index); + + %Set up the figure. + main_fig = my_figure(tcks_filename, 1, 3, [1 1 1], 1, [],[],~invisible); + + set(gcf, 'color', [0 0 0]); + + if no_axes + set(gca, 'visible', 'off') ; + else + label_handle = get(gca,'xlabel'); + set(label_handle, 'string', 'X-axis', 'color', [1 1 1]); + + label_handle = get(gca,'ylabel'); + set(label_handle, 'string', 'Y-axis', 'color', [1 1 1]); + + label_handle = get(gca,'zlabel'); + set(label_handle, 'string', 'Z-axis', 'color', [1 1 1]); + end + + daspect ([ 1 1 1 ]); + + add_sphere_to_plot(sphere_radius, props); + + if voxel_size ~= 0 + + add_vox_lines_to_plot(voxel_size,num_voxels,~no_voxline_highlight); + + end + + + light + lighting gouraud; + + + if isempty(include) + include = 1:num_sets; + end + + for set_i = include + + if size(elem_prop_keys,2) + prop_values = elem_prop_values{set_i}; + else + prop_values = []; + end + + tcks = tck_sets{set_i}; + + + if ~isempty(bundle_include) + + num_tcks = size(tcks,1); + + bundle_indices = get_properties(elem_prop_keys, prop_values, 'bundle_index', 1:num_tcks); + + tck_include = []; + + for tck_i = 1:num_tcks + if any(find(bundle_include == bundle_indices(tck_i))) + tck_include = [tck_include; tck_i]; %#ok + end + end + + if isempty(tck_include) + disp('Warning! No bundles matched the given indices, returning all tcks.'); + end + + end + + num_tcks = size(tcks,1); + + bundle_indices = get_properties(elem_prop_keys, prop_values, 'bundle_index', [0:1:(num_tcks-1)]', num_tcks); + radii = get_properties(elem_prop_keys, prop_values, 'tract_radius', tck_radius, num_tcks); + + + if ~isempty(tck_include) + + tcks = tcks(tck_include); + bundle_indices = bundle_indices(tck_include); + radii = radii(tck_include); + + end + + + if strfind('tubes', style) == 1 + + add_tcks_to_plot(tcks, radii, colours_of_bundles, bundle_indices, tube_corners); + + elseif strfind('lines', style) == 1 + + add_lines_to_plot(tcks, colours_of_bundles, bundle_indices); + + else + + error(['Urecogised style option ''' style '''.']); + + end + + daspect ([ 1 1 1 ]); + + end + + fprintf('\n'); + disp(['Plotted ' num2str(num_sets) ' tck sets.']); + + end + + if properties_plot > 0 && length(include) ~= 1 + + if exist([tcks_filename 'x']) + + ext_props_fig = plot_extend_elem_properties([tcks_filename 'x'], set_prop_keys, set_prop_values,include); + + end + end + + if (properties_plot == 1 || properties_plot == 3) && length(include) ~= 1 + if exist([tcks_filename 'xx']) + + ext_ext_props_fig = plot_extended_extend_elem_properties([tcks_filename 'xx'], elem_prop_keys, elem_prop_values, colours_of_bundles, include); + + end + + end + +end \ No newline at end of file diff --git a/matlab/plot_tcks.m b/matlab/plot_tcks.m new file mode 100644 index 0000000..83b45ee --- /dev/null +++ b/matlab/plot_tcks.m @@ -0,0 +1,239 @@ +function main_fig = plot_tcks(varargin) +% +% PURPOSE: Plots tcks from tcks files, and optionally displays reference sphere and voxels +% +% ARGUMENTS: +% +% tcks_filename The filename of the tcks in either .tck or .frr formats. +% +% OPTIONS (name, description, type, default): +% +% -tcks_radius +% Radii of the plotted tcks +% float +% 0.02 +% +% -num_points +% Number of points to plot along each tcks. +% int +% 100 +% +% -include +% The indices of the tcks to include in the plot +% matrix_:x: +% +% -bundle_include +% The indices of the bundles to include in the plot +% matrix_:x: +% +% -colours_of_bundles +% Colours of the plotted tcks +% matrix_:x3 +% +% -voxel_size +% Size of reference voxel +% float +% 0.15 +% +% -num_voxels +% Number of reference voxels +% int +% 3 +% +% -cube_size +% Size of reference voxel +% float +% 0 +% +% -style +% Plot to style (either 'tcks' or 'lines').. +% string +% 'tcks' +% +% -sphere_radius +% Size of reference sphere +% float +% 0 +% +% -no_axes +% Removes axes from plot +% bool +% 0 +% +% -clean +% Removes everything else from plot +% bool +% 0 +% +% -campos +% Position of the camera +% matrix_1x3 +% + + main_fig = -1; + + global colours_of_bundles; + + description = 'Plots tcks from tcks files, and optionally displays reference sphere and voxels'; + + arguments = {'tcks_filename', 'The filename of the tcks in either .tck or .frr formats.'}; + + options = {... + 'tcks_radius ', 0.02, 'float', 'Radii of the plotted tcks';... + 'num_points ', 100, 'int', 'Number of points to plot along each tcks.';... + 'include ', [], 'matrix_:x:', 'The indices of the tcks to include in the plot';... + 'bundle_include ', [], 'matrix_:x:', 'The indices of the bundles to include in the plot';... + 'colours_of_bundles', colours_of_bundles, 'matrix_:x3', 'Colours of the plotted tcks';... + 'voxel_size ', 0.15, 'float', 'Size of reference voxel';... + 'num_voxels ', 3, 'int', 'Number of reference voxels';... + 'cube_size ', 0, 'float', 'Size of reference voxel';... + 'style ', 'tubes', 'string', 'Plot to style (either ''tcks'' or ''lines'')..';... + 'sphere_radius ', 0, 'float', 'Size of reference sphere';... + 'no_axes', 0, 'bool', 'Removes axes from plot';... + 'tube_corners ', 6, 'int', 'Change plot to ''line style''.(NB: Only relevant with ''-num_strands'' option = 0).';... + 'clean', 0, 'bool', 'Removes everything else from plot';... + 'happy_colours', 0, 'bool', 'Uses ''happy colours''';... + 'inv_happy_colours', 0, 'bool', 'Uses the inverse of ''happy colours''';... + 'no_voxline_highlight', 0, 'bool', 'Doesn''t highlight corner axes of voxel lines.';... + 'campos', [], 'matrix_1x3', 'Position of the camera'}; + + + parse_arguments + if (help_display) + return; + end + + if clean + voxel_size = 0; + sphere_radius = 0; + no_axes = 1; + end + +% End arguments % + + if happy_colours + + if inv_happy_colours + error('Can''t use ''-happy_colours'' and ''-inv_happy_colours'' simultaneously'); + end + + load('/home/tclose/Data/Tractography/misc/comb_happy_colours.mat'); + + elseif inv_happy_colours + + load('/home/tclose/Data/Tractography/misc/inv_comb_happy_colours.mat'); + + end + + [tcks, props, prop_keys, prop_values] = load_tcks(tcks_filename); + + if ~isempty(bundle_include) + + num_tcks = size(tcks,1); + + if ~isempty(include) + error('Cannot use ''include'' and ''bundle_include simultaneously'); + end + + bundle_indices = get_properties(prop_keys, prop_values, 'bundle_index', 0:1:(num_tcks-1), num_tcks); + + for tcks_i = 1:num_tcks + if any(find(bundle_include == bundle_indices(tcks_i))) + include = [include; tcks_i]; %#ok + end + end + + if isempty(include) + disp('Warning! No bundles matched the given indices, returning all tcks.'); + end + + %To match 0 indexing + include = include - 1; + + end + + + if ~isempty(include) + + tcks = tcks(include+1); + prop_values = prop_values(include+1,:); + + end + + num_tcks = size(tcks,1); + + bundle_indices = get_properties(prop_keys, prop_values, 'bundle_index', [0:1:(num_tcks-1)]', num_tcks); + radii = get_properties(prop_keys, prop_values, 'tract_radius', tcks_radius, num_tcks); + + add_colour_key(bundle_indices,colours_of_bundles); + + %Set up the figure. + main_fig = my_figure(strrep(tcks_filename,'_','')); + + cameratoolbar('Show'); + cameratoolbar('SetMode','orbit'); + + if strfind('tubes', style) == 1 + + add_tcks_to_plot(tcks, radii, colours_of_bundles, bundle_indices, tube_corners); + + elseif strfind('lines', style) == 1 + + add_lines_to_plot(tcks, colours_of_bundles, bundle_indices); + + else + + error(['Urecogised style option ''' style '''.']); + + end + + + if sphere_radius ~= 0 + + add_sphere_to_plot(sphere_radius); + + end + + if voxel_size ~= 0 + + add_vox_lines_to_plot(voxel_size,num_voxels,~no_voxline_highlight); + + end + + + set(gcf, 'color', [0 0 0]); + + + if no_axes + + set(gca, 'visible', 'off'); + + else + + label_handle = get(gca,'xlabel'); + set(label_handle, 'string', 'X-axis', 'color', [1 1 1]); + + label_handle = get(gca,'ylabel'); + set(label_handle, 'string', 'Y-axis', 'color', [1 1 1]); + + label_handle = get(gca,'zlabel'); + set(label_handle, 'string', 'Z-axis', 'color', [1 1 1]); + + end + + if ~isempty(campos) + + set(gca,'CameraPosition',campos); + + end + + daspect ([ 1 1 1 ]); + + light + lighting gouraud; + + + fprintf('\n'); + disp(['Plotted ' num2str(num_tcks) ' tcks.']); + +end \ No newline at end of file diff --git a/matlab/plot_test.m b/matlab/plot_test.m new file mode 100644 index 0000000..8f6756e --- /dev/null +++ b/matlab/plot_test.m @@ -0,0 +1,166 @@ +function plot_test(varargin) +% +% PURPOSE: Plots the difference between the analytically calculated gradient and the numerically calculated gradient. +% +% ARGUMENTS: +% +% comparison_files The filename containing the comparison between the analytical and numerical gradients. +% +% OPTIONS (name, description, type, default): +% +% -style +% Style of the plot. +% string +% 'x' +% +% -marker_size +% Size of marker +% int +% 10 +% +% -line_width +% Width of line +% int +% 2 +% +% -param_include +% Parameters to include in the plots. +% matrix_1x: +% +% -test_include +% Tests to include in the plots. +% matrix_1x: + + + description = 'Plots the difference between the analytically calculated gradient and the numerically calculated gradient.'; + + arguments = {'comparison_files', 'The filename containing the comparison between the analytical and numerical gradients.'}; + + options = {... + 'style ', 'x', 'string', 'Style of the plot.';... + 'marker_size ', 10, 'int', 'Size of marker';... + 'line_width ', 2, 'int', 'Width of line';... + 'param_include', [], 'matrix_1x:', 'Parameters to include in the plots.';... + 'test_include', [], 'matrix_1x:', 'Tests to include in the plots.';... + }; + + + parse_arguments + if (help_display) + return; + end + +% End arguments % + + + extension = file_extension(comparison_files); + base = file_base(comparison_files); + + %Load numeric and analytic gradients in 'unzipped' (flattened into vectors) formats. + if strcmp(extension, 'str') + + [analytic, labels] = load_unzip_strands([base '.analytic.' extension]); + numeric = load_unzip_strands([base '.numeric.' extension']); + + elseif strcmp(extension, 'tct') + + [analytic, labels] = load_unzip_tracts([base '.analytic.tct']); + numeric = load_unzip_tracts([base '.numeric.' extension]); + + elseif strcmp(extension, 'sst') + + [analytic, labels] = load_unzip_strand_sets([base '.analytic.' extension]); + numeric = load_unzip_strand_sets([base '.numeric.' extension]); + + elseif strcmp(extension, 'tst') + + [analytic, labels] = load_unzip_tract_sets([base '.analytic.' extension]); + numeric = load_unzip_tract_sets([base '.numeric.' extension]); + + elseif strcmp(extension, 'ssc') + + [analytic, labels] = load_unzip_strand_sections([base '.analytic.' extension]); + numeric = load_unzip_strand_sections([base '.numeric.' extension]); + + elseif strcmp(extension, 'tsc') + + [analytic, labels] = load_unzip_tract_sections([base '.analytic.' extension]); + numeric = load_unzip_tract_sections([base '.numeric.' extension]); + + elseif strcmp(extension, 'trp') + + [analytic, labels] = load_unzip_triples([base '.analytic.' extension]); + numeric = load_unzip_triples([base '.numeric.' extension]); + + elseif strcmp(extension, 'mif') + + [analytic, labels] = load_unzip_image([base '.analytic.' extension]); + numeric = load_unzip_image([base '.numeric.' extension]); + + elseif strcmp(extension, 'tnr') + + base_extension = file_extension(base); + base_base = file_base(base); + + [analytic, labels] = load_unzip_tensor([base_base '.analytic.' base_extension '.' extension]); + numeric = load_unzip_tensor([base_base '.numeric.' base_extension '.' extension]); + + else + error(['Unrecognised extension ''' char(extension) '''.']); + end + + + %Ensure matrices are of the same size. + num_parameters = size(analytic,1); + + if num_parameters ~= size(numeric,1); + error (['Number of parameters in numeric matrix (' num2str(size(numeric,1)) ') does not match number in analytic matrix (' num2str(num_parameters) ').']); + end + + num_tests = size(analytic,2); + + if num_tests ~= size(numeric,2); + error (['Number of parameters in numeric matrix (' num2str(size(numeric,2)) ') does not match number in analytic matrix (' num2str(num_tests) ').']); + end + + %Set to display to all comparisons if not selection explicitly provided. + if isempty(param_include) + param_include = 1:num_parameters; + end + + if isempty(test_include) + test_include = 1:num_tests; + end + + num_param_include = length(param_include(:)); + + %Plot comparisons. + for param_index_i = 1:num_param_include + + param_index = param_include(param_index_i); + + numeric_param = numeric(param_index, test_include)'; + analytic_param = analytic(param_index, test_include)'; + + my_figure(labels{param_index}, param_index_i, num_param_include); + plot(numeric_param, analytic_param, style, 'MarkerSize', marker_size, 'LineWidth',line_width); + + set(get(gca,'xlabel'), 'string', 'numeric', 'color', [1 1 1]); + set(get(gca,'ylabel'), 'string', 'analytic', 'color', [1 1 1]); + + min_value = min([numeric_param; analytic_param]) * 1.1; + max_value = max([numeric_param; analytic_param]) * 1.1; + + hold on; + + plot([min_value; max_value], [min_value; max_value], '-', 'color', [0.7412 0.6549 0.9608]); + + hold off; + + end + + disp('') + disp(['Plotted ' num2str(num_tests) ' tests.']); + disp('') + +end diff --git a/matlab/plot_test_bed.m b/matlab/plot_test_bed.m new file mode 100644 index 0000000..888173e --- /dev/null +++ b/matlab/plot_test_bed.m @@ -0,0 +1,231 @@ +function plot_test_bed(varargin) +% +% PURPOSE: Plots probability landscape of Prob::TestPeaks function. +% +% ARGUMENTS: +% +% peaks_filename Filename containing the spike landscape to plot +% +% OPTIONS (name, description, type, default): +% +% -image_plot +% Image plot instead of surface. +% bool +% 0 +% +% -invert +% Invert the plot upside down. +% bool +% 0 +% +% -extent_of_plot +% Extent of the peaks to plot. +% float +% 15 +% +% -roi_radius +% The region of interest radius, after which the pdf drops off with the square of the distance +% float +% 15 +% +% -barrier_rate +% The rate at which it drops off +% float +% 0.3 +% +% -resolution +% Resolution of the grid +% float +% 1 +% +% -transparency +% Transparency of the plot. +% float +% 0.5 +% +% -samples_location +% Location of the samples to plot +% string +% '' +% +% -style_of_samples +% Style in which the samples will be plotted. +% string +% '-' +% +% -map_samples +% Map samples onto probability landscape. +% bool +% 0 +% +% -start_sample +% Highlight the start sample. +% bool +% 0 +% +% -mark_every_sample +% Mark every nth sample along path (only relevant for iteration plot). +% int +% 0 +% +% -include_samples +% Samples to include in the plots. +% matrix_1x: + + description = 'Plots probability landscape of Prob::TestPeaks function.'; + + arguments = {'samples_location', '', 'string', 'Location of the samples to plot'}; + + options = {... + 'image_plot' , 0, 'bool', 'Image plot instead of surface.';... + 'invert' , 0, 'bool', 'Invert the plot upside down.';... + 'extent_of_plot' , 2.5, 'float', 'Extent of the peaks to plot.';... + 'roi_radius' , 5, 'float', 'The region of interest radius, after which the density function drops off with the square of the distance';... + 'barrier_rate' , 0.3, 'float', 'The rate at which it drops off';... + 'resolution' , 0.1, 'float', 'Resolution of the grid';... + 'transparency' , 0.5, 'float', 'Transparency of the plot.';... + 'style_of_samples', '-', 'string', 'Style in which the samples will be plotted.';... + 'map_samples' , 0, 'bool', 'Map samples onto probability landscape.';... + 'start_sample' , 0, 'bool', 'Highlight the start sample.';... + 'mark_every_sample', 0, 'int', 'Mark every nth sample along path (only relevant for iteration plot).';... + 'include_samples' , [], 'matrix_1x:','Samples to include in the plots.';... + 'peaks_filename', '', 'string', 'Filename containing the spike landscape to plot';... + 'gauss_relative_scale', 1, 'float', 'Relative scale of the quadratic in the ''y'' dimension compared to the ''x'' dimension.';... + }; + + parse_arguments + if (help_display) + return; + end + +% End arguments % + + + grid_points = [-extent_of_plot:resolution:extent_of_plot]'; + + num_grid_points = size(grid_points,1); + + Prob = zeros(num_grid_points, num_grid_points); + + [X,Y] = meshgrid(grid_points, grid_points); + + + if isempty(peaks_filename) + + for x = 1:num_grid_points + + for y = 1:num_grid_points + + point = [grid_points(x) grid_points(y)]; + + Prob(x,y) = test_gaussian_log_prob(point, gauss_relative_scale); + + end + + end + + + else + + peaks = load(peaks_filename); + + for x = 1:num_grid_points + + for y = 1:num_grid_points + + point = [grid_points(x) grid_points(y)]; + + Prob(x,y) = test_peak_log_prob(point, peaks, roi_radius, barrier_rate); + + end + + end + + end + + my_figure(samples_location); + + + + h = surf(X,Y,Prob); + + set(h,'FaceAlpha', transparency); + + + cameratoolbar('Show'); + cameratoolbar('SetMode','orbit'); + + + + if ~isempty(samples_location) + + samples = load(samples_location); + + num_samples = size(samples,1); + + sample_probs = zeros(num_samples,1); + + if isempty(include_samples) + include_samples = 1:num_samples; + end + + if map_samples + + if ~isempty(peaks_filename) + sample_probs = test_peak_log_prob(samples(include_samples,:), peaks, roi_radius, barrier_rate); + else + sample_probs = test_gaussian_log_prob(samples(include_samples,:), gauss_relative_scale); + end + + end + + hold on; + + plot3(samples(include_samples,2), samples(include_samples,1), sample_probs,style_of_samples);% 'mo', 'MarkerEdgeColor', 'blue', 'MarkerFaceColor', 'blue', 'MarkerSize', 4); + + hold off; + + if start_sample + hold on; + + if map_samples + if ~isempty(peaks_filename) + start_prob = test_peak_log_prob(samples(1,:), peaks, roi_radius, barrier_rate); + else + start_prob = test_gaussian_log_prob(samples(1,:), gauss_relative_scale); + end + else + start_prob = 0; + end + + plot3(samples(1,2), samples(1,1), start_prob, 'md', 'MarkerEdgeColor', 'red', 'MarkerFaceColor', 'red', 'MarkerSize', 10); + + + hold off; + end + + if mark_every_sample + + if map_samples + + if ~isempty(peaks_filename) + mark_probs = test_peak_log_prob(samples(1:mark_every_sample:num_samples,:), peaks, roi_radius, barrier_rate); + else + mark_probs = test_gaussian_log_prob(samples(1:mark_every_sample:num_samples,:), gauss_relative_scale); + end + + else + mark_probs = zeros(size([1:mark_every_sample:num_samples]')); + end + + hold on; + + plot3(samples(1:mark_every_sample:num_samples,2), samples(1:mark_every_sample:num_samples,1), mark_probs, 'mo', 'MarkerEdgeColor', 'magenta', 'MarkerFaceColor', 'magenta', 'MarkerSize', 5); + + hold off; + + end + + end + +end \ No newline at end of file diff --git a/matlab/plot_test_gradient.m b/matlab/plot_test_gradient.m new file mode 100644 index 0000000..1d8c345 --- /dev/null +++ b/matlab/plot_test_gradient.m @@ -0,0 +1,635 @@ +function plot_test_gradient(varargin) +% +% PURPOSE: Plots the difference between the analytically calculated gradient and the numerically calculated gradient. +% +% ARGUMENTS: +% +% comparison_files The filename containing the comparison between the analytical and numerical gradients. +% +% OPTIONS (name, description, type, default): +% +% -style +% Style of the plot. +% string +% 'x' +% +% -marker_size +% Size of marker +% int +% 10 +% +% -line_width +% Width of line +% int +% 2 +% +% -include +% Samples to include in the plots. +% matrix_1x: + + + description = 'Plots the difference between the analytically calculated gradient and the numerically calculated gradient.'; + + arguments = {'comparison_files', 'The filename containing the comparison between the analytical and numerical gradients.'}; + + options = {... + 'style ', 'x', 'string', 'Style of the plot.';... + 'marker_size ', 10, 'int', 'Size of marker';... + 'line_width ', 2, 'int', 'Width of line';... + 'include ', [], 'matrix_1x:', 'Samples to include in the plots.';... + }; + + + parse_arguments + if (help_display) + return; + end + +% End arguments % + + + file_parts = regexp(comparison_files, '\.', 'split'); + + extension = file_parts(end); + base = cat(2,file_parts{1:end-1}); + + + + if strcmp(extension, 'str') + + analytic = load_strands([base '.analytic.str']); + numeric = load_strands([base '.numeric.str']); + + num_strands = size(analytic,1); + + if num_strands == 0 + error ('No strands loaded.'); + end + + num_degree = length(analytic{1}); + + if num_strands ~= size(numeric,1) + error(['Size of numeric gradient (' num2str(size(numeric,1)) ') did not match size of analytic gradient (' num2str(num_strands) ').']); + end + + if isempty(include) + include = 1:num_strands; + end + + num_include = length(include); + + degrees = cell(num_degree); + + for degree_i = 1:num_degree + degrees{degree_i} = zeros(3*num_include,2); + end + + for strand_i = include + + analytic_strand = analytic{strand_i}; + numeric_strand = numeric{strand_i}; + + start_index = (strand_i-1)*3 + 1; + end_index = start_index+2; + + for degree_i = 1:num_degree + + degrees{degree_i}(start_index:end_index,1) = numeric_strand(degree_i,:)'; + degrees{degree_i}(start_index:end_index,2) = analytic_strand(degree_i,:)'; + + + end + + + end + + + for degree_i = 1:num_degree + + degree = degrees{degree_i}; + + my_figure([comparison_files '- degree ' num2str(degree_i-1)], degree_i, num_degree, []); + h = plot(degree(:,1), degree(:,2), style, 'MarkerSize', marker_size, 'LineWidth',line_width); + + set(get(gca,'xlabel'), 'string', 'numeric', 'color', [1 1 1]); + set(get(gca,'ylabel'), 'string', 'analytic', 'color', [1 1 1]); + + min_value = min(min(degree)) * 1.1; + max_value = max(max(degree)) * 1.1; + + hold on; + + plot([min_value; max_value], [min_value; max_value], '-', 'color', [0.7412 0.6549 0.9608]); + + hold off; + + end + + + elseif strcmp(extension, 'sst') + + analytic = load_strand_sets([base '.analytic.sst']); + numeric = load_strand_sets([base '.numeric.sst']); + + num_sets = size(analytic,1); + + if num_sets == 0 + error('No sets loaded.'); + elseif size(analytic{1},1) == 0 + error ('Loaded have size 0.'); + end + + num_degree = size(analytic{1}{1},1); + + if num_sets ~= size(numeric,1) + error(['Size of numeric gradient (' num2str(size(numeric,1)) ') did not match size of analytic gradient (' num2str(num_sets) ').']); + end + + if isempty(include) + include = 1:num_sets; + end + + num_include = length(include); + + degrees = cell(num_degree,1); + + for degree_i = 1:num_degree + degrees{degree_i} = zeros(3*num_include,2); + end + + + start_index = 1; + + for set_i = include + + analytic_set = analytic{set_i}; + numeric_set = numeric{set_i}; + + num_strands = size(analytic_set,1); + + if (num_strands ~= size(numeric_set,1)) + error (['Size of numeric gradient, ' num2str(size(numeric_set,1)) ' in set ' num2str(set_i) ' does not match analytic gradient, ' num2str(num_strands) '.']); + end + + for strand_i = 1:num_strands + + analytic_strand = analytic_set{strand_i}; + numeric_strand = numeric_set{strand_i}; + + for degree_i = 1:num_degree + + degrees{degree_i}(start_index:(start_index+2),1) = numeric_strand(degree_i,:)'; + degrees{degree_i}(start_index:(start_index+2),2) = analytic_strand(degree_i,:)'; + + end + + start_index = start_index + 3; + end + + end + + size(degrees{1}) + + for degree_i = 1:num_degree + + degree = degrees{degree_i}; + + my_figure([comparison_files '- degree ' num2str(degree_i-1)], degree_i, num_degree, []); + h = plot(degree(:,1), degree(:,2), style, 'MarkerSize', marker_size, 'LineWidth',line_width); + + set(get(gca,'xlabel'), 'string', 'numeric', 'color', [1 1 1]); + set(get(gca,'ylabel'), 'string', 'analytic', 'color', [1 1 1]); + + min_value = min(min(degree)) * 1.1; + max_value = max(max(degree)) * 1.1; + + hold on; + + plot([min_value; max_value], [min_value; max_value], '-', 'color', [0.7412 0.6549 0.9608]); + + hold off; + + end + + elseif strcmp(extension, 'tst') + + analytic = load_tract_sets([base '.analytic.tst']); + numeric = load_tract_sets([base '.numeric.tst']); + + num_sets = size(analytic,1); + + if num_sets == 0 + error('No sets loaded.'); + elseif size(analytic{1},1) == 0 + error ('Loaded have size 0.'); + end + + num_degree = size(analytic{1}{1},1); + + if num_sets ~= size(numeric,1) + error(['Size of numeric gradient (' num2str(size(numeric,1)) ') did not match size of analytic gradient (' num2str(num_sets) ').']); + end + + if isempty(include) + include = 1:num_sets; + end + + num_include = length(include); + + degrees = cell([3,num_degree]); + + for strand_i = 1:3 + for degree_i = 1:num_degree + degrees{strand_i, degree_i} = zeros(3*num_include,2); + end + end + + start_index = 1; + + for set_i = include + + analytic_set = analytic{set_i}; + numeric_set = numeric{set_i}; + +% num_strands = size(analytic_set,1); + + + for strand_i = 1:3 + + analytic_strand = analytic_set{strand_i}; + numeric_strand = numeric_set{strand_i}; + + for degree_i = 1:num_degree + + degrees{strand_i,degree_i}(start_index:(start_index+2),1) = numeric_strand(degree_i,:)'; + degrees{strand_i,degree_i}(start_index:(start_index+2),2) = analytic_strand(degree_i,:)'; + + end + + start_index = start_index + 3; + end + + end + + size(degrees{1}) + + for strand_i = 1:3 + for degree_i = 1:num_degree + + degree = degrees{strand_i, degree_i}; + + my_figure([comparison_files '- axis ' num2str(strand_i) ' degree ' num2str(degree_i-1)], (strand_i-1)*num_degree + degree_i, 3 * num_degree, []); + h = plot(degree(:,1), degree(:,2), style, 'MarkerSize', marker_size, 'LineWidth',line_width); + + set(get(gca,'xlabel'), 'string', 'numeric', 'color', [1 1 1]); + set(get(gca,'ylabel'), 'string', 'analytic', 'color', [1 1 1]); + + min_value = min(min(degree)) * 1.1; + max_value = max(max(degree)) * 1.1; + + hold on; + + plot([min_value; max_value], [min_value; max_value], '-', 'color', [0.7412 0.6549 0.9608]); + + hold off; + + end + end + + elseif strcmp(extension, 'tct') + + analytic = load_tracts([base '.analytic.tct']); + numeric = load_tracts([base '.numeric.tct']); + + num_tracts = size(analytic,1); + + if num_tracts == 0 + error ('No tracts loaded.'); + end + + num_degree = length(analytic{1,1}); + + if num_tracts ~= size(numeric,1) + error(['Size of numeric gradient (' num2str(size(numeric,1)) ') did not match size of analytic gradient (' num2str(num_tracts) ').']); + end + + if isempty(include) + include = 1:num_tracts; + end + + num_include = length(include); + + axis_degrees = cell(3,num_degree); + + for axis_i = 1:3 + for degree_i = 1:num_degree + axis_degrees{axis_i, degree_i} = zeros(3*num_include,2); + end + end + + for tract_i = include + + start_index = (tract_i-1)*3 + 1; + end_index = start_index+2; + + for axis_i = 1:3 + + analytic_strand = analytic{tract_i, axis_i}; + numeric_strand = numeric{tract_i, axis_i}; + + + for degree_i = 1:num_degree + + axis_degrees{axis_i, degree_i}(start_index:end_index,1) = analytic_strand(degree_i,:)'; + axis_degrees{axis_i, degree_i}(start_index:end_index,2) = numeric_strand(degree_i,:)'; + + + end + + end + + end + + for axis_i = 1:3 + for degree_i = 1:num_degree + + degree = axis_degrees{axis_i, degree_i}; + + my_figure([comparison_files '- Axis ' num2str(axis_i) ', Degree ' num2str(degree_i)], (axis_i-1)*num_degree + degree_i, 3 * num_degree, []); + h = plot(degree(:,1), degree(:,2), style, 'MarkerSize', marker_size, 'LineWidth',line_width); + + set(get(gca,'xlabel'), 'string', 'numeric', 'color', [1 1 1]); + set(get(gca,'ylabel'), 'string', 'analytic', 'color', [1 1 1]); + + min_value = min(min(degree)) * 1.1; + max_value = max(max(degree)) * 1.1; + + hold on; + + plot([min_value; max_value], [min_value; max_value], '-', 'color', [0.7412 0.6549 0.9608]); + + hold off; + + end + end + + + elseif strcmp(extension, 'trp') + + analytic = load_triples([base '.analytic.trp']); + numeric = load_triples([base '.numeric.trp']); + + + num_triples = size(analytic,1); + + if num_triples ~= size(numeric,1) + error(['Size of numeric gradient (' num2str(size(numeric,1)) ') did not match size of analytic gradient (' num2str(num_triples) ').']); + end + + + if isempty(include) + include = 1:num_triples; + end + + num_include = length(include); + + for dim_i = 1:3 + + my_figure([comparison_files ' - Dim ' num2str(dim_i) '.'], dim_i, 3, []); + + h = plot(analytic(include,dim_i), numeric(include,dim_i), style, 'MarkerSize', marker_size, 'LineWidth',line_width); + + set(get(gca,'xlabel'), 'string', 'numeric', 'color', [1 1 1]); + set(get(gca,'ylabel'), 'string', 'analytic', 'color', [1 1 1]); + + min_value = min(min([ analytic(include,dim_i) numeric(include,dim_i)])) * 1.1; + max_value = max(max([ analytic(include,dim_i) numeric(include,dim_i)])) * 1.1; + + hold on; + + plot([min_value; max_value], [min_value; max_value], '-', 'color', [0.7412 0.6549 0.9608]); + + hold off; + + end + + elseif strcmp(extension, 'ssc') + + analytic = load_strand_sections([base '.analytic.ssc']); + numeric = load_strand_sections([base '.numeric.ssc']); + + + num_sections = size(analytic,1); + + if num_sections ~= size(numeric,1) + error(['Size of numeric gradient (' num2str(size(numeric,1)) ') did not match size of analytic gradient (' num2str(num_segments) ').']); + end + + + if isempty(include) + include = 1:num_sections; + end + + num_include = length(include); + + + position_and_tangent = cell(2); + + for pos_or_tang = 1:2 + position_and_tangent{pos_or_tang} = zeros(3*num_include,2); + end + + for section_i = include + + start_index = (section_i-1)*3 + 1; + end_index = start_index+2; + + for pos_or_tang = 1:2 + + position_and_tangent{pos_or_tang}(start_index:end_index,1) = numeric{section_i}(pos_or_tang,:)'; + position_and_tangent{pos_or_tang}(start_index:end_index,2) = analytic{section_i}(pos_or_tang,:)'; + + + end + + + end + + + + for pos_or_tang = 1:2 + + position_or_tangent = position_and_tangent{pos_or_tang}; + + if (pos_or_tang == 1) + title_string = [comparison_files ' - Position.']; + else + title_string = [comparison_files ' - Tangent.']; + end + + my_figure(title_string, pos_or_tang, 2, []); + + h = plot(position_or_tangent(:,1), position_or_tangent(:,2), style, 'MarkerSize', marker_size, 'LineWidth',line_width); + + set(get(gca,'xlabel'), 'string', 'numeric', 'color', [1 1 1]); + set(get(gca,'ylabel'), 'string', 'analytic', 'color', [1 1 1]); + + min_value = min(min(position_or_tangent)) * 1.1; + max_value = max(max(position_or_tangent)) * 1.1; + + hold on; + + plot([min_value; max_value], [min_value; max_value], '-', 'color', [0.7412 0.6549 0.9608]); + + hold off; + + end + + elseif strcmp(extension, 'tsc') + + analytic = load_tract_sections([base '.analytic.tsc']); + numeric = load_tract_sections([base '.numeric.tsc']); + + + num_sections = size(analytic,1); + + if num_sections ~= size(numeric,1) + error(['Size of numeric gradient (' num2str(size(numeric,1)) ') did not match size of analytic gradient (' num2str(num_sections) ').']); + end + + + if isempty(include) + include = 1:num_sections; + end + + num_include = length(include); + + + section_components = cell(4); + + for comp_i = 1:4 + section_components{comp_i} = zeros(3*num_include,2); + end + + for section_i = include + + start_index = (section_i-1)*3 + 1; + end_index = start_index+2; + + for comp_i = 1:4 + + section_components{comp_i}(start_index:end_index,1) = numeric{section_i}(comp_i,:)'; + section_components{comp_i}(start_index:end_index,2) = analytic{section_i}(comp_i,:)'; + + end + + + end + + + + for comp_i = 1:4 + + component = section_components{comp_i}; + + if (comp_i == 1) + title_string = [comparison_files ' - Position.']; + elseif comp_i == 2 + title_string = [comparison_files ' - Tangent.']; + elseif comp_i == 3 + title_string = [comparison_files ' - Width1.']; + else + title_string = [comparison_files ' - Width2.']; + end + + my_figure(title_string, comp_i, 4, []); + + h = plot(component(:,1), component(:,2), style, 'MarkerSize', marker_size, 'LineWidth',line_width); + + set(get(gca,'xlabel'), 'string', 'numeric', 'color', [1 1 1]); + set(get(gca,'ylabel'), 'string', 'analytic', 'color', [1 1 1]); + + min_value = min(min(component)) * 1.1; + max_value = max(max(component)) * 1.1; + + hold on; + + plot([min_value; max_value], [min_value; max_value], '-', 'color', [0.7412 0.6549 0.9608]); + + hold off; + + end + + + elseif strcmp(extension, 'mif') + + analytic_struct = read_image([base '.analytic.mif']); + numeric_struct = read_image([base '.numeric.mif']); + + analytic = analytic_struct.data; + numeric = numeric_struct.data; + + num_include = size(analytic,1) * size(analytic,2) * size(analytic,3) * size(analytic,4); + + analytic = reshape(analytic, num_include, 1); + numeric = reshape(numeric, num_include, 1); + + min_value = min(min([ analytic numeric])) * 1.1; + max_value = max(max([ analytic numeric])) * 1.1; + + my_figure([comparison_files], []); + + h = plot(analytic, numeric, style, 'MarkerSize', marker_size, 'LineWidth',line_width); + + set(get(gca,'xlabel'), 'string', 'numeric', 'color', [1 1 1]); + set(get(gca,'ylabel'), 'string', 'analytic', 'color', [1 1 1]); + + min_value = min(min([ analytic numeric])) * 1.1; + max_value = max(max([ analytic numeric])) * 1.1; + + hold on; + + plot([min_value; max_value], [min_value; max_value], '-', 'color', [0.7412 0.6549 0.9608]); + + hold off; + + elseif strcmp(extension, 'tes') + + analytic = load([base '.analytic.tes']); + numeric = load([base '.numeric.tes']); + + num_include = size(analytic,1); + + + for dim_i = 1:2 + + min_value = min(min([analytic(:,dim_i) numeric(:,dim_i)])) * 1.1; + max_value = max(max([analytic(:,dim_i) numeric(:,dim_i)])) * 1.1; + + my_figure([comparison_files ' - dim ' num2str(dim_i)], dim_i, 2, []); + + h = plot(analytic(:,dim_i), numeric(:,dim_i), style, 'MarkerSize', marker_size, 'LineWidth',line_width); + + set(get(gca,'xlabel'), 'string', 'numeric', 'color', [1 1 1]); + set(get(gca,'ylabel'), 'string', 'analytic', 'color', [1 1 1]); + + min_value = min(min([ analytic(:,dim_i) numeric(:,dim_i)])) * 1.1; + max_value = max(max([ analytic(:,dim_i) numeric(:,dim_i)])) * 1.1; + + hold on; + + plot([min_value; max_value], [min_value; max_value], '-', 'color', [0.7412 0.6549 0.9608]); + + hold off; + end + + else + error(['Unrecognised extension ''' char(extension) '''.']); + end + + + fprintf('\n'); + disp(['Plotted ' num2str(num_include) ' comparisons.']); + + +end diff --git a/matlab/plot_test_peaks.m b/matlab/plot_test_peaks.m new file mode 100644 index 0000000..9a10a11 --- /dev/null +++ b/matlab/plot_test_peaks.m @@ -0,0 +1,195 @@ +function plot_test_peaks(varargin) +% +% PURPOSE: Plots probability landscape of Prob::TestPeaks function. +% +% ARGUMENTS: +% +% peaks_filename Filename containing the spike landscape to plot +% +% OPTIONS (name, description, type, default): +% +% -image_plot +% Image plot instead of surface. +% bool +% 0 +% +% -invert +% Invert the plot upside down. +% bool +% 0 +% +% -extent_of_plot +% Extent of the peaks to plot. +% float +% 15 +% +% -roi_radius +% The region of interest radius, after which the pdf drops off with the square of the distance +% float +% 15 +% +% -barrier_rate +% The rate at which it drops off +% float +% 0.3 +% +% -resolution +% Resolution of the grid +% float +% 1 +% +% -transparency +% Transparency of the plot. +% float +% 0.5 +% +% -samples_location +% Location of the samples to plot +% string +% '' +% +% -style_of_samples +% Style in which the samples will be plotted. +% string +% '-' +% +% -map_samples +% Map samples onto probability landscape. +% bool +% 0 +% +% -start_sample +% Highlight the start sample. +% bool +% 0 +% +% -mark_every_sample +% Mark every nth sample along path (only relevant for iteration plot). +% int +% 0 +% +% -include_samples +% Samples to include in the plots. +% matrix_1x: + + description = 'Plots probability landscape of Prob::TestPeaks function.'; + + arguments = {'peaks_filename', 'Filename containing the spike landscape to plot'}; + + options = {... + 'image_plot' , 0, 'bool', 'Image plot instead of surface.';... + 'invert' , 0, 'bool', 'Invert the plot upside down.';... + 'extent_of_plot' , 15, 'float', 'Extent of the peaks to plot.';... + 'roi_radius' , 15, 'float', 'The region of interest radius, after which the pdf drops off with the square of the distance';... + 'barrier_rate' , 0.3, 'float', 'The rate at which it drops off';... + 'resolution' , 1, 'float', 'Resolution of the grid';... + 'transparency' , 0.5, 'float', 'Transparency of the plot.';... + 'samples_location', '', 'string', 'Location of the samples to plot';... + 'style_of_samples', '-', 'string', 'Style in which the samples will be plotted.';... + 'map_samples' , 0, 'bool', 'Map samples onto probability landscape.';... + 'start_sample' , 0, 'bool', 'Highlight the start sample.';... + 'mark_every_sample', 0, 'int', 'Mark every nth sample along path (only relevant for iteration plot).';... + 'include_samples' , [], 'matrix_1x:','Samples to include in the plots.';... + }; + + parse_arguments + if (help_display) + return; + end + +% End arguments % + + peaks = load(peaks_filename); + + grid_points = [-extent_of_plot:resolution:extent_of_plot]'; + + num_grid_points = size(grid_points,1); + + Prob = zeros(num_grid_points, num_grid_points); + + [X,Y] = meshgrid(grid_points, grid_points); + + for x = 1:num_grid_points + + for y = 1:num_grid_points + + point = [grid_points(x) grid_points(y)]; + + Prob(x,y) = test_peak_log_prob(point, peaks, roi_radius, barrier_rate); + + end + + end + + my_figure(peaks_filename); + + + + h = surf(X,Y,Prob); + + set(h,'FaceAlpha', transparency); + + + cameratoolbar('Show'); + cameratoolbar('SetMode','orbit'); + + + + if ~isempty(samples_location) + + samples = load(samples_location); + + num_samples = size(samples,1); + + sample_probs = zeros(num_samples,1); + + if isempty(include_samples) + include_samples = 1:num_samples; + end + + if map_samples + + sample_probs = test_peak_log_prob(samples(include_samples,:), peaks, roi_radius, barrier_rate); + + end + + hold on; + + plot3(samples(include_samples,2), samples(include_samples,1), sample_probs,style_of_samples);% 'mo', 'MarkerEdgeColor', 'blue', 'MarkerFaceColor', 'blue', 'MarkerSize', 4); + + hold off; + + if start_sample + hold on; + + if map_samples + start_prob = test_peak_log_prob(samples(1,:), peaks, roi_radius, barrier_rate); + else + start_prob = 0; + end + + plot3(samples(1,2), samples(1,1), start_prob, 'md', 'MarkerEdgeColor', 'red', 'MarkerFaceColor', 'red', 'MarkerSize', 10); + + + hold off; + end + + if mark_every_sample + + if map_samples + mark_probs = test_peak_log_prob(samples(1:mark_every_sample:num_samples,:), peaks, roi_radius, barrier_rate); + else + mark_probs = zeros(size([1:mark_every_sample:num_samples]')); + end + + hold on; + + plot3(samples(1:mark_every_sample:num_samples,2), samples(1:mark_every_sample:num_samples,1), mark_probs, 'mo', 'MarkerEdgeColor', 'blue', 'MarkerFaceColor', 'blue', 'MarkerSize', 4); + + hold off; + + end + + end + +end \ No newline at end of file diff --git a/matlab/plot_test_scan.m b/matlab/plot_test_scan.m new file mode 100644 index 0000000..30e9a47 --- /dev/null +++ b/matlab/plot_test_scan.m @@ -0,0 +1,237 @@ +function plot_scan(varargin) +% +% PURPOSE: Plots the output of 'scan_strands' +% +% ARGUMENTS: +% +% scan_filename The filename of the '.mif', '.sst', or '.tst' scan_image containing the scan. +% +% OPTIONS (name, description, type, default): +% +% -scale_range +% The range of the colour scale plot. +% matrix_1x2 +% +% -state_filename +% Filename of the states to overlay on the surface plot. +% string +% '' +% +% -include_states +% States to include in plot. +% matrix_:x: +% +% -mark_rand_samples +% Mark samples where the momentum is randomized. +% bool +% 0 +% +% -highlight_samples +% Highlight selected samples with a larger marker +% matrix_:x: +% +% -image +% Plot as a flat image instead of a surface. +% bool +% 0 +% +% -exponential +% Change plot to display the probability instead of the log probability. +% bool +% 0 +% +% -offset +% Offset the values by a constant amount (used in conjunction with '-exponential'). +% float +% 0 +% +% -transparency +% The transparency of the surface. +% float +% 0.5 + + + description = 'Plots the output of ''scan_strands'''; + + arguments = {'scan_filename', 'The filename of the ''.mif'', ''.sst'', or ''.tst'' scan_image containing the scan.'}; + + options = {... + 'scale_range ', [], 'matrix_1x2', 'The range of the colour scale plot.';... + 'state_filename ', '', 'string' , 'Filename of the states to overlay on the surface plot.';... + 'include_states ', [], 'matrix_:x:', 'States to include in plot.';... + 'mark_rand_samples', 1, 'bool', 'Mark samples where the momentum is randomized.';... + 'highlight_samples', [], 'matrix_:x:', 'Highlight selected samples with a larger marker';... + 'image_plot ', 0, 'bool' , 'Plot as a flat image instead of a surface.';... + 'map_to_surface ', 0, 'bool' , 'Maps the probabilities on the surfaces of the scans, representing the probability due to that dimension.';... + 'exponential ', 0, 'bool' , 'Change plot to display the probability instead of the log probability.';... + 'offset ', 0, 'float' , 'Offset the values by a constant amount (used in conjunction with ''-exponential'').';... + 'transparency ', 0.5, 'float' , 'The transparency of the surface.';... + }; + + + multiple_last_arguments = 0; + + parse_arguments + if (help_display) + return; + end + +% End arguments % + + figure_name = strrep(scan_filename,'_',' '); + + if exponential + figure_name = [figure_name ' - Probability']; + else + figure_name = [figure_name ' - Log Probability']; + end + + + %If 2d scan + if ~strcmp(file_extension(scan_filename), 'mif') + error(['Unrecognised file_extension, ''' file_extension(scan_filename) '''.']); + end + + scan_image = read_image(scan_filename); + + if ~isfield(scan_image, 'data') + error(['Could not load scan_image from ' scan_filename ]); + end + + axis1_scale = str2num(scan_image.axis1_scale); + axis2_scale = str2num(scan_image.axis2_scale); + + scan_range1 = [-axis1_scale:2*axis1_scale/(scan_image.dim(1)-1):axis1_scale]; + scan_range2 = [-axis2_scale:2*axis2_scale/(scan_image.dim(2)-1):axis2_scale]; + + if offset > 0 + scan_image.data = scan_image.data + offset; + end + + if exponential + scan_image.data = exp(scan_image.data); + end + + + %Plot as a flat image. + if image_plot + + my_figure(figure_name); + + if isempty(scale_range) + imagesc(scan_range1, scan_range2, scan_image.data); + else + imagesc(scan_range1, scan_range2, scan_image.data, scale_range); + end + + colorbar; + + %Else plot as a surface. + else + + [X,Y] = meshgrid(scan_range1, scan_range2); + + my_figure(figure_name, 1, 1, [], 1); + + h = surf(X, Y, scan_image.data); + + + if transparency ~= 1 + set(h,'FaceAlpha', transparency); + end + + %If states provided (i.e. a MCMC sequence) plot projection on to + %scan slice. + if ~isempty(state_filename) + + trans_data = scan_image.data'; + + iter_filename = [file_base(state_filename) '.iter.' file_extension(state_filename)]; + + if exist(iter_filename) + states = load(iter_filename); + else + states = load(state_filename); + end + + props = read_properties([state_filename '.prp']); + + num_states = size(states,1); + + proj1 = states(:,1) ./ str2num(scan_image.axis1_scale); + proj2 = states(:,2) ./ str2num(scan_image.axis2_scale); + px = zeros(num_states,1); + + %If map_to_surface option is selected, map probability values via + %bilinear interpolation to scan surface. + if map_to_surface + + for state_i = 1:num_states + + if (proj1(state_i) >= -1) && (proj1(state_i) <= 1) && (proj2(state_i) >= -1) && (proj2(state_i) <= 1) + + index1 = (scan_image.dim(1)-1) * (proj1(state_i) + 1)/2 + 1; + index2 = (scan_image.dim(2)-1) * (proj2(state_i) + 1)/2 + 1; + + low1 = floor(index1); + high1 = ceil(index1); + frac1 = rem(index1,1); + + low2 = floor(index2); + high2 = ceil(index2); + frac2 = rem(index2,1); + + px(state_i) = (1-frac2) * ((1-frac1) * trans_data(low1, low2) + frac1 * trans_data(high1, low2)) + ... + frac2 * ((1-frac1) * trans_data(low1, high2) + frac1 * trans_data(high1, high2)); + + end + + end + + state_plot_colour = [1 0.5 1]; + + else + + state_plot_colour = 'yellow'; + + end + + + hold on; + + + plot3(states(:,1), states(:,2), px, 'Color', state_plot_colour); + + plot3(states(1,1), states(1,2), px(1), 'md', 'MarkerEdgeColor', 'red', 'MarkerFaceColor', 'red', 'MarkerSize', 10); + + if mark_rand_samples + + sample_period = str2double(props.sample_period); + + mark_samples = sample_period:sample_period:num_states; + + plot3(states(mark_samples,1), states(mark_samples,2), px(mark_samples), 'mo', 'MarkerEdgeColor', 'blue', 'MarkerFaceColor', 'blue', 'MarkerSize', 5); + + end + + if ~isempty(highlight_samples) + + highlight_samples = highlight_samples + 1; + + highlight_samples = highlight_samples(highlight_samples < num_states); + + plot3(states(highlight_samples,1), states(highlight_samples,2), px(highlight_samples), 'md', 'MarkerEdgeColor', 'green', 'MarkerFaceColor', 'green', 'MarkerSize', 8); + + end + + hold off + + end + + end + + xlabel('Axis 1'); + ylabel('Axis 2'); + + +end diff --git a/matlab/plot_tract_sets.m b/matlab/plot_tract_sets.m new file mode 100644 index 0000000..4cd46e1 --- /dev/null +++ b/matlab/plot_tract_sets.m @@ -0,0 +1,436 @@ +function main_fig = plot_tracts_sets(varargin) +% +% PURPOSE: Plots strands from strand files, and optionally displays reference sphere and voxels +% +% ARGUMENTS: +% +% tracts_filename The filename of the tracts ('.tct' format). +% +% OPTIONS (name, description, type, default): +% +% -include +% The indices of the samples to include in the plot +% matrix_:x: +% +% -last +% Overrides '-include' to only print the last tract set. +% bool +% 0 +% +% -tract_include +% The indices of the tracts to include in the plot +% matrix_:x: +% +% -colours_of_bundles +% Colours of the plotted strands +% matrix_:x3 +% +% -voxel_size +% Size of reference voxel +% float +% 0.15 +% +% -num_voxels +% Number of reference voxels +% int +% 3 +% +% -cube_size +% Size of reference voxel +% float +% 0 +% +% -strand_radius +% Radii of the plotted strands. (NB: can only be used with '-style' option 'strands'). +% float +% 0.02 +% +% -style +% Change plot to 'line style'.(NB: Only relevant with '-num_width_sections' option > 0). +% string +% 'tracts' +% +% -tube_corners +% Set the number of tube corners for 'tracts' style. +% int +% 12 +% +% -num_length_sections +% Number of samples along the length of the tracts. +% int +% 100 +% +% -properties_plot +% Do, don't or only plot the extended properties associated with the tract set (0 -> don't plot properties, 1 -> plot properties, 2 -> only plot properties). +% int +% 1 +% +% -new_plot +% Plots strands in new figures for comparision +% bool +% 0 +% +% -transparency +% Fix the transparency of the tracts to a set value. If 0 the intensities of the of the tracts are used instead. +% float +% 1 +% +% -sphere_radius +% Size of reference sphere +% float +% 0 + + main_fig = -1; + + global colours_of_bundles; + + description = 'Plots strands from strand files, and optionally displays reference sphere and voxels'; + + arguments = {'tracts_filename', 'The filename of the tracts (''.tct'' format).'}; + + options = {... + 'include ', [], 'matrix_:x:', 'The indices of the samples to include in the plot';... + 'dont_include ', [], 'matrix_:x:', 'The indices of the samples not to include in the plot';... + 'last', 0, 'bool', 'Overrides ''-include'' to only print the last tract set.';... + 'tract_include ', [], 'matrix_:x:', 'The indices of the tracts to include in the plot';... + 'colours_of_bundles', colours_of_bundles, 'matrix_:x3', 'Colours of the plotted strands';... + 'voxel_size ', 0.15, 'float', 'Size of reference voxel';... + 'num_voxels ', -1, 'int', 'Number of reference voxels';... + 'cube_size ', 0, 'float', 'Size of reference voxel';... + 'strand_radius ', 0.02, 'float', 'Radii of the plotted strands. (NB: can only be used with ''-style'' option ''strands'').';... + 'style ', 'tracts', 'string', 'Change plot to ''line style''.(NB: Only relevant with ''-num_width_sections'' option > 0).';... + 'tube_corners ', 12, 'int', 'Set the number of tube corners for ''tracts'' style.';... + 'num_length_sections', 100, 'int', 'Number of samples along the length of the tracts.';... + 'properties_plot', 0, 'int', 'Do, don''t or only plot the extended properties associated with the tract set (0 -> don''t plot properties, 1 -> plot properties, 2 -> only plot properties).';... + 'new_plot', 0, 'bool', 'Plots strands in new figures for comparision';... + 'transparency' ,1, 'float', 'Fix the transparency of the tracts to a set value. If 0 the intensities of the of the tracts are used instead.';... + 'sphere_radius ', 0, 'float', 'Size of reference sphere';... + 'no_axes', 0, 'bool', 'Removes axes from plot';... + 'num_width_sections ', -1, 'int', 'Number of strands to plot along each axis. If zero the default 3D surface option will be used instead.';... + 'clean', 0, 'bool', 'Removes everything else from plot';... + 'no_voxline_highlight', 0, 'bool', 'Doesn''t highlight corner axes of voxel lines.';... + 'oblong', 0, 'bool', 'Prints an oblong tractlet rather than cylindrical';... + 'happy_colours', 0, 'bool', 'Uses ''happy colours''';... + 'inv_happy_colours', 0, 'bool', 'Uses the inverse of ''happy colours''';... + 'true_tracts_plot', 0, 'bool', 'Plots true tracts (as determined from observed image)';... + 'no_density_plot', 0, 'bool', 'Omitts density from properties plot';... + 'highlight_axes', 0, 'bool', 'Highlights the axes when printing in ''strand'' or ''line'' style';... + 'invisible', 0, 'bool', 'Makes the figure invisible (for automatically saving afterwards).'}; + + parse_arguments + if (help_display) + return; + end + + if clean + voxel_size = 0; + sphere_radius = 0; + no_axes = 1; + end + + +% End arguments % + if happy_colours + + if inv_happy_colours + error('Can''t use ''-happy_colours'' and ''-inv_happy_colours'' simultaneously'); + end + + load('/home/tclose/Data/Tractography/misc/comb_happy_colours.mat'); + + elseif inv_happy_colours + + load('/home/tclose/Data/Tractography/misc/inv_comb_happy_colours.mat'); + + end + + + if ~strcmp(file_extension(tracts_filename), 'tst') + error (['Extension, ''' file_extension(tracts_filename) ''' is not a valid tract set file (''.tst'').']); + end + + + [tract_sets, properties, set_prop_keys, set_prop_values, elem_prop_keys, elem_prop_values] = load_tract_sets(tracts_filename); + + num_sets = size(tract_sets,1); + + if (num_voxels < 0 || true_tracts_plot) + [num_voxels, true_location] = get_observed_properties(properties); + num_voxels = num_voxels(1); + end + + [loaded_num_length_sections, loaded_num_width_sections] = get_num_section_properties(properties,style); + + if num_length_sections == -1 + num_length_sections = loaded_num_length_sections; + end + + if num_width_sections == -1 + num_width_sections = loaded_num_width_sections; + end + + if last + + if ~isempty(dont_include) || ~isempty(include) + error('Error! -last cannot be used simultaneously with -include or -dont_include options'); + end + + include = size(tract_sets,1)-1; + + else + + if ~isempty(dont_include) + + if ~isempty(include) + error('Error! -include and -dont_include options cannot be used simultaneously'); + end + + include = [1:num_sets]; + + include(dont_include) = []; + + include = include -1; + + end + + end + + if length(include) == 1 + properties_plot = 0; + end + + if properties_plot == 0 + num_figs = 1; + elseif properties_plot == 1 + num_figs = 3; + elseif properties_plot == 2 + num_figs = 2; + end + + if true_tracts_plot + num_figs = num_figs + 1; + end + + if properties_plot ~= 2 + + overall_max_bundle_index = 0; + + for set_i = 1:num_sets + + num_tracts = size(tract_sets{set_i},1); + + if size(elem_prop_keys,2) + prop_values = elem_prop_values{set_i}; + else + prop_values = []; + end + + bundle_indices = get_properties(elem_prop_keys, prop_values, 'bundle_index', [0:1:(num_tracts-1)]', num_tracts); + + max_bundle_index = max(bundle_indices); + + if max_bundle_index > overall_max_bundle_index + overall_max_bundle_index = max_bundle_index; + end + end + + if highlight_axes + + overall_max_bundle_index = (overall_max_bundle_index+1)*4-1; + + end + + set_bundle_colours(overall_max_bundle_index); + + + %Set up the figure. + main_fig = my_figure(tracts_filename, 1, num_figs, [1 1 1], 1, [],[],~invisible); + + if isempty(include) + include = 1:num_sets; + else + include = include+1; %Convert to Matlab indexing + end + + for set_i = include + + prop_values = elem_prop_values{set_i}; + tracts = tract_sets{set_i}; + + if ~isempty(tract_include) + tracts = tracts(tract_include+1,:); + prop_values = prop_values(tract_include+1,:); + end + + num_tracts = size(tracts,1); + + intensities = get_properties(elem_prop_keys, prop_values, 'intensity', 1.0, num_tracts); + bundle_indices = get_properties(elem_prop_keys, prop_values, 'bundle_index', (0:1:(num_tracts-1))', num_tracts); + + if strfind('tracts', style) == 1 + + add_tracts_to_plot(tracts, colours_of_bundles, intensities, ones(num_tracts,1), tube_corners, num_length_sections, transparency, bundle_indices); + + elseif strfind('tubes', style) == 1 + + [strands, bundle_indices] = tracts2strands(tracts, ones(num_tracts,1), num_width_sections, highlight_axes, oblong, bundle_indices); + tcks = strands2tcks(strands, num_length_sections); + + radii = ones(size(tcks)) * strand_radius; + + add_tcks_to_plot(tcks, radii, colours_of_bundles, bundle_indices, tube_corners); + + elseif strfind('lines', style) == 1 + + [strands, bundle_indices] = tracts2strands(tracts, ones(num_tracts,1), num_width_sections, highlight_axes, oblong, bundle_indices); + tcks = strands2tcks(strands, num_length_sections); + + add_lines_to_plot(tcks, colours_of_bundles, bundle_indices); + + else + + error(['Urecogised style option ''' style '''.']); + + end + + end + + add_sphere_to_plot(sphere_radius, properties); + + if voxel_size ~= 0 + + add_vox_lines_to_plot(voxel_size,num_voxels,~no_voxline_highlight); + + end + + set(gcf, 'color', [0 0 0]); + + + if no_axes + +% set(gca, 'visible', 'off'); + + else + + label_handle = get(gca,'xlabel'); + set(label_handle, 'string', 'X-axis', 'color', [1 1 1]); + + label_handle = get(gca,'ylabel'); + set(label_handle, 'string', 'Y-axis', 'color', [1 1 1]); + + label_handle = get(gca,'zlabel'); + set(label_handle, 'string', 'Z-axis', 'color', [1 1 1]); + + end + + daspect ([ 1 1 1 ]); + + light + lighting gouraud; + + + fprintf('\n'); + disp(['Plotted ' num2str(length(include)) ' of ' num2str(num_sets) ' tract sets.']); + + end + + + if properties_plot && length(include) ~= 1 + + if exist([tracts_filename 'x']) + + ext_props_fig = plot_extend_properties([tracts_filename 'x'], set_prop_keys, set_prop_values,include, num_figs - true_tracts_plot - 1, num_figs); + + end + + + if exist([tracts_filename 'xx']) + + if no_density_plot +% omit_properties = cell(1,1) + omit_properties{1} = 'density'; + else + omit_properties = cell(0); + end + + + ext_ext_props_fig = plot_extend_elem_properties([tracts_filename 'xx'], elem_prop_keys, elem_prop_values, colours_of_bundles, include, tract_include, num_figs - true_tracts_plot, num_figs, omit_properties); + + end + + end + + + if true_tracts_plot + + if isempty(true_location) + error('Could not find true state location in observed image.'); + end + + my_figure(['True config: ' true_location], num_figs, num_figs); + + cameratoolbar('Show'); + cameratoolbar('SetMode','orbit'); + + + if (file_extension(true_location) == 'tck') + + [true_tcks, ~, true_prop_keys, true_prop_values] = load_tcks(true_location); + + num_true_tcks = size(true_tcks,1); + + true_bundle_indices = get_properties(true_prop_keys, true_prop_values, 'bundle_index', [0:1:(num_true_tcks-1)]', num_true_tcks); + true_radii = get_properties(true_prop_keys, true_prop_values, 'track_radius', 0.03, num_true_tcks); + + %Map bundle indices back consecutive range from 0 upwards. + mapped_indices = true_bundle_indices; + unique_indices = unique(true_bundle_indices); + for unique_i = 1:length(unique_indices) + mapped_indices(true_bundle_indices == unique_indices(unique_i)) = unique_i - 1; + end + + set_bundle_colours(max(unique_indices)); + + add_tcks_to_plot(true_tcks,true_radii,colours_of_bundles, mapped_indices,tube_corners); + + elseif (file_extension(true_location) == 'tct') + + true_tracts = load_tracts(true_location); + + num_true_tracts = size(true_tracts,1); + + set_bundle_colours(num_true_tracts-1); + + add_tracts_to_plot(true_tracts, colours_of_bundles, ones(num_true_tracts,1), ones(num_true_tracts,1), tube_corners, num_length_sections, 1.0); + + else + error(['Unrecognised extension of true location file ''' true_location '''.']); + end + + + if voxel_size ~= 0 + + add_vox_lines_to_plot(voxel_size,num_voxels,~no_voxline_highlight); + + end + + set(gcf, 'color', [0 0 0]); + + label_handle = get(gca,'xlabel'); + set(label_handle, 'string', 'X-axis', 'color', [1 1 1]); + + label_handle = get(gca,'ylabel'); + set(label_handle, 'string', 'Y-axis', 'color', [1 1 1]); + + label_handle = get(gca,'zlabel'); + set(label_handle, 'string', 'Z-axis', 'color', [1 1 1]); + + daspect ([ 1 1 1 ]); + + light + lighting gouraud; + + end + + +end \ No newline at end of file diff --git a/matlab/plot_tracts.m b/matlab/plot_tracts.m new file mode 100644 index 0000000..4bfe5e9 --- /dev/null +++ b/matlab/plot_tracts.m @@ -0,0 +1,300 @@ +function main_fig = plot_tracts(varargin) +% +% PURPOSE: Plots strands from strand files, and optionally displays reference sphere and voxels +% +% ARGUMENTS: +% +% tracts_filename The filename of the tracts ('.tct' format). +% +% OPTIONS (name, description, type, default): +% +% -include +% The indices of the strands to include in the plot +% matrix_:x: +% +% -colours_of_bundles +% Colours of the plotted strands +% matrix_:x3 +% +% -voxel_size +% Size of reference voxel +% float +% 0.15 +% +% -num_voxels +% Number of reference voxels +% int +% 3 +% +% -cube_size +% Size of reference voxel +% float +% 0 +% +% -num_length_sections +% Number of segments to plot for each tract. +% int +% 100 +% +% -strand_radius +% Radii of the plotted strands. (NB: can only be used with '-style' option 'strands'). +% float +% 0.02 +% +% -num_width_sections +% Number of strands to plot along each axis. If zero the default 3D surface option will be used instead. +% int +% 2 +% +% -style +% Change plot to 'line style'.(NB: Only relevant with '-num_width_sections' option > 0). +% string +% 'tracts' +% +% -tube_corners +% Change plot to 'line style'.(NB: Only relevant with '-num_width_sections' option = 0). +% int +% 12 +% +% -sphere_radius +% Size of reference sphere +% float +% 0 +% +% -no_axes +% Removes axes from plot +% bool +% 0 +% +% -clean +% Removes everything else from plot +% bool +% 0 +% +% -colour_key +% Displays colour key +% bool +% 0 +% +% -oblong +% Prints an oblong tractlet rather than cylindrical +% bool +% 0 +% +% -happy_colours +% Uses 'happy colours' +% bool +% 0 +% +% -inv_happy_colours +% Uses the inverse of 'happy colours' +% bool +% 0 +% +% -ignore_bundles +% Ignores bundle indices when plotting colours. +% bool +% 0 +% +% -no_voxline_highlight +% Doesn't highlight corner axes of voxel lines. +% bool +% 0 +% +% -transparency +% Fix the transparency of the tracts to a set value. If 0 the intensities of the of the tracts are used instead. +% float +% 1 +% +% -highlight_axes +% Highlights the axes when printing in 'strand' or 'line' style +% bool +% 0 + + main_fig = -1; + + global colours_of_bundles; + + description = 'Plots strands from strand files, and optionally displays reference sphere and voxels'; + + arguments = {'tracts_filename', 'The filename of the tracts (''.tct'' format).'}; + + options = {... + 'include ', [], 'matrix_:x:', 'The indices of the strands to include in the plot';... + 'colours_of_bundles', colours_of_bundles, 'matrix_:x3', 'Colours of the plotted strands';... + 'voxel_size ', 0.15, 'float', 'Size of reference voxel';... + 'num_voxels ', 3, 'int', 'Number of reference voxels';... + 'cube_size ', 0, 'float', 'Size of reference voxel';... + 'num_length_sections ', 100, 'int', 'Number of segments to plot for each tract.';... + 'strand_radius ', 0.02, 'float', 'Radii of the plotted strands. (NB: can only be used with ''-style'' option ''strands'').';... + 'num_width_sections ', 2, 'int', 'Number of strands to plot along each axis. If zero the default 3D surface option will be used instead.';... + 'style ', 'tractlets', 'string', 'Change plot to ''line style''.(NB: Only relevant with ''-num_width_sections'' option > 0).';... + 'tube_corners ', 12, 'int', 'Change plot to ''line style''.(NB: Only relevant with ''-num_width_sections'' option = 0).';... + 'sphere_radius ', 0, 'float', 'Size of reference sphere';... + 'no_axes', 0, 'bool', 'Removes axes from plot';... + 'clean', 0, 'bool', 'Removes everything else from plot';... + 'colour_key', 0, 'bool', 'Displays colour key';... + 'oblong', 0, 'bool', 'Prints an oblong tractlet rather than cylindrical';... + 'happy_colours', 0, 'bool', 'Uses ''happy colours''';... + 'inv_happy_colours', 0, 'bool', 'Uses the inverse of ''happy colours''';... + 'ignore_bundles', 0, 'bool', 'Ignores bundle indices when plotting colours.';... + 'no_voxline_highlight', 0, 'bool', 'Doesn''t highlight corner axes of voxel lines.';... + 'transparency' ,1, 'float', 'Fix the transparency of the tracts to a set value. If 0 the intensities of the of the tracts are used instead.';... + 'highlight_axes', 0, 'bool', 'Highlights the axes when printing in ''strand'' or ''line'' style';... + 'invisible', 0, 'bool', 'Makes the figure invisible (for automatically saving afterwards).'}; + + + parse_arguments + if (help_display) + return; + end + + if clean + voxel_size = 0; + sphere_radius = 0; + no_axes = 1; + end + +% End arguments % + + if happy_colours + + if inv_happy_colours + error('Can''t use ''-happy_colours'' and ''-inv_happy_colours'' simultaneously'); + end + + load('/home/tclose/Data/Tractography/misc/comb_happy_colours.mat'); + + elseif inv_happy_colours + + load('/home/tclose/Data/Tractography/misc/inv_comb_happy_colours.mat'); + + end + + if ~strcmp(file_extension(tracts_filename), 'tct') + error (['Extension, ''' file_extension(tracts_filename) ''' is not a valid tract file (''.tct'').']); + end + + + [tracts, props, prop_keys, prop_values] = load_tracts(tracts_filename); + + num_loaded_tracts = size(tracts,1); + + bundle_indices = get_properties(prop_keys, prop_values, 'bundle_index', (0:(num_loaded_tracts-1))', num_loaded_tracts); + + if ~isempty(include) + mapped_include = find(ismember(bundle_indices,include)); + tracts = tracts(mapped_include,:); + + if ignore_bundles + bundle_indices = include; + else + bundle_indices = mapped_include; + end + prop_values = prop_values(mapped_include,:); + end + + % base_widths = get_properties(prop_keys, prop_values, 'base_width', 1.0, num_tracts); + + num_tracts = size(tracts,1); + + max_bundle_index = max(bundle_indices); + + if highlight_axes + num_required_colours = max_bundle_index * 4; + else + num_required_colours = max_bundle_index; + end + + + set_bundle_colours(num_required_colours); + + %Set up the figure + main_fig = my_figure(strrep(tracts_filename,'_',''), 1, 1, [1 1 1], 1, [],[],~invisible); + + cameratoolbar('Show'); + cameratoolbar('SetMode','orbit'); + + + % If '-num_width_sections' parameter is not set plot the boundary of the tract + % instead. + if strfind(style, 'tractlets') == 1 + + if oblong + error('''-oblong'' option cannot be used with ''tracts'' style'); + end + + + if highlight_axes + error('''-highlight_axes'' option cannot be used with ''tracts'' style'); + end + + add_tracts_to_plot(tracts, colours_of_bundles, ones(num_tracts,1), ones(num_tracts,1), tube_corners, num_length_sections, transparency, bundle_indices); + + elseif strfind(style, 'tubes') == 1 + + [strands, bundle_indices] = tracts2strands(tracts, ones(num_tracts,1), num_width_sections, highlight_axes, oblong, bundle_indices); + tcks = strands2tcks(strands); + + radii = ones(size(tcks)) * strand_radius; + + add_tcks_to_plot(tcks, radii, colours_of_bundles, bundle_indices); + + %[tcks, colours_of_bundles] = display_strands(tcks, colours_of_bundles, include, 'bundle', line_style); + + elseif strfind('lines', style) == 1 + + [strands, bundle_indices] = tracts2strands(tracts, ones(num_tracts,1), num_width_sections, highlight_axes, oblong, bundle_indices); + tcks = strands2tcks(strands); + + add_lines_to_plot(tcks, colours_of_bundles, bundle_indices); + + else + + error(['Urecogised style option ''' style '''.']); + + end + + add_sphere_to_plot(sphere_radius); + + + if voxel_size ~= 0 + + add_vox_lines_to_plot(voxel_size,num_voxels,~no_voxline_highlight); + + end + + set(gcf, 'color', [0 0 0]); + + if no_axes + + set(gca, 'visible', 'off'); + + else + + label_handle = get(gca,'xlabel'); + set(label_handle, 'string', 'X-axis', 'color', [1 1 1]); + + label_handle = get(gca,'ylabel'); + set(label_handle, 'string', 'Y-axis', 'color', [1 1 1]); + + label_handle = get(gca,'zlabel'); + set(label_handle, 'string', 'Z-axis', 'color', [1 1 1]); + + end + + daspect ([ 1 1 1 ]); + + light + lighting gouraud; + + + fprintf('\n'); + disp(['Plotted ' num2str(num_tracts) ' tracts.']); + + + if colour_key + add_colour_key(bundle_indices); + end + +end diff --git a/matlab/plotbts.m b/matlab/plotbts.m new file mode 100644 index 0000000..ec5bdf8 --- /dev/null +++ b/matlab/plotbts.m @@ -0,0 +1,25 @@ +function fig = plotbts(varargin) + + if nargin == 0 + error('No arguments supplied'); + end + + filename = varargin{1}; + + if file_extension(filename) == 'str' + fig = plot_strands(varargin{:}); + elseif file_extension(filename) == 'sst' + fig = plot_strand_sets(varargin{:}); + elseif file_extension(filename) == 'tct' + fig = plot_tracts(varargin{:}); + elseif file_extension(filename) == 'tst' + fig = plot_tract_sets(varargin{:}); + elseif file_extension(filename) == 'tck' + fig = plot_tcks(varargin{:}); + elseif file_extension(filename) == 'mif' + fig = plot_image(varargin{:}); + else + error(['Unrecognised extension, ''' file_extension(filename) '''.']); + end + +end \ No newline at end of file diff --git a/matlab/read_element_properties.m b/matlab/read_element_properties.m new file mode 100644 index 0000000..eefdfce --- /dev/null +++ b/matlab/read_element_properties.m @@ -0,0 +1,48 @@ +function [keys, values] = read_element_properties(location) + + disp('Reading properties...'); + + file = fopen(location, 'r'); + + if (file == -1) + error([ 'Could not open file ' location '!' ]); + end + + + header_line = fgetl(file); + + %Seperate the header tag from the key list. + [header, key_string] = strtok(header_line,':'); + + if ~strcmp(header, '%%% Extended Properties File %%% - keys') + error(['Extended properties header tag ''%%% Extended Properties File %%% - keys'' was not found at start of extended properties file ''' location '']); + end + + keys = parse_properties_row(key_string(3:end)); + + num_keys = length(keys); + + values = cell(0, num_keys); + + row_i = 1; + + value_line = fgetl(file); + + while value_line ~= -1; + + value_row = parse_properties_row(value_line); + + if size(value_row,2) ~= num_keys + error(['Number of values on line ' num2str(row_i) ' (' num2str(size(value_row,2)) ') does not match number of keys (' num2str(num_keys) ').']); + end + + values(row_i, :) = value_row; + + value_line = fgetl(file); + row_i = row_i + 1; %#ok + + end + + disp('Finished reading properties...'); + +end diff --git a/matlab/read_element_property_keys.m b/matlab/read_element_property_keys.m new file mode 100644 index 0000000..64e65a8 --- /dev/null +++ b/matlab/read_element_property_keys.m @@ -0,0 +1,54 @@ +function [keys, values] = read_element_properties(location) + + file = fopen(location, 'r'); + + if (file == -1) + error([ 'Could not open file ' filename '!' ]); + end + + + header_line = fgetl(file); + + %Seperate the header tag from the key list. + [header, key_string] = strtok(header_line,':'); + + if ~strcmp(header, '%%% Extended Properties File %%% - keys') + error(['Extended properties header tag ''%%% Extended Properties File %%% - keys'' was not found at start of extended properties file ''' location '']); + end + + %String ': ' from start of keys and trailing tab from end. + key_string = deblank(key_string(3:end)); + + keys = cell(0); + + keys = regexp(key_string,'\t','split')'; + + num_keys = size(keys,1); + + values = cell(0, num_keys); + + row_i = 1; + + value_line = fgetl(file); + + while value_line ~= -1; + + value_row = regexp(value_line,'\t','split'); + + %Remove the empty value after the final tab. + value_row = value_row(1:end-1); + + if size(value_row,2) ~= num_keys + error(['Number of values on line ' num2str(row_i) ' (' num2str(size(value_row,2)) ') does not match number of keys (' num2str(num_keys) ').']); + end + + for key_i=1:num_keys + values{row_i, key_i} = value_row{key_i}; + end + + value_line = fgetl(file); + row_i = row_i + 1; %#ok + + end + +end \ No newline at end of file diff --git a/matlab/read_extracted_features.m b/matlab/read_extracted_features.m new file mode 100644 index 0000000..9c2e3f7 --- /dev/null +++ b/matlab/read_extracted_features.m @@ -0,0 +1,36 @@ +function read_extracted_features(dir_name) + +fid = fopen([ dir_name '/v1_norm.dat']); + +v1_norm = load([ dir_name '/v1_norm.dat']); + +v2_norm = fopen([ dir_name '/v2_norm.dat']); + +v0_norm = fopen([ dir_name '/v0_norm.dat']); + +dot_v1_v2 = fopen([ dir_name '/dot_v1_v2.dat']); + + + +% +% fid = fopen([ dir_name '/v1_norm.dat']); +% +% [w,v,machine_format] = fopen(fid); +% +% v1_norm = fread(fid, inf, 'float32=>double',machine_format); +% fclose(fid); +% +% +% fid = fopen([ dir_name '/v2_norm.dat']); +% v2_norm = fread(fid, inf, 'float32=>double',machine_format); +% fclose(fid); +% +% fid = fopen([ dir_name '/v0_norm.dat']); +% v0_norm = fread(fid, inf, 'float32=>double',machine_format); +% fclose(fid); +% +% fid = fopen([ dir_name '/dot_v1_v2.dat']); +% dot_v1_v2 = fread(fid, inf, 'float32=>double',machine_format); +% fclose(fid); + +hist(v1_norm) \ No newline at end of file diff --git a/matlab/read_fibres.m b/matlab/read_fibres.m new file mode 100644 index 0000000..2bf5475 --- /dev/null +++ b/matlab/read_fibres.m @@ -0,0 +1,113 @@ +function [elems, properties] = read_fibres(filename, varargin) + +% if nargin == 2 +% num_elems = varargin{1} * 3; +% else +% num_elems = inf; +% end + + file = fopen(filename,'r'); + + [fname, mode, machine_format] = fopen(file); + + + if (file == -1) + error([ 'Could not open file ' filename '!' ]); + end + + + line = fgetl(file); + + if (length(line) < 13 || ~strcmp(line(1:13),'mrtrix tracks')) + error(['File, ' filename ' was not a valid mrtrix tracks file']); + end + + offset = 0; + datatype = []; + + while 1 + line = fgetl(file); + if ~ischar(line), break, end; + line = strtrim(line); + if strcmp(line, 'END'), break, end; + delim = strfind (line,':'); + + if isempty(delim) + disp (['invalid line in header: ''' line ''' - ignored']); + else + + key = lower(strtrim(line(1:delim(1)-1))); + value = strtrim(line(delim(1)+1:end)); + + if strcmp(key, 'datatype') + + if strcmp(value, 'Float32LE') + machine_format = 'ieee-le'; + + elseif strcmp(value, 'Float32BE') + machine_format = 'ieee-be'; + + elseif strcmp(value, 'Float64LE') + machine_format = 'ieee-le.l64'; + + elseif strcmp(value, 'Float64BE') + machine_format = 'ieee-be.l64'; + + else + error(['Unrecognised format ''' value '''.']); + end + + elseif strcmp(key, 'file') + offset = str2double(value(3:end)); + else + key = strrep(key, ' ', '_'); + eval(['properties.' key ' = value;']); + end + + end + end + + if (~offset) + error('"file" property was not found after 100 lines'); + end + + % Read elements + fseek(file, offset, 'bof'); + + if (strcmp(machine_format,'ieee-le') || strcmp(machine_format,'ieee-be')) + elems = fread(file, inf, 'float32=>double', machine_format); + else + elems = fread(file, inf, 'double=>double', machine_format); + end +% elems = elems(1:end-3); + + num_triples = size(elems,1)/3; + + if num_triples ~= round(num_triples) + error (['Number of elements loaded from mrtrix file data was not divisible by 3 (' num2str(size(elems,1)) ')']); + end + + elems = reshape(elems,3,num_triples)'; + + + % Find end of file marker. + is_pos_inf = isinf(elems) .* (elems > 0); + + is_pos_inf_row = is_pos_inf(:,1) .* is_pos_inf(:,2) .* is_pos_inf(:,3); + + end_of_data = find(is_pos_inf_row); + + if size(end_of_data,1) > 2 + error ([ num2str(size(end_of_data,1)) ' end_of_data markers found in file (max allowed 2). (Very) Probably infinity valued parameters have been written to fibres file.']); + + elseif size(end_of_data,1) == 2 + if end_of_data(2) ~= size(elems,1) + error ('Second end_of_data marker found not at end of file, possibly corrupt file'); + end + + end_of_data = end_of_data(1); + end + + elems = elems(1:(end_of_data-1),:); + +end \ No newline at end of file diff --git a/matlab/read_image.m b/matlab/read_image.m new file mode 100644 index 0000000..bffd7d7 --- /dev/null +++ b/matlab/read_image.m @@ -0,0 +1,132 @@ +function image = read_image (filename) + +% function: image = read_mrtrix (filename) +% +% returns a structure containing the header information and data for the MRtrix +% format image 'filename' (i.e. files with the extension '.mif' or '.mih'). + +image.comments = {}; + +f = fopen (filename, 'r'); +if (f<1) + error (['could not open file ' filename ]); +end +L = fgetl(f); +if ~strncmp(L, 'mrtrix image', 12) + fclose(f); + error ([filename ' is not in MRtrix format']); +end + +transform = []; +DW_scheme = []; + +while 1 + L = fgetl(f); + if ~ischar(L), break, end; + L = strtrim(L); + if strcmp(L, 'END'), break, end; + d = strfind (L,':'); + if isempty(d) + disp (['invalid line in header: ''' L ''' - ignored']); + else + key = lower(strtrim(L(1:d(1)-1))); + value = strtrim(L(d(1)+1:end)); + if strcmp(key, 'dim') + image.dim = str2num(char(split_strings (value, ',')))'; + elseif strcmp(key, 'vox') + image.vox = str2num(char(split_strings (value, ',')))'; + elseif strcmp(key, 'dw_scheme') + DW_scheme(end+1,:) = str2num(char(split_strings (value, ',')))'; + elseif strcmp(key, 'transform') + transform(end+1,:) = str2num(char(split_strings (value, ',')))'; + elseif strcmp(key, 'comments') + image.comments{end+1} = value; + elseif strcmp(key, 'labels') + image.labels = split_strings (value, '\'); + elseif strcmp(key, 'units') + image.units = split_strings (value, '\'); + elseif strcmp(key, 'file') + file = value; + + elseif strcmp(key, 'img_dims') %do nothing; + elseif strcmp(key, 'img_vox_lengths') %do nothing; + elseif strcmp(key, 'diff_encodings') %do nothing; + elseif strcmp(key, 'img_offsets') %do nothing; % image.offset = value; + else + key = strrep(key, ' ', '_'); + eval(['image.' key ' = value;']); + end + end +end +fclose(f); + + +if ~isempty(transform) + image.transform = transform; + image.transform(4,:) = [ 0 0 0 1 ]; +end + +if ~isempty(DW_scheme) + image.DW_scheme = DW_scheme; +end + +if ~isfield (image, 'dim') || ~exist ('file') || ... + ~isfield (image, 'layout') || ~isfield (image, 'datatype') + disp ('critical entries missing in header - not reading data') + return +end + +layout = split_strings(image.layout, ','); +order = (abs(str2num (char(layout)))+1)'; + +[ file, offset ] = strtok(file); +if isempty(offset), offset = 0; else offset = str2num(char(offset)); end +[f,g] = fileparts(filename); +if strcmp(file,'.'), file = filename; else file = fullfile (f, file); end + +datatype = lower(image.datatype); +byteorder = datatype(end-1:end); + +if strcmp(byteorder, 'le') + f = fopen (file, 'r', 'l'); + datatype = datatype(1:end-2); +elseif strcmp(byteorder, 'be') + f = fopen (file, 'r', 'b'); + datatype = datatype(1:end-2); +else + if strcmp(datatype, 'bit') + datatype = 'bit1'; + f = fopen(file, 'r', 'b'); + else + f = fopen(file, 'r'); + end +end + +if (f<1) + disp (['error opening ' filename ]); + return +end + +fseek (f, offset, -1); +image.data = fread (f, inf, datatype); +fclose (f); + +order(order)= 1:size(order,2); +image.data = reshape (image.data, image.dim(order)); +image.data = ipermute (image.data, order); +for i=1:size(order,2) + if layout{i}(1) == '-' + image.data = flipdim(image.data, i); + end +end + + + + +function S = split_strings (V, delim) + S = {}; + while size(V,2) > 0 + [R, V] = strtok(V,delim); + S{end+1} = R; + end + diff --git a/matlab/read_properties.m b/matlab/read_properties.m new file mode 100644 index 0000000..5f53df8 --- /dev/null +++ b/matlab/read_properties.m @@ -0,0 +1,36 @@ +function props = read_properties (filename) +% function props = read_properties (filename) +% Reads properties from a file and returns them in a struct. + +f = fopen (filename, 'r'); +if (f<1) + disp (['could not open file ' filename ]); + return +end + +while 1 + L = fgetl(f); + if ~ischar(L), break, end; + L = strtrim(L); + if strcmp(L, 'END'), break, end; + d = strfind (L,':'); + if isempty(d) + disp (['invalid line in header: ''' L ''' - ignored']); + else + key = strrep(lower(strtrim(L(1:d(1)-1))), ' ', '_'); + value = strtrim(L(d(1)+1:end)); + eval(['props.' key ' = value;']); + end +end +fclose(f); + + + + +function S = split_strings (V, delim) + S = {}; + while size(V,2) > 0 + [R, V] = strtok(V,delim); + S{end+1} = R; + end + diff --git a/matlab/read_set_element_properties.m b/matlab/read_set_element_properties.m new file mode 100644 index 0000000..2bfc336 --- /dev/null +++ b/matlab/read_set_element_properties.m @@ -0,0 +1,63 @@ +function [keys, values] = read_set_element_properties(location) + + file = fopen(location, 'r'); + + if (file == -1) + + keys = cell(0); + values = cell(0); + return; +% error([ 'Could not open file ' location '!' ]); + end + + + header_line = fgetl(file); + + %Seperate the header tag from the key list. + [header, key_string] = strtok(header_line,':'); + + if ~strcmp(header, '%%% Extended Properties File %%% - keys') + error(['Extended properties header tag ''%%% Extended Properties File %%% - keys'' was not found at start of extended properties file ''' location '']); + end + + %String ': ' from start of keys and trailing tabs from end. + keys = parse_properties_row(key_string(3:end)); + + num_keys = length(keys); + + row_i = 1; + + value_line = fgetl(file); + + while value_line ~= -1; + + sub_row_i = 1; + + while length(value_line) < 8 || ~strcmp(value_line(1:8), '--- END ') || ~strcmp(value_line((end-3):end), ' ---') + + value_row = parse_properties_row(value_line); + + if size(value_row,2) ~= num_keys + error(['Number of values on line ' num2str(row_i) ' (' num2str(size(value_row,2)) ') does not match number of keys (' num2str(num_keys) ').']); + end + + values{row_i,1}(sub_row_i,:) = value_row; + + + value_line = fgetl(file); + sub_row_i = sub_row_i + 1; %#ok + + if value_line == -1 + error (['Found end of file before row delimeter for row (in row ' num2str(row_i) ').']); + end + + end + + row_i = row_i + 1; %#ok + value_line = fgetl(file); + + end + + + +end \ No newline at end of file diff --git a/matlab/save_evo_for_talk.m b/matlab/save_evo_for_talk.m new file mode 100644 index 0000000..bded81f --- /dev/null +++ b/matlab/save_evo_for_talk.m @@ -0,0 +1,42 @@ +function save_evo_for_report(output_path, varargin) + +% set_transparent = 0; + resolution = 600; + + if (nargin == 2) + resolution = varargin{2}; + end + + +%set(gcf, 'color', [1 1 1]); + +%note A4 is 21cm wide 29.7cm tall + +% xlim([-2 2]); +% ylim([-2 2]); +% zlim([-2 2]); + +%set(gcf,'Units','centimeters'); +set(gcf,'PaperUnits','centimeters'); + +% set(gcf, 'Position', [10 10 10 10]); +set(gcf, 'PaperSize', [3 3]); +set(gcf, 'PaperPosition', [0 0 3 3]); + +%set(gca, 'visible', 'off'); +set(gca, 'Outerposition', [0 0 1 1]); +set(gca, 'Position', [0 0 1 1]); + +background = [0 0 0]; + +set(gcf, 'color', background); + +set(gcf,'InvertHardCopy','off'); + +print(gcf, '-dpng', ['-r' num2str(resolution)], [output_path]); + +cdata = imread([output_path '.png']); +%cdata = imcrop(cdata, [10 10 300 300]); + +% write it back out - setting transparency info +imwrite(cdata, [output_path '.png'], 'png', 'BitDepth', 16, 'transparency', background) \ No newline at end of file diff --git a/matlab/save_figure_for_talk.m b/matlab/save_figure_for_talk.m new file mode 100644 index 0000000..d473a48 --- /dev/null +++ b/matlab/save_figure_for_talk.m @@ -0,0 +1,43 @@ +function save_figure_for_talk(output_path, resolution) + +% set_transparent = 0; + + if ~exist('resolution','var') + resolution = 600; + end + + + %set(gcf, 'color', [1 1 1]); + + %note A4 is 21cm wide 29.7cm tall + + % xlim([-2 2]); + % ylim([-2 2]); + % zlim([-2 2]); + + %set(gcf,'Units','centimeters'); + set(gcf,'PaperUnits','centimeters'); + + % set(gcf, 'Position', [10 10 10 10]); + set(gcf, 'PaperSize', [3 3]); + set(gcf, 'PaperPosition', [0 0 3 3]); + + %set(gca, 'visible', 'off'); + set(gca, 'Outerposition', [0 0 1 1]); + set(gca, 'Position', [0 0 1 1]); + + background = [0 0 0]; + + set(gcf, 'color', background); + + set(gcf,'InvertHardCopy','off'); + + print(gcf, '-dpng', ['-r' num2str(resolution)], [output_path]); + + cdata = imread([output_path '.png']); + %cdata = imcrop(cdata, [10 10 300 300]); + + % write it back out - setting transparency info + imwrite(cdata, [output_path '.png'], 'png', 'BitDepth', 16, 'transparency', background) + +end \ No newline at end of file diff --git a/matlab/save_samples_for_report.m b/matlab/save_samples_for_report.m new file mode 100644 index 0000000..c2b5387 --- /dev/null +++ b/matlab/save_samples_for_report.m @@ -0,0 +1,45 @@ +function save_render_for_report(output_path, varargin) + +% set_transparent = 0; + resolution = 600; + + if (nargin == 2) + resolution = varargin{2}; + end + + +%set(gcf, 'color', [1 1 1]); + +%note A4 is 21cm wide 29.7cm tall + +xlim([-.53 .53]); +ylim([-.53 .53]); +zlim([-.53 .53]); + +campos([0 0 1]); +camup([0 1 0]); + +%set(gcf,'Units','centimeters'); +set(gcf,'PaperUnits','centimeters'); + +% set(gcf, 'Position', [10 10 10 10]); +set(gcf, 'PaperSize', [3 3]); +set(gcf, 'PaperPosition', [0 0 3 3]); + +%set(gca, 'visible', 'off'); +set(gca, 'Outerposition', [0 0 1 1]); +set(gca, 'Position', [0 0 1 1]); + +background = [0 0 0]; + +set(gcf, 'color', background); + +set(gcf,'InvertHardCopy','off'); + +% print(gcf, '-dpng', ['-r' num2str(resolution)], [output_path]); + +%cdata = imread([output_path '.png']); +%cdata = imcrop(cdata, [10 10 300 300]); + +% write it back out - setting transparency info +%imwrite(cdata, [output_path '.png'], 'png', 'BitDepth', 16, 'transparency', background) \ No newline at end of file diff --git a/matlab/save_samples_for_talk.m b/matlab/save_samples_for_talk.m new file mode 100644 index 0000000..084eb9f --- /dev/null +++ b/matlab/save_samples_for_talk.m @@ -0,0 +1,67 @@ +function save_samples_for_talk(output_path, camera_viewangle, paper_size, resolution, camera_target, camera_pos) + +% set_transparent = 0; + + if ~exist('resolution','var') + resolution = 600; + end + + if ~exist('paper_size','var') + paper_size = 15; + end + + if ~exist('camera_pos','var') + camera_pos = [-3.25 -3.25 3.25]; + end + + if ~exist('camera_viewangle','var') + camera_viewangle = 7.5; + end + + if ~exist('camera_target','var') + camera_target = [0,0,0]; + end + + set(gca,'CameraPositionMode', 'manual'); + set(gca,'CameraTargetMode', 'manual'); + set(gca,'CameraViewAngleMode', 'manual'); + + set(gca, 'CameraPosition', camera_pos); + set(gca, 'CameraTarget', camera_target); + set(gca, 'CameraViewAngle', camera_viewangle); + + + %set(gcf, 'color', [1 1 1]); + + %note A4 is 21cm wide 29.7cm tall + + % xlim([-2 2]); + % ylim([-2 2]); + % zlim([-2 2]); + + %set(gcf,'Units','centimeters'); + set(gcf,'PaperUnits','centimeters'); + + % set(gcf, 'Position', [10 10 10 10]); + set(gcf, 'PaperSize', [paper_size paper_size]); + set(gcf, 'PaperPosition', [0 0 paper_size paper_size]); + + set(gca, 'visible', 'off'); + set(gca, 'Outerposition', [0 0 1 1]); + set(gca, 'Position', [0 0 1 1]); + + background = [0 0 0]; + + set(gcf, 'color', background); + + set(gcf,'InvertHardCopy','off'); + + print(gcf, '-dpng', ['-r' num2str(resolution)], [output_path]); + + cdata = imread([output_path '.png']); + %cdata = imcrop(cdata, [10 10 300 300]); + + % write it back out - setting transparency info + imwrite(cdata, [output_path '.png'], 'png', 'BitDepth', 16, 'transparency', background) + +end \ No newline at end of file diff --git a/matlab/set_bundle_colours.m b/matlab/set_bundle_colours.m new file mode 100644 index 0000000..3392769 --- /dev/null +++ b/matlab/set_bundle_colours.m @@ -0,0 +1,14 @@ +function set_bundle_colours(max_bundle_index) + + global colours_of_bundles; + + num_colours = max_bundle_index+1; + + if size(colours_of_bundles,1) < num_colours + + colours_of_bundles = rand([num_colours, 3]); +% add_colour_key(colours_of_bundles, 0:1:num_colours-1); + + end + +end \ No newline at end of file diff --git a/matlab/split_at_file_seperator.m b/matlab/split_at_file_seperator.m new file mode 100644 index 0000000..2a52457 --- /dev/null +++ b/matlab/split_at_file_seperator.m @@ -0,0 +1,44 @@ +function fibre_objects = split_at_file_seperator(elems, file_seperator, varargin) + + + if (size(elems, 2) ~= 3) + error (['Dimension 2 of elements must be 3 (' num2str(size(elems,2)) ')']); + end + + if (length(file_seperator) ~= 3) + error (['Length of file seperator must be 3 (' length(file_seperator) ')']); + end + + seperators = ones(size(elems,1),1); + + for i=1:length(file_seperator) + + if isnan(file_seperator(i)) + sep_column = isnan(elems(:,i)); + elseif isinf(file_seperator(i)) && (file_seperator(i) > 0) + sep_column = isinf(elems(:,i)) .* (elems(:,i) > 0); + elseif isinf(file_seperator(i)) && (file_seperator(i) < 0) + sep_column = isinf(elems(:,i)) .* (elems(:,i) < 0); + else + error(['Invalid file seperator, ''' num2str(file_seperator(i)) ''', must be nan, inf or -inf']); + end + + seperators = seperators .* sep_column; + + end + + seperator_indices = [0; find(seperators)]; + + num_fibres = size(seperator_indices,1)-1; + + fibre_objects = cell(num_fibres,1); + + for fibre_i = 1:num_fibres + + fibre_objects{fibre_i} = elems((seperator_indices(fibre_i)+1):(seperator_indices(fibre_i+1)-1),:); + + end + + + +end \ No newline at end of file diff --git a/matlab/strands2tcks.m b/matlab/strands2tcks.m new file mode 100644 index 0000000..e2ba199 --- /dev/null +++ b/matlab/strands2tcks.m @@ -0,0 +1,13 @@ +function tcks = strands2tcks(strands, num_length_sections) + + if ~exist('num_length_sections','var') + num_length_sections = 100; + end + + tcks = cell(size(strands)); + + for strand_i = 1:length(strands) + tcks{strand_i} = fourier2tck(strands{strand_i},num_length_sections); + end + +end \ No newline at end of file diff --git a/matlab/test_gaussian_log_prob.m b/matlab/test_gaussian_log_prob.m new file mode 100644 index 0000000..b72eb20 --- /dev/null +++ b/matlab/test_gaussian_log_prob.m @@ -0,0 +1,13 @@ +function log_probs = test_gaussian_log_prob(points, relative_scale) + + num_points = size(points,1); + + log_probs = zeros(num_points,1); + + for point_i = 1:num_points + + log_probs(point_i) = points(point_i,1).^2 + relative_scale * points(point_i,2).^2; + + end + +end \ No newline at end of file diff --git a/matlab/test_odr.m b/matlab/test_odr.m new file mode 100644 index 0000000..aeae1dd --- /dev/null +++ b/matlab/test_odr.m @@ -0,0 +1,24 @@ +points = [0.0558338, -0.0151347, 0.0378316; 0.0825788, 0.00693855, -0.077859; 0.228064, -0.331608, -0.149636; 0.256504, -0.356444, -0.340913; 0.330395, -0.383082, -0.342205; 0.543772, -0.510789, -0.485669; 0.59165, -0.547569, -0.568391; 0.717377, -0.76264, -0.70171; 0.801649, -0.832203, -0.839953; 0.94715, -0.886547, -0.925994; ] +V = [0.567898 -0.368983 0.735761 ; -0.568563 -0.822213 0.0265069 ; -0.595171 0.433379 0.676723 ; ] +centre = [ 0.455497, -0.461908, -0.43945 ] +direction = [ 0.567898, -0.568563, -0.595171 ] + + +figure; + +hold on; + +plot3(points(:,1), points(:,2), points(:,3), 'Marker', 'x', 'LineStyle', 'none'); + +line_points = [centre - direction/2; centre; centre + direction/2]; + +plot3(line_points(:,1), line_points(:,2), line_points(:,3)) + +plot3( [0 0 0; V(1,:)], [0 0 0; V(2,:)], [0 0 0; V(3,:)], 'Color', 'red'); + +daspect([1 1 1]); + +hold off; + +cameratoolbar('Show'); +cameratoolbar('SetMode','orbit'); \ No newline at end of file diff --git a/matlab/test_peak_log_prob.m b/matlab/test_peak_log_prob.m new file mode 100644 index 0000000..e6e044b --- /dev/null +++ b/matlab/test_peak_log_prob.m @@ -0,0 +1,44 @@ +function log_probs = test_peak_log_prob(points, peaks, roi_radius, barrier_rate) + + num_peaks = size(peaks,1); + num_points = size(points,1); + + log_probs = zeros(num_points,1); + + for peak_i = 1:num_peaks + + peak_centre = peaks(peak_i, 1:2); + peak_width = peaks(peak_i, 3:4); + peak_height = peaks(peak_i, 5); + peak_type = peaks(peak_i, 6); + + if peak_type == 0 % Gaussian + + peak_variance = (peak_width / 3.0).^2; + + peak_log_probs = peak_height * exp (- ((peak_centre(1) - points(:,1)).^2) ./ peak_variance(1)) .* exp (- ((peak_centre(2) - points(:,2)).^2) ./ peak_variance(2)); + + elseif peak_type == 1 % Pyramid + + peak_steepness(1) = peak_height / peak_width(1); + peak_steepness(2) = peak_height / peak_width(2); + + peak_log_probs = peak_height - abs(peak_centre(1) - points(:,1)) .* peak_steepness(1) - abs(peak_centre(2) - points(:,2)) .* peak_steepness(2); + + peak_log_probs(find(peak_log_probs < 0)) = 0; + + else + error(['Unrecognised peak type, ' num2str(peak_type) '.']); + end + + points_norm = sqrt(points(:,1).^2 + points(:,2).^2); + + outside_roi = find(points_norm > roi_radius); + + peak_log_probs(outside_roi) = peak_log_probs(outside_roi) - ((points_norm(outside_roi) - roi_radius) * barrier_rate).^2; + + log_probs = log_probs + peak_log_probs; + + end + +end \ No newline at end of file diff --git a/matlab/tracts2strands.m b/matlab/tracts2strands.m new file mode 100644 index 0000000..cd3fd37 --- /dev/null +++ b/matlab/tracts2strands.m @@ -0,0 +1,80 @@ +function [strands, bundle_indices] = tracts2strands(tracts, base_widths, num_strands, highlight_axes, oblong, tract_indices) + + if ~exist('highlight_axes','var') + highlight_axes = 0; + end + + if ~exist('oblong','var') + oblong = 0; + end + + if ~exist('tract_indices','var') + tract_indices = []; + end + + if isempty(tract_indices) + tract_indices = [0:1:size(tracts,1)-1]; + end + + num_tracts = size(tracts,1); + + strands = cell(num_tracts,1); + bundle_indices = zeros(num_tracts,1); + + strand_count = 0; + tcks = cell(num_tracts * (2 * num_strands + 1),4); + + + width_fraction = 1 / num_strands; + + if num_strands < 0 + error(['''-num_strands'' must be greater than zero (' num2str(num_strands) ').']); + end + + ax_fractions = (-1+width_fraction):(2*width_fraction):(1-width_fraction); + + for tract_i = 1:num_tracts + + base_index = tract_indices(tract_i); + + if highlight_axes + base_index = base_index * 4; + end + + for ax2_frac = ax_fractions + + for ax3_frac = ax_fractions + + + if (sqrt(ax2_frac^2 + ax3_frac^2) <= 1.0) || oblong + strand_count = strand_count + 1; + + strands{strand_count} = tracts{tract_i, 1} + (tracts{tract_i, 2} * ax2_frac + tracts{tract_i, 3} * ax3_frac) * base_widths(tract_i); + + + if highlight_axes + + if ax2_frac == 0 && ax3_frac == 0 + strand_index = base_index + 1; + elseif ax2_frac == 0 + strand_index = base_index + 2; + elseif ax3_frac == 0 + strand_index = base_index + 3; + else + strand_index = base_index; + end + + else + strand_index = base_index; + end + + bundle_indices(strand_count) = strand_index; + + end + end + end + + end + + +end \ No newline at end of file diff --git a/matlab/unzip_image.m b/matlab/unzip_image.m new file mode 100644 index 0000000..239c353 --- /dev/null +++ b/matlab/unzip_image.m @@ -0,0 +1,5 @@ +function [section_matrix, labels] = unzip_image(image) + + + +end \ No newline at end of file diff --git a/matlab/unzip_strand_sections.m b/matlab/unzip_strand_sections.m new file mode 100644 index 0000000..43f4f6b --- /dev/null +++ b/matlab/unzip_strand_sections.m @@ -0,0 +1,31 @@ +function [section_matrix, labels] = unzip_strand_sections(sections, prop_keys, prop_values) + + num_sections = size(sections,1); + + if num_sections == 0 + error ('No sections loaded.'); + end + + num_props = length(prop_keys); + num_parameters = 6 + num_props; + + section_matrix = zeros(num_parameters, num_sections); + labels = cell(num_parameters,1); + + for prop_i = 1:num_props + section_matrix(prop_i,:) = get_properties(prop_keys, prop_values, prop_keys{prop_i}); + labels{prop_i} = prop_keys{prop_i}; + end + + for section_i = 1:num_sections + section_matrix((num_props+1):end, section_i) = sections{section_i}(:); + end + + labels{num_props+1} = 'Position - Dim 0'; + labels{num_props+2} = 'Position - Dim 1'; + labels{num_props+3} = 'Position - Dim 2'; + labels{num_props+4} = 'Tangent - Dim 0'; + labels{num_props+5} = 'Tangent - Dim 1'; + labels{num_props+6} = 'Tangent - Dim 2'; + +end \ No newline at end of file diff --git a/matlab/unzip_strand_sets.m b/matlab/unzip_strand_sets.m new file mode 100644 index 0000000..a0fbe97 --- /dev/null +++ b/matlab/unzip_strand_sets.m @@ -0,0 +1,71 @@ +function [strand_sets_matrix, labels] = unzip_strand_sets(sets, set_prop_keys, set_prop_values, elem_prop_keys, elem_prop_values) + + num_sets = size(sets,1); + + if num_sets == 0 + error ('No sets loaded.'); + end + + num_strands = size(sets{1},1); + first_set = sets(1); + degree = size(first_set{1}{1},1); + + for set_i = 1:num_sets + + set = sets{set_i}; + + if size(sets{set_i},1) ~= num_strands + error(['Number of strands in set ' num2str(set_i) ' (' num2str(size(sets{set_i},1)) ') does match that of previous sets (' num2str(num_strands) ').']); + end + + for strand_i = 1:num_strands + if size(sets{set_i}{strand_i},1) ~= degree + error(['Degree of strand ' num2str(strand_i) ' in set ' num2str(set_i) ' (' num2str(size(sets{set_i}{strand_i},1)) ') does match that of previous strands (' num2str(degree) ').']); + end + end + + end + + + num_set_props = length(set_prop_keys); + num_elem_props = length(elem_prop_keys); + + num_parameters = num_strands * degree * 3 + num_set_props + num_elem_props * num_strands; + + + strand_sets_matrix = zeros(num_parameters, num_sets); + labels = cell(num_parameters,1); + + for prop_i = 1:num_set_props + strand_sets_matrix(prop_i,:) = get_properties(set_prop_keys, set_prop_values, set_prop_keys{prop_i}); + labels{prop_i} = set_prop_keys{prop_i}; + end + + + for strand_i = 1:num_strands + + same_strand_across_sets = cell(num_sets); + same_strand_props_across_sets = cell(num_sets, num_elem_props); + + for set_i = 1:num_sets + + set = sets{set_i}; + + same_strand_across_sets(set_i) = set(strand_i); + + if num_elem_props + same_strand_props_across_sets(set_i) = elem_prop_values{set_i}(strand_i,:); + end + end + + [strand_matrix, strand_labels] = unzip_strands(same_strand_across_sets, elem_prop_keys, same_strand_props_across_sets, ['Strand ' num2str(strand_i-1) ' - ']); + + start = (strand_i-1) * (degree * 3 + num_elem_props) + num_set_props + 1; + finish = strand_i * (degree * 3 + num_elem_props) + num_set_props; + + strand_sets_matrix(start:finish,:) = strand_matrix; + labels(start:finish) = strand_labels; + + end + +end \ No newline at end of file diff --git a/matlab/unzip_strands.m b/matlab/unzip_strands.m new file mode 100644 index 0000000..f00b70a --- /dev/null +++ b/matlab/unzip_strands.m @@ -0,0 +1,49 @@ +function [strand_matrix, labels] = unzip_strands(strands, prop_keys, prop_values, label_prefix) + + if ~exist('label_prefix', 'var') + label_prefix = ''; + end + + num_strands = size(strands,1); + + if num_strands == 0 + error ('No strands loaded.'); + end + + degree = size(strands{1},1); + + for strand_i = 1:num_strands + if size(strands{strand_i},1) ~= degree + error(['Degree of strand_matrix strand ' num2str(strand_i) ' (' num2str(size(strands{strand_i},1)) ') does match that of previous strands (' num2str(degree) ').']); + end + end + + num_props = length(prop_keys); + num_parameters = degree * 3 + num_props; + + strand_matrix = zeros(num_parameters, num_strands); + labels = cell(num_parameters,1); + + for prop_i = 1:num_props + strand_matrix(prop_i,:) = get_properties(prop_keys, prop_values, prop_keys{prop_i}); + labels{prop_i} = [label_prefix prop_keys{prop_i}]; + end + + for strand_i = 1:num_strands + + start = num_props + 1; +% finish = num_props + degree * 3; + + transposed_strand = strands{strand_i}'; + strand_matrix(start:end,strand_i) = transposed_strand(:); + + end + + for degree_i = 1:degree + for dim_i = 1:3 + param_i = (degree_i-1) * 3 + dim_i + num_props; + labels{param_i} = [label_prefix 'Degree ' num2str(degree_i-1) ' - Dim ' num2str(dim_i-1) ]; + end + end + +end \ No newline at end of file diff --git a/matlab/unzip_tensor.m b/matlab/unzip_tensor.m new file mode 100644 index 0000000..7e07b0d --- /dev/null +++ b/matlab/unzip_tensor.m @@ -0,0 +1,34 @@ +function [tensor_matrix, labels] = unzip_tensor(tensor_array, row_labels) + + num_rows = size(tensor_array,1); + + if num_rows ~= size(tensor_array,2) + error(['Number columns (' num2str(size(tensor_array,2)) ') does not match number of rows (' num2str(num_rows) ').']); + end + + if num_rows ~= length(row_labels) + error(['Length of column labels (' num2str(length(row_labels)) ') does not match number of rows (' num2str(num_rows) ').']); + end + + labels = cell(num_rows^2,1); + + for row_i = 1:num_rows + for col_i = 1:num_rows + + row_label = strrep(row_labels(row_i), '_', ' '); + col_label = strrep(row_labels(col_i), '_', ' '); + + row_label = row_label{1}; + col_label = col_label{1}; + + row_label = row_label(1:(end-1)); + col_label = col_label(1:(end-1)); + + labels{(row_i-1)*num_rows + col_i} = [row_label ' :: ' col_label]; + end + end + + tensor_matrix = reshape(tensor_array, num_rows^2, size(tensor_array,3)); + + +end \ No newline at end of file diff --git a/matlab/unzip_tract_sections.m b/matlab/unzip_tract_sections.m new file mode 100644 index 0000000..5c13222 --- /dev/null +++ b/matlab/unzip_tract_sections.m @@ -0,0 +1,36 @@ +function [section_matrix, labels] = unzip_tract_sections(sections, prop_keys, prop_values) + + num_sections = size(sections,1); + + if num_sections == 0 + error ('No sections loaded.'); + end + + num_props = length(prop_keys); + num_parameters = 12 + num_props; + + section_matrix = zeros(num_parameters, num_sections); + labels = cell(num_parameters,1); + + for prop_i = 1:num_props + section_matrix(prop_i,:) = get_properties(prop_keys, prop_values, prop_keys{prop_i}); + labels{prop_i} = prop_keys{prop_i}; + end + + for section_i = 1:num_sections + section_matrix((num_props+1):end, section_i) = sections{section_i}(:); + end + + labels{num_props+1} = 'Position - Dim 0'; + labels{num_props+2} = 'Position - Dim 1'; + labels{num_props+3} = 'Position - Dim 2'; + labels{num_props+4} = 'Tangent - Dim 0'; + labels{num_props+5} = 'Tangent - Dim 1'; + labels{num_props+6} = 'Tangent - Dim 2'; + labels{num_props+7} = 'Width 1 - Dim 0'; + labels{num_props+8} = 'Width 1 - Dim 1'; + labels{num_props+9} = 'Width 1 - Dim 2'; + labels{num_props+10} = 'Width 2 - Dim 0'; + labels{num_props+11} = 'Width 2 - Dim 1'; + labels{num_props+12} = 'Width 2 - Dim 2'; +end \ No newline at end of file diff --git a/matlab/unzip_tract_sets.m b/matlab/unzip_tract_sets.m new file mode 100644 index 0000000..7cb0e58 --- /dev/null +++ b/matlab/unzip_tract_sets.m @@ -0,0 +1,72 @@ +function [tract_sets_matrix, labels] = unzip_tract_sets(sets, set_prop_keys, set_prop_values, elem_prop_keys, elem_prop_values) + + num_sets = size(sets,1); + + if num_sets == 0 + error ('No sets loaded.'); + end + + num_tracts = size(sets{1},1); + first_set = sets(1); + degree = size(first_set{1}{1},1); + + for set_i = 1:num_sets + + set = sets{set_i}; + new_num_tracts = size(set,1); + + if new_num_tracts ~= num_tracts + error(['Number of tracts in set ' num2str(set_i) ' (' num2str(new_num_tracts) ') does match that of previous sets (' num2str(num_tracts) ').']); + end + + for tract_i = 1:num_tracts + + new_degree = size(set{tract_i,1},1); + + if new_degree ~= degree + error(['Degree of tract ' num2str(tract_i) ' in set ' num2str(set_i) ' (' num2str(new_degree) ') does match that of previous tracts (' num2str(degree) ').']); + end + end + + end + + + num_set_props = length(set_prop_keys); + num_elem_props = length(elem_prop_keys); + + num_parameters = num_tracts * degree * 3 + num_set_props + num_elem_props * num_tracts; + + + tract_sets_matrix = zeros(num_parameters, num_sets); + labels = cell(num_parameters,1); + + for prop_i = 1:num_set_props + tract_sets_matrix(prop_i,:) = get_properties(set_prop_keys, set_prop_values, set_prop_keys{prop_i}); + labels{prop_i} = set_prop_keys{prop_i}; + end + + + for tract_i = 1:num_tracts + + same_tract_across_sets = cell(num_sets,3); + same_tract_props_across_sets = cell(num_sets, num_elem_props); + + for set_i = 1:num_sets + + set = sets{set_i}; + + same_tract_across_sets(set_i,:) = set(tract_i,:); + same_tract_props_across_sets(set_i,:) = elem_prop_values{set_i}(tract_i,:); + end + + [tract_matrix, tract_labels] = unzip_tracts(same_tract_across_sets, elem_prop_keys, same_tract_props_across_sets, ['Tract ' num2str(tract_i-1) ' - ']); + + start = (tract_i-1) * (degree * 9 + num_elem_props) + num_set_props + 1; + finish = tract_i * (degree * 9 + num_elem_props) + num_set_props; + + tract_sets_matrix(start:finish,:) = tract_matrix; + labels(start:finish) = tract_labels; + + end + +end \ No newline at end of file diff --git a/matlab/unzip_tracts.m b/matlab/unzip_tracts.m new file mode 100644 index 0000000..f0e6e9c --- /dev/null +++ b/matlab/unzip_tracts.m @@ -0,0 +1,53 @@ +function [tract_matrix, labels] = unzip_tracts(tracts, prop_keys, prop_values, label_prefix) + + if ~exist('label_prefix', 'var') + label_prefix = ''; + end + + num_tracts = size(tracts,1); + + if num_tracts == 0 + error ('No tracts loaded.'); + end + + degree = size(tracts{1,1},1); + + for tract_i = 1:num_tracts + for ax_i = 1:3 + if size(tracts{tract_i,ax_i},1) ~= degree + error(['Degree of tract_matrix tract ' num2str(tract_i) ' (' num2str(size(tracts{tract_i,ax_i},1)) ') does match that of previous tracts (' num2str(degree) ').']); + end + end + end + + num_props = length(prop_keys); + num_parameters = degree * 3 * 3 + num_props; + + tract_matrix = zeros(num_parameters, num_tracts); + labels = cell(num_parameters,1); + + for prop_i = 1:num_props + tract_matrix(prop_i,:) = get_properties(prop_keys, prop_values, prop_keys{prop_i}); + labels{prop_i} = [label_prefix prop_keys{prop_i}]; + end + + for tract_i = 1:num_tracts + for ax_i = 1:3 + start = num_props + (ax_i-1) * degree * 3 + 1; + finish = num_props + (ax_i) * degree * 3; + transposed_tract = tracts{tract_i,ax_i}'; + tract_matrix(start:finish,tract_i) = transposed_tract(:); + end + end + + for ax_i = 0:1:2 + for degree_i = 0:1:(degree-1) + for dim_i = 0:1:2 + param_i = ax_i*degree*3 + degree_i * 3 + dim_i + (num_props+1); + labels{param_i} = [label_prefix 'Axis ' num2str(ax_i) ' - Degree ' num2str(degree_i) ' - Dim ' num2str(dim_i) ]; + end + end + end + + +end \ No newline at end of file diff --git a/matlab/unzip_triples.m b/matlab/unzip_triples.m new file mode 100644 index 0000000..e69de29 diff --git a/profiles/callgrind.out.16487 b/profiles/callgrind.out.16487 new file mode 100755 index 0000000..f32e1a4 --- /dev/null +++ b/profiles/callgrind.out.16487 @@ -0,0 +1,33910 @@ +version: 1 +creator: callgrind-3.6.0.SVN-Debian +pid: 16487 +cmd: dummy +part: 1 + + +desc: I1 cache: +desc: D1 cache: +desc: L2 cache: + +desc: Timerange: Basic block 0 - 208919124522 +desc: Trigger: Program termination + +positions: line +events: Ir +summary: 1323501268167 + + +ob=(1) /lib/ld-2.11.1.so +fl=(11) /build/buildd/eglibc-2.11.1/elf/dl-environ.c +fn=(26) _dl_next_ld_env_entry +31 3 ++3 11 ++2 90 ++11 43 +-13 130 ++17 1 +-14 20 ++5 2 +-3 2 ++3 2 ++2 2 + +fl=(38) /build/buildd/eglibc-2.11.1/elf/dl-init.c +fn=(174) _dl_init +93 11 ++5 1 +-4 1 ++1 1 ++3 2 ++7 2 ++27 2 ++1 24 ++1 11 +-1 11 ++1 22 +-97 33 ++9 10 +-3 20 ++3 30 ++5 27 ++5 16 ++8 16 ++6 48 +cob=(2) ??? +cfi=(13) ??? +cfn=(460) 0x0000000004e4e288 +calls=1 -70 +* 189547 +cob=(2) +cfi=(13) +cfn=(440) 0x0000000004c26f38 +calls=1 -70 +* 29 +cob=(2) +cfi=(13) +cfn=(420) 0x00000000051210f8 +calls=1 -70 +* 29 +cob=(2) +cfi=(13) +cfn=(400) 0x00000000054e0450 +calls=1 -70 +* 29 +cob=(2) +cfi=(13) +cfn=(264) 0x000000000576fec8 +calls=1 -70 +* 2214 +cob=(2) +cfi=(13) +cfn=(244) 0x0000000005a2fe00 +calls=1 -70 +* 29 +cob=(2) +cfi=(13) +cfn=(224) 0x0000000005cb1a98 +calls=1 -70 +* 29 +cob=(4) /lib/libc-2.11.1.so +cfi=(40) /build/buildd/eglibc-2.11.1/csu/../sysdeps/unix/sysv/linux/x86_64/../init-first.c +cfn=(196) _init +calls=1 -18 +* 6489 ++4 8 ++1 16 ++65 8 +-88 2 +-6 4 +-9 4 ++9 1 +-3 2 ++3 3 ++5 3 ++5 2 ++8 2 ++6 7 +cob=(2) +cfi=(13) +cfn=(176) 0x0000000004a234c8 +calls=1 -70 +* 29 +* 1 ++4 1 ++1 2 ++26 2 + +fl=(7) /build/buildd/eglibc-2.11.1/elf/../elf/dl-sysdep.c +fn=(166) _dl_sysdep_start_cleanup +251 1 + +fn=(54) _dl_important_hwcaps +353 6 ++3 1 +-3 2 ++3 1 +-1 1 ++1 1 ++9 1 +-12 4 ++12 1 ++10 3 ++44 4 +cfi=(20) /build/buildd/eglibc-2.11.1/io/../sysdeps/unix/syscall-template.S +cfn=(56) access +calls=1 82 +* 11 +* 3 +-2 1 ++17 1 +-17 1 ++17 5 ++3 2 ++22 2 ++8 2 ++2 1 ++1 1 +-1 2 ++1 4 ++8 1 +-4 2 ++1 1 +-1 1 ++4 1 ++3 2 ++4 6 ++1 2 ++18 10 ++1 3 +cfi=(14) /build/buildd/eglibc-2.11.1/elf/dl-minimal.c +cfn=(36) malloc +calls=1 96 +* 28 ++1 1 +-1 2 ++1 1 ++7 2 ++22 3 ++3 1 +-3 3 ++3 1 ++28 2 +-7 1 ++7 4 ++1 1 +-1 1 ++1 1 +-1 1 ++1 1 +-1 1 ++1 3 +-1 3 ++1 3 +-1 3 ++1 3 +-1 5 ++5 2 +-5 3 ++5 3 ++3 1 +-3 1 ++3 1 +-3 3 ++3 1 +-3 1 ++3 7 ++2 16 +-2 4 ++1 12 +-1 2 ++1 12 +-1 10 ++4 4 ++3 1 ++2 2 +-1 1 +-1 2 ++2 3 ++13 13 ++3 3 +-3 3 ++3 3 ++3 4 ++3 8 +379 3 ++63 4 ++98 5 +cfi=(15) /build/buildd/eglibc-2.11.1/string/../sysdeps/x86_64/memcpy.S +cfn=(58) mempcpy +calls=1 56 +* 22 +* 1 ++1 1 +-1 1 ++1 2 +cfi=(15) +cfn=(58) +calls=1 56 +* 22 +* 3 + +fn=(12) _dl_sysdep_start +88 8 ++25 1 +-1 1 ++1 143 ++3 1 +-3 1 ++6 2 +-2 1 +-1 1 ++3 1 +-6 1 ++6 4 ++1 1 +-1 7 ++1 105 ++3 2 +-4 49 +fi=(17) /build/buildd/eglibc-2.11.1/elf/../sysdeps/unix/sysv/linux/dl-sysdep.c +-83 2 +cfi=(8) /build/buildd/eglibc-2.11.1/elf/../sysdeps/unix/sysv/linux/x86_64/brk.c +cfn=(14) brk +calls=1 -7 +* 11 +fi=(5) /build/buildd/eglibc-2.11.1/elf/../sysdeps/x86_64/dl-machine.h +226 5 +fe=(7) ++2 2 +cfi=(10) /build/buildd/eglibc-2.11.1/elf/../misc/sbrk.c +cfn=(20) sbrk +calls=1 35 +* 17 +* 3 ++12 3 ++3 4 +cfi=(2) /build/buildd/eglibc-2.11.1/elf/rtld.c +cfn=(22) dl_main +calls=1 886 +* 2122610 ++2 9 +-67 1 +-59 4 ++34 1 +-34 4 ++43 1 +-43 4 ++40 1 +-40 4 ++37 1 +-37 5 ++13 1 +-13 4 ++10 1 +-10 4 ++7 1 +-7 4 +226 1 +cfi=(9) /build/buildd/eglibc-2.11.1/string/../sysdeps/x86_64/multiarch/../rtld-strlen.S +cfn=(18) strlen +calls=1 29 +* 42 +* 2 + +fl=(9) +fn=(18) +29 40 ++1 40 ++1 40 ++1 40 ++2 23 ++1 23 ++2 23 ++1 23 +-1 69 ++1 69 ++1 91 ++1 91 ++1 91 ++2 78 ++5 39 ++1 39 ++1 39 ++1 39 ++3 39 +-6 5 ++1 5 ++1 5 ++1 5 ++3 5 ++1 40 ++1 40 ++1 40 ++2 40 ++3 33 ++1 33 ++1 33 ++1 33 ++3 33 ++1 22 ++1 22 ++1 22 ++2 22 ++3 16 ++1 16 ++1 16 ++1 16 ++3 16 ++1 11 ++1 11 ++1 11 ++2 11 ++3 6 ++1 6 ++1 6 ++1 6 ++3 6 ++1 5 ++1 5 ++1 5 ++2 5 ++3 39 ++2 39 ++1 39 ++1 34 ++2 34 ++1 34 ++1 30 ++2 30 ++1 30 ++1 27 ++2 27 ++1 27 ++1 24 ++2 24 ++2 24 ++1 24 ++1 21 ++2 21 ++1 21 ++1 20 ++2 20 ++1 20 ++1 10 ++2 10 ++1 10 +-1 30 ++1 30 + +fl=(1) ??? +fn=(0) 0x0000000000000af0 +0 2 +cfi=(2) +cfn=(2) _dl_start +calls=1 363 +0 2123846 +0 14 +cfi=(38) +cfn=(174) +calls=1 93 +0 198780 +0 3 +cob=(12) /home/tclose/Code/Tractography/bin/dummy +cfi=(84) ??? +cfn=(1040) 0x000000000040e360 +calls=1 0 +0 1323498945522 + +fl=(34) /build/buildd/eglibc-2.11.1/elf/dl-version.c +fn=(134) match_symbol +82 460 ++9 46 +-8 46 +-1 138 ++1 46 ++8 46 ++6 138 ++15 46 ++1 92 ++2 46 ++5 92 ++14 572 ++12 720 ++4 480 +-30 480 ++19 276 +cfi=(16) /build/buildd/eglibc-2.11.1/string/../sysdeps/x86_64/multiarch/../strcmp.S +cfn=(44) strcmp +calls=46 -76 +* 3816 +* 138 ++34 46 ++1 322 + +fn=(132) _dl_check_map_versions +180 99 ++15 11 +-15 22 ++15 22 ++2 11 ++3 11 +-3 11 ++2 11 ++1 11 ++2 11 +-3 11 ++3 11 ++3 27 ++4 9 +-4 9 ++4 18 ++10 27 ++7 9 +62 9 +226 18 +62 54 +226 11 +62 11 +226 22 +62 106 ++1 163 +-1 326 ++2 549 +cfi=(26) /build/buildd/eglibc-2.11.1/elf/dl-misc.c +cfn=(84) _dl_name_match_p +calls=183 301 +* 11316 +* 366 +230 40 ++4 60 ++5 80 ++20 52 +-16 440 +cfn=(134) +calls=9 82 +* 1651 +* 222 +cfn=(134) +calls=37 82 +* 6395 +* 230 ++11 138 ++9 80 ++5 33 ++1 15 ++8 22 ++3 24 ++10 108 +-10 216 ++6 162 +-6 24 ++6 18 ++8 22 ++83 99 +-77 10 +-1 30 +cfi=(14) +cfn=(32) calloc +calls=10 111 +* 370 ++2 10 +-2 20 ++2 10 ++11 10 ++2 10 +-5 10 ++3 20 ++2 10 ++3 45 ++4 18 ++4 54 ++1 36 ++1 27 ++1 27 ++2 27 +-9 22 ++4 66 ++1 44 ++1 33 ++1 33 ++2 33 +-5 22 ++10 22 +-10 66 ++1 33 ++1 33 ++1 33 ++2 33 ++5 30 +-10 90 ++1 45 ++1 45 ++1 45 ++2 45 ++8 60 ++5 33 ++1 11 ++4 20 ++3 30 ++20 108 +-14 54 +-2 54 ++2 60 +-2 6 ++2 6 ++5 108 ++1 54 +-1 270 ++1 54 ++1 54 +-1 108 ++4 186 + +fn=(130) _dl_check_all_versions +383 5 ++4 1 +-4 1 ++4 1 +-4 1 ++4 3 ++1 33 +-1 11 ++1 11 +-1 22 ++5 7 +-3 44 +cfn=(132) +calls=11 180 +* 26216 +-1 44 + +fl=(20) +fn=(56) +82 36 ++1 9 ++1 54 + +fn=(92) read +82 36 ++1 9 + +fn=(90) open +82 248 ++1 62 ++1 312 + +fn=(104) close +82 40 ++1 10 + +fl=(18) /build/buildd/eglibc-2.11.1/posix/../sysdeps/unix/syscall-template.S +fn=(50) uname +82 4 ++1 1 + +fl=(17) +fn=(48) _dl_discover_osversion +67 4 ++2 3 ++85 5 +-45 3 +cfi=(18) +cfn=(50) +calls=1 -27 +* 5 +* 3 ++12 2 ++10 12 ++4 3 +-2 9 ++2 10 ++3 4 +-3 4 ++7 3 +-1 3 ++2 3 ++2 14 ++5 2 + +fl=(25) /build/buildd/eglibc-2.11.1/setjmp/../sysdeps/x86_64/setjmp.S +fn=(78) __sigsetjmp +26 26 ++2 26 ++1 52 ++1 26 ++4 26 ++1 26 ++1 26 ++1 26 ++1 26 ++2 52 ++2 26 ++1 26 ++2 52 ++2 26 ++4 26 ++1 26 + +fl=(33) /build/buildd/eglibc-2.11.1/string/memmove.c +fn=(124) memmove +47 2 ++5 4 +-5 10 ++1 2 +-1 2 ++5 4 ++5 6 ++22 102 ++30 14 + +fl=(19) /build/buildd/eglibc-2.11.1/elf/dl-load.c +fn=(94) _dl_map_object_from_fd +839 108 ++11 9 +-11 9 ++11 9 +-11 9 ++11 9 +cfi=(23) /build/buildd/eglibc-2.11.1/elf/dl-debug.c +cfn=(68) _dl_debug_initialize +calls=9 52 +* 81 ++4 27 +-4 9 ++4 9 +cfi=(27) /build/buildd/eglibc-2.11.1/io/../sysdeps/unix/sysv/linux/wordsize-64/fxstat.c +cfn=(96) _fxstat +calls=9 37 +* 90 +* 18 ++11 63 ++1 27 +-1 162 ++1 216 ++17 18 ++22 27 ++9 18 ++21 36 ++31 27 ++3 63 +cfi=(12) /build/buildd/eglibc-2.11.1/elf/dl-object.c +cfn=(28) _dl_new_object +calls=9 36 +* 4248 ++1 9 +-1 9 ++1 9 +-52 9 ++63 9 ++1 9 +-64 9 ++63 9 ++2 9 ++3 9 +-4 9 ++1 9 ++2 36 ++1 27 ++1 18 ++22 9 ++8 9 +-25 9 ++17 9 ++8 18 +-8 36 ++8 18 +-8 9 ++8 18 +-8 9 ++8 18 ++89 18 +-47 9 ++47 27 +-47 9 ++47 27 +-88 116 ++6 27 ++1 36 +-8 552 ++1 414 ++60 6 ++4 2 ++1 4 ++1 6 ++4 4 ++3 4 ++4 8 ++6 2 +cfi=(32) /build/buildd/eglibc-2.11.1/elf/dl-tls.c +cfn=(122) _dl_next_tls_modid +calls=2 54 +* 16 +* 6 ++1 2 +-67 90 ++6 108 ++8 18 ++1 18 +-1 18 ++1 18 +-1 36 ++1 18 ++1 126 ++2 54 ++1 54 ++1 54 ++4 18 +-4 18 ++4 45 ++5 81 ++11 9 +-11 81 ++11 9 +-46 6 ++1 2 +1160 27 ++1 27 +-5 18 ++1 9 +-70 8 ++78 36 +982 9 +1178 18 +982 9 +1178 36 ++2 9 +-2 9 ++2 9 ++19 72 +cfi=(21) /build/buildd/eglibc-2.11.1/misc/../sysdeps/unix/syscall-template.S +cfn=(60) mmap +calls=9 82 +* 54 ++4 9 +-4 9 ++4 18 ++7 27 ++1 9 ++2 9 +-2 9 ++2 9 ++10 18 ++35 54 ++1 27 ++2 36 ++7 72 ++6 9 ++2 9 +-2 9 ++1 9 ++2 18 +-1 36 ++8 18 ++3 18 ++11 72 +cfi=(28) /build/buildd/eglibc-2.11.1/string/../string/memset.c +cfn=(100) memset +calls=9 32 +* 1296 ++1 54 ++5 18 ++15 18 +-73 90 ++4 18 +-2 18 ++2 90 +cfi=(21) +cfn=(60) +calls=9 82 +* 54 +-2 18 +-29 63 +cfi=(21) +cfn=(98) mprotect +calls=9 82 +* 45 +* 9 +1323 9 +-77 9 ++77 18 ++9 9 +fi=(3) /build/buildd/eglibc-2.11.1/elf/dynamic-link.h +113 9 +fe=(19) +1332 9 +fi=(3) +113 9 ++6 9 +-2 9 ++2 18 ++7 9 ++5 9 ++3 9 ++1 9 +-3 9 +-5 18 +-1 212 ++1 132 ++10 44 +-18 132 ++18 9 +-18 27 ++2 410 ++8 152 ++8 152 +-18 456 ++25 27 ++20 36 ++1 36 ++1 36 ++1 36 ++2 36 ++5 36 ++1 35 ++1 36 ++6 27 ++5 18 ++7 18 ++1 36 ++16 27 ++5 1 ++2 1 +-2 2 ++2 1 ++2 2 ++2 2 ++3 27 ++2 2 ++2 2 ++3 18 +fe=(19) +1338 27 ++16 27 ++19 18 ++2 45 ++51 27 ++1 4 ++3 4 +cfi=(20) +cfn=(104) +calls=2 82 +* 10 +* 14 +cfi=(20) +cfn=(104) +calls=7 82 +* 35 +* 18 ++8 18 ++3 18 ++2 9 +-2 9 ++2 9 ++16 18 +cfi=(6) /build/buildd/eglibc-2.11.1/elf/dl-lookup.c +cfn=(10) _dl_setup_hash +calls=9 843 +* 261 ++4 18 ++1 18 ++17 18 ++4 9 ++5 9 +-5 9 ++1 18 ++4 9 ++8 9 +-1 18 ++20 81 +-35 2 +fi=(3) +128 36 ++3 36 ++3 36 ++1 36 +fe=(19) +1263 21 +-2 21 ++2 7 +-2 7 ++3 7 +-3 7 ++2 7 ++1 42 ++2 28 ++42 24 +cfi=(21) +cfn=(60) +calls=3 82 +* 18 ++3 6 + +fn=(120) local_strdup +160 28 ++1 7 +cfi=(9) +cfn=(18) +calls=7 29 +* 453 +* 7 ++1 14 +cfi=(14) +cfn=(36) +calls=7 -66 +* 196 ++2 14 ++3 14 ++1 14 +-1 7 ++1 7 +-1 7 +cfi=(15) +cfn=(42) memcpy +calls=7 56 +* 215 + +fn=(64) fillin_rpath +384 16 ++4 3 +cfi=(14) +cfn=(66) strsep +calls=1 -68 +* 24 +* 9 +cfi=(14) +cfn=(66) +calls=3 -68 +* 866 +* 12 ++3 6 +cfi=(9) +cfn=(18) +calls=3 29 +* 162 ++4 3 +-4 3 ++4 4 ++15 6 ++29 54 ++1 30 +-38 8 ++5 6 ++51 9 ++3 12 +cfi=(14) +cfn=(36) +calls=3 96 +* 84 ++3 3 +-3 3 ++3 3 ++4 3 ++2 9 +-2 6 ++2 3 +cfi=(15) +cfn=(58) +calls=3 56 +* 81 +* 3 ++3 3 +-2 6 ++2 3 ++1 1 ++5 2 ++1 1 +-1 2 ++1 2 +-1 4 ++1 2 +-1 4 ++1 41 ++1 2 +-1 6 ++1 2 +-1 32 +-98 2 ++98 3 ++1 13 +-1 2 ++1 2 +-1 8 ++1 2 +-1 6 ++4 3 +-1 6 ++1 3 ++7 6 ++1 3 ++3 9 ++5 1 ++3 9 +-14 6 +-9 2 + +fn=(82) _dl_map_object +1958 364 ++7 52 ++1 52 ++3 156 ++12 372 +-12 558 ++5 609 ++1 406 ++2 609 +cfi=(26) +cfn=(84) +calls=203 301 +* 12464 +* 406 +2240 234 +2001 9 +-1 18 ++10 9 +-1 18 ++26 18 +-2 9 ++2 9 +cfi=(22) /build/buildd/eglibc-2.11.1/string/../sysdeps/x86_64/multiarch/../strchr.S +cfn=(62) index +calls=9 26 +* 273 +* 18 +2172 2 ++1 3 +cfn=(86) expand_dynamic_string_token +calls=1 314 +* 231 ++2 1 +-3 1 ++3 1 ++4 9 +cfn=(88) open_verify +calls=1 1565 +* 202 ++3 1 +-3 1 ++3 1 ++11 27 ++3 18 ++41 9 ++1 63 +-1 9 ++1 27 +cfn=(94) +calls=9 839 +* 13987 +* 18 +2000 18 ++39 16 +cfi=(9) +cfn=(18) +calls=8 29 +* 431 +* 8 ++2 8 +-2 8 ++2 8 ++7 32 ++33 24 ++1 112 +cfn=(110) open_path +calls=8 1809 +* 9409 ++6 8 +-6 8 ++6 8 ++7 2 ++71 16 +-78 14 +599 21 +2095 21 ++6 14 +cfi=(31) /build/buildd/eglibc-2.11.1/elf/dl-cache.c +cfn=(114) _dl_load_cache_lookup +calls=7 182 +* 9571 ++2 7 +-2 7 ++2 7 ++4 21 ++12 14 ++22 70 +cfn=(88) +calls=7 1565 +* 1484 ++3 21 ++2 21 +cfn=(120) +calls=7 160 +* 983 ++1 7 +-1 7 ++1 14 +-90 8 +-5 16 ++5 8 ++3 16 +-3 8 ++3 16 +-3 8 ++3 56 +-3 24 +599 24 +2058 24 ++13 40 ++1 40 +599 24 +1982 186 +-1 372 ++4 117 ++2 117 +-2 234 ++2 351 +cfi=(16) +cfn=(44) +calls=117 63 +* 2996 +* 351 + +fn=(52) _dl_init_paths +622 1 ++15 2 +-15 8 ++15 3 +cfi=(7) +cfn=(54) +calls=1 353 +* 355 ++4 1 +-4 1 ++4 1 +cfi=(14) +cfn=(36) +calls=1 96 +* 28 ++2 1 +-2 2 ++2 1 ++7 7 ++4 2 +cfi=(14) +cfn=(36) +calls=1 96 +* 53 +* 1 ++3 3 ++7 1 ++22 1 +-3 1 ++1 2 ++2 1 +-23 1 ++23 4 +-22 1 ++18 1 ++4 2 +-12 1 +-2 1 ++3 1 ++2 1 +-3 1 ++4 2 ++4 1 +-3 1 ++3 1 +-8 3 +-2 3 ++3 3 ++2 3 +-3 3 ++4 6 ++4 3 +-3 3 ++3 3 ++1 8 +-1 52 ++2 4 +-1 12 ++1 4 +-1 48 ++1 8 +-1 4 ++1 4 +-1 16 ++1 4 +-1 12 ++3 4 +-14 4 ++14 24 ++7 1 ++4 1 +-5 1 ++6 2 ++2 4 ++2 3 ++32 5 ++8 3 +cfi=(22) +cfn=(62) +calls=1 26 +* 52 +* 2 ++2 2 +cfi=(9) +cfn=(18) +calls=1 29 +* 86 +* 8 +cfi=(15) +cfn=(42) +calls=1 56 +* 62 +* 1 ++17 7 ++2 1 ++1 2 ++1 1 +-4 3 ++2 44 ++1 88 ++1 44 +-4 133 ++7 1 +cfi=(14) +cfn=(36) +calls=1 96 +* 28 ++2 1 +-2 1 ++2 1 ++6 7 +cfn=(64) +calls=1 384 +* 1630 ++4 3 ++6 1 +-52 1 ++58 2 ++1 8 +-75 1 +-2 1 ++2 2 ++11 2 + +fn=(86) +314 8 ++10 1 +-10 1 ++10 2 +cfi=(22) +cfn=(62) +calls=1 26 +* 43 +* 2 +161 2 +cfi=(9) +cfn=(18) +calls=1 29 +* 81 +* 1 ++1 2 +cfi=(14) +cfn=(36) +calls=1 -66 +* 28 ++2 2 ++3 2 +339 3 +167 1 +339 4 +167 1 +cfi=(15) +cfn=(42) +calls=1 56 +* 47 + +fn=(88) +1565 671 ++36 61 +-36 183 ++36 242 ++21 244 +cfi=(20) +cfn=(90) +calls=61 82 +* 617 ++1 61 +-1 61 ++1 61 ++11 27 +-1 9 ++1 45 +cfi=(20) +cfn=(92) +calls=9 82 +* 45 +* 18 ++7 27 +-7 9 ++7 9 ++16 126 ++50 18 ++5 18 ++2 27 ++6 18 ++7 9 ++1 9 ++1 9 +-2 36 ++1 27 ++16 36 ++15 18 +-15 480 ++1 169 ++4 45 ++1 27 ++14 63 ++2 27 ++5 2 ++1 2 +-13 123 ++16 4 ++6 2 +-3 2 ++1 2 ++1 2 ++1 4 ++14 563 +-13 2 +-1 22 + +fn=(110) +1809 64 ++1 8 +-1 40 ++7 8 +-7 8 ++1 8 ++6 16 ++5 32 ++52 16 +-52 8 ++52 8 +-52 56 ++75 24 +-63 69 ++7 92 +cfi=(15) +cfn=(58) +calls=23 56 +* 617 ++1 23 +-1 23 ++1 161 ++20 16 ++26 3 +-46 479 ++3 184 ++4 318 +cfi=(15) +cfn=(58) +calls=53 56 +* 1032 +* 212 +cfi=(15) +cfn=(58) +calls=53 56 +* 1355 +* 53 +-1 53 ++7 106 ++3 371 +cfn=(88) +calls=53 1565 +* 2596 +* 53 ++2 159 ++26 180 ++2 134 ++39 22 +-41 22 ++41 110 ++7 22 +-2 22 ++2 118 +-67 16 ++1 48 ++79 8 +-79 16 ++6 16 ++3 8 +-3 8 ++3 24 +cfi=(30) /build/buildd/eglibc-2.11.1/io/../sysdeps/unix/sysv/linux/wordsize-64/xstat.c +cfn=(112) _xstat +calls=8 37 +* 98 +-1 16 ++1 8 ++2 12 ++7 24 ++27 3 +cfi=(14) +cfn=(36) +calls=1 96 +* 28 +* 1 ++1 2 +-1 1 ++1 1 ++2 4 +cfi=(15) +cfn=(42) +calls=1 56 +* 51 ++1 2 ++34 72 +-14 21 ++10 14 +-66 6 + +fl=(21) +fn=(98) +82 80 ++1 20 + +fn=(170) munmap +82 4 ++1 1 + +fn=(60) +82 140 ++1 28 + +fl=(26) +fn=(116) _dl_sysdep_read_whole_file +44 2 ++3 1 +-3 4 ++3 1 +-3 1 ++3 1 +cfi=(20) +cfn=(90) +calls=1 +35 +* 5 ++1 1 +-1 1 ++1 2 ++2 4 +cfi=(27) +cfn=(96) +calls=1 -13 +* 10 +* 2 ++2 1 ++3 1 +-3 1 ++3 1 ++13 2 +cfi=(20) +cfn=(104) +calls=1 +14 +* 5 ++3 7 +-14 7 +cfi=(21) +cfn=(60) +calls=1 +25 +* 6 +* 2 + +fn=(84) +301 10225 ++1 4090 +cfi=(16) +cfn=(44) +calls=2045 63 +* 14322 +* 4090 ++3 2045 ++2 4090 ++4 2036 +-4 6108 ++1 6219 +cfi=(16) +cfn=(44) +calls=2073 63 +* 47163 +* 4146 ++6 37 +-7 37 ++7 2119 +-7 2008 ++7 6024 + +fl=(28) +fn=(100) +32 11 +-2 22 ++2 11 ++5 22 ++1 33 ++1 33 ++3 33 ++4 22 ++8 22 ++1 43 ++2 7 ++1 7 ++1 7 ++1 7 ++1 7 ++1 7 ++1 7 ++1 14 +-9 14 ++2 70 ++1 70 ++1 70 ++1 70 ++1 70 ++1 70 ++1 70 ++1 140 +-9 140 +-30 14 ++43 7 ++3 14 ++1 14 +-4 4 ++3 8 ++1 41 ++2 22 +-2 22 ++2 54 +-2 54 +-47 11 ++53 11 ++4 22 ++8 11 + +fl=(29) /build/buildd/eglibc-2.11.1/elf/dl-deps.c +fn=(106) _dl_map_object_deps +149 1 ++1 1 +-1 2 ++1 1 +-1 2 ++1 1 +-1 1 ++1 2 +-1 4 ++1 1 +-1 1 ++1 2 ++16 1 +-16 1 ++14 1 ++1 1 ++1 1 ++6 3 ++10 1 +-10 1 ++10 1 +-36 5 ++20 1 +-2 1 ++19 1 +-17 1 ++6 1 +-6 1 +-2 1 ++2 1 +-2 1 ++1 1 ++1 1 ++6 3 ++10 1 +-10 1 ++10 5 ++19 1 +-15 1 +338 2 +203 1 ++1 1 +-18 2 +338 1 +201 1 +338 1 +204 1 +338 5 +208 2 ++5 1 ++4 2 +-9 20 ++5 10 ++4 20 ++2 2 ++3 22 ++2 9 ++11 9 +-4 9 +-7 9 ++6 9 ++1 9 +-7 9 ++5 9 ++3 18 ++3 63 ++50 50 ++1 51 +-51 860 ++1 430 ++6 125 +cfi=(22) +cfn=(62) +calls=25 26 +* 778 +* 75 ++5 125 +-3 25 ++3 25 +cfi=(24) /build/buildd/eglibc-2.11.1/elf/dl-error.c +cfn=(74) _dl_catch_error +calls=25 -87 +* 58503 ++2 75 ++15 25 ++2 50 ++5 9 ++6 9 ++2 9 +-8 18 ++5 9 +-2 9 ++1 9 ++2 9 ++4 54 +-59 8 ++13 4 +466 22 ++2 27 ++2 27 +cfi=(14) +cfn=(36) +calls=9 96 +* 252 ++2 9 +-2 9 ++2 9 ++4 36 +-1 9 ++2 9 +-1 18 +cfi=(15) +cfn=(42) +calls=9 56 +* 253 ++1 36 +cfi=(15) +cfn=(42) +calls=9 56 +* 253 ++3 9 ++4 66 ++2 11 ++1 72 +217 42 ++1 10 +-1 20 ++2 63 +487 4 ++4 2 ++4 5 ++11 4 +cfi=(14) +cfn=(36) +calls=1 96 +* 28 ++2 1 +-2 1 ++2 1 ++5 2 ++1 1 +-1 1 ++1 1 +-1 1 ++1 1 +-1 1 ++1 4 ++8 5 ++4 2 +-10 3 ++6 50 ++4 20 +-10 30 ++13 2 ++46 5 ++2 4 ++35 3 ++7 1 ++6 2 +-6 1 ++6 2 +-6 9 ++6 18 +-6 9 ++6 212 ++5 38 ++4 27 ++1 18 +-1 111 ++1 83 ++3 299 +-1 544 +-7 138 +-13 40 ++40 2 ++10 1 +-8 1 ++8 1 ++3 2 ++3 8 +-30 13 ++6 1 +-6 1 +cfi=(33) +cfn=(124) +calls=1 47 +* 73 ++2 1 ++6 5 +-6 1 ++6 1 +491 2 ++1 3 +288 760 +612 8 +cfi=(15) +cfn=(42) +calls=1 56 +* 64 ++5 4 + +fn=(108) openaux +62 50 ++4 25 +-4 25 ++7 25 +-4 50 ++1 25 +-1 50 ++1 100 +-1 75 +cfi=(19) +cfn=(82) +calls=25 1958 +* 56553 +* 25 ++5 75 + +fl=(36) /build/buildd/eglibc-2.11.1/elf/dl-reloc.c +fn=(146) _dl_relocate_object +158 66 ++10 22 +-10 33 ++14 11 +-14 22 ++14 11 ++1 55 ++6 22 ++6 33 ++4 22 ++8 33 ++45 11 +fi=(5) +96 22 +fe=(36) +242 22 +fi=(5) +96 11 ++39 3 +fe=(36) +268 320 +156 20 +fi=(5) +295 10 +fe=(36) +-27 10 +fi=(5) ++27 10 +fi=(4) /build/buildd/eglibc-2.11.1/elf/do-rel.h +65 10 +-8 10 ++1 10 ++1 10 ++6 10 +fe=(36) +268 2 +156 2 +fi=(5) +295 1 +fe=(36) +-27 1 +fi=(5) ++27 1 +fi=(4) +65 1 +-8 1 ++1 1 ++1 1 ++6 12 +-8 11 ++1 11 ++1 11 ++6 11 ++3 32 +fi=(5) +476 10 +-1 20 ++4 20 +-3 1491 +-1 2982 ++4 2982 ++2 4503 ++1 1501 +fi=(4) +68 4503 +fe=(36) +268 165 ++3 33 ++40 11 ++3 22 ++13 22 ++1 22 +cfn=(160) _dl_protect_relro +calls=11 +8 +* 275 +* 11 ++1 88 +fi=(5) +135 20 +-39 20 ++6 20 ++4 30 ++13 10 +-8 10 ++8 20 ++13 10 ++3 10 +-3 10 ++3 30 +fe=(36) ++51 33 ++82 9 +fi=(4) +75 11 ++2 11 +-2 22 ++1 11 ++1 102 ++14 10 +-12 10 ++12 21 +-12 1 ++12 2 ++10 22 ++10 33 ++4 10 ++2 10 +-2 10 ++2 10 +fi=(5) +296 30 +fi=(4) +119 20 ++1 10 ++2 20 +-2 10 +-1 10 +fi=(5) +267 10 +fi=(4) +119 10 +fi=(5) +270 10 +fi=(4) +119 10 ++1 30 +fi=(5) +270 10 +fi=(4) +119 5758 ++1 2879 ++2 5758 +-2 2879 +-1 2879 +fi=(5) +267 2879 +fi=(4) +119 2879 +fi=(5) +270 2879 +fi=(4) +119 2879 ++1 8637 +fi=(5) +270 2879 ++18 5778 ++7 52819 +fi=(4) +120 3492 +fi=(5) +295 5238 +fi=(4) +120 1746 +fi=(5) +295 7005 +fi=(4) +120 14 +fi=(5) +295 21 +fi=(4) +120 7 +fi=(5) +295 21064 +cfi=(6) +cfn=(152) _dl_lookup_symbol_x +calls=1753 698 +* 1738268 +* 7012 ++1 8667 ++4 2869 +-4 5738 ++4 8607 ++9 17334 ++85 2875 +fi=(4) +117 5750 +fi=(5) +394 2875 +fi=(4) +117 2885 +fi=(5) +377 30 ++4 30 ++5 20 +fi=(4) +117 10 +fi=(5) +386 20 +fi=(4) +117 20 +fi=(5) +335 3 ++1 2 +fi=(4) +117 1 +fi=(5) +336 1 +fi=(4) +117 2 +fi=(5) +327 6 ++1 3 +fi=(4) +117 3 +fi=(5) +328 3 +fi=(4) +117 6 +fi=(5) +295 14 +fi=(4) +104 30 +fi=(5) +466 9 +fi=(4) +105 9 +fi=(5) +466 18 ++1 18 +fi=(4) +104 9 +fi=(5) +465 9 +fi=(4) +104 9 +fi=(5) +467 9 +fi=(4) +104 9 +fi=(5) +467 5236 +fi=(4) +104 2618 +fi=(5) +465 2618 +fi=(4) +104 2618 +fi=(5) +467 2618 +fi=(4) +104 2618 +fi=(5) +466 2618 +fi=(4) +105 2618 +fi=(5) +466 2618 +fi=(4) +127 5 ++1 2 ++1 2 +-1 1 +fi=(5) +267 1 +fi=(4) +128 1 +fi=(5) +270 1 +fi=(4) +128 3 +fi=(5) +270 1 +fi=(4) +128 4 ++1 4 +-1 2 +fi=(5) +267 2 +fi=(4) +128 2 +fi=(5) +270 2 +fi=(4) +128 6 +fi=(5) +270 2 ++18 6 ++7 117 +cfi=(6) +cfn=(152) +calls=3 698 +* 2668 +* 12 ++1 9 ++4 1 +-4 2 ++4 3 ++9 18 ++85 9 +fi=(4) +127 10 +fi=(5) +295 28099 +fe=(36) + +fn=(160) +336 11 +-2 22 ++1 22 ++1 33 ++2 22 ++2 22 ++1 33 +cfi=(21) +cfn=(98) +calls=11 82 +* 55 +-1 22 ++7 33 + +fl=(32) +fn=(162) _dl_add_to_slotinfo +820 2 ++9 2 +-9 6 ++6 4 ++8 6 ++42 2 +-1 6 ++1 4 ++1 8 + +fn=(122) +54 2 ++3 6 ++48 4 ++4 4 + +fn=(138) _dl_determine_tlsoffset +116 7 ++6 3 ++3 2 ++36 3 ++2 9 +-38 1 ++38 2 ++3 4 ++4 4 +-4 6 ++2 4 ++2 6 ++12 4 ++4 10 ++2 8 ++10 2 +-37 4 ++37 2 +-37 5 ++41 1 +-1 1 ++52 1 +-51 4 ++52 8 + +fn=(140) _dl_allocate_tls_storage +332 1 ++13 1 +-13 2 ++2 1 ++11 2 +cfi=(14) +cfn=(40) __libc_memalign +calls=1 53 +* 50 ++1 1 +-1 1 ++1 1 ++7 1 ++4 305 +-58 1 ++1 1 +-1 1 ++1 2 +cfi=(14) +cfn=(32) +calls=1 111 +* 37 ++1 2 ++3 1 ++6 2 ++64 5 + +fn=(164) _dl_allocate_tls_init +380 7 ++1 1 +-1 1 ++1 1 ++12 1 +-8 1 ++8 5 ++5 7 ++6 11 ++22 4 ++1 6 ++2 4 ++1 6 ++8 6 ++1 6 ++1 10 +cfi=(15) +cfn=(58) +calls=2 56 +* 37 +* 8 +cfi=(28) +cfn=(100) +calls=2 32 +* 112 +* 6 +-42 6 ++6 9 ++3 1 ++1 2 +-1 1 ++1 2 ++6 2 ++2 2 +-2 4 ++2 4 ++38 1 ++3 9 + +fl=(16) +fn=(44) +63 6086 ++1 6086 ++1 6086 ++1 3455 ++1 3455 ++1 3455 ++1 3455 +cfn=(45) strcmp'2 +calls=3455 -6 +* 209833 ++5 2631 ++1 2631 ++1 2631 ++1 2631 + +fn=(45) +63 29437 ++1 29437 ++1 29437 ++1 27869 ++1 27869 ++1 27869 ++1 27869 +cfn=(45) +calls=25982 -6 +* 1770092 ++2 1887 ++1 1887 ++2 1568 ++1 1568 ++1 1568 ++1 1568 + +fl=(12) +fn=(28) +36 90 ++3 10 +-3 40 ++3 10 +cfi=(9) +cfn=(18) +calls=10 -10 +* 522 ++6 10 +-6 10 ++7 20 ++6 40 +cfi=(14) +cfn=(32) +calls=10 +59 +* 451 ++3 10 +-3 10 ++3 20 ++4 10 ++5 10 +-6 10 ++4 10 ++2 10 +-5 10 ++3 10 ++2 20 +cfi=(15) +cfn=(42) +calls=10 -8 +* 273 ++2 10 +-2 10 ++5 10 +-1 10 +-2 10 ++3 40 ++3 10 +-3 10 ++3 10 ++9 10 +-7 10 ++4 10 ++3 10 +-47 5 ++49 2 +-2 2 ++2 30 +-2 30 ++18 20 +-6 10 ++1 10 ++5 10 +-6 10 ++6 39 ++3 216 ++7 9 +-5 9 ++2 9 ++3 63 ++4 27 ++1 18 ++1 9 ++3 9 +-3 9 ++3 9 +-5 3 ++1 2 ++1 1 ++3 1 +-3 1 ++3 2 ++4 27 ++4 63 ++8 1 ++6 1 +-3 2 ++3 11 +-3 18 ++3 18 ++2 18 +cfi=(9) +cfn=(18) +calls=9 29 +* 470 +* 9 ++4 9 +-4 9 ++4 9 ++64 9 ++4 90 +46 100 ++27 20 ++39 5 ++10 1 ++4 4 ++24 18 +cfi=(14) +cfn=(36) +calls=9 -54 +* 252 ++1 9 +-1 9 ++1 27 ++45 27 +cfi=(15) +cfn=(58) +calls=9 56 +* 309 +* 9 ++6 274 +-1 137 ++1 146 +-1 9 ++1 9 ++2 18 ++3 18 + +fl=(15) +fn=(58) +56 145 ++4 145 ++3 145 ++1 145 ++2 52 ++1 52 ++2 52 ++1 52 ++5 52 ++1 52 +-1 93 ++1 93 ++2 85 ++1 85 ++2 85 ++1 85 ++5 85 ++1 85 +-1 60 ++1 60 ++2 60 ++1 60 ++2 60 ++1 60 ++5 60 ++1 60 +-1 85 ++1 85 ++2 74 ++1 74 ++2 74 ++1 148 ++5 74 ++1 74 +-1 71 ++1 98 ++5 27 ++1 27 ++1 27 ++1 27 ++2 27 ++2 27 ++1 27 ++2 27 ++6 145 ++4 145 ++12 2 ++2 2 ++1 2 ++26 2 ++1 2 ++3 2 ++1 2 ++1 2 ++5 2 ++2 2 ++1 2 ++1 2 ++1 2 ++2 2 ++1 2 ++1 2 ++1 2 ++2 2 ++1 2 ++2 2 ++22 2 ++2 2 + +fn=(42) +56 40 ++2 40 ++2 40 ++3 40 ++1 40 ++2 11 ++1 11 ++2 11 ++1 11 ++5 11 ++1 11 +-1 29 ++1 29 ++2 12 ++1 12 ++2 12 ++1 24 ++5 12 ++1 12 +-1 28 ++1 28 ++2 9 ++1 9 ++2 9 ++1 9 ++5 9 ++1 9 +-1 31 ++1 31 ++2 22 ++1 22 ++2 22 ++1 22 ++5 22 ++1 22 +-1 18 ++1 42 ++5 24 ++1 24 ++1 24 ++1 24 ++2 24 ++2 24 ++1 24 ++2 24 ++8 40 ++8 10 ++6 10 ++2 10 ++1 10 ++3 2 ++1 4 ++5 2 ++1 2 ++2 2 ++2 2 ++1 2 ++2 2 +-8 1 ++1 1 ++2 1 ++2 1 ++1 1 ++2 3 ++9 2 ++1 2 +-1 8 ++1 8 ++3 10 ++1 10 ++1 10 ++5 10 ++2 10 ++1 10 ++1 10 ++1 10 ++2 10 ++1 10 ++1 10 ++1 10 ++2 10 ++1 10 ++2 10 ++2 1 ++2 1 ++1 1 ++1 1 ++1 1 ++2 1 ++1 1 ++1 1 ++1 1 ++2 1 ++1 1 ++2 2 ++5 1 ++6 1 ++1 1 +-7 9 ++6 9 ++1 9 + +fl=(14) +fn=(36) +96 171 +cfn=(40) +calls=57 -43 +* 1556 + +fn=(32) +111 22 +-3 22 ++3 44 +-3 22 ++3 44 ++4 44 +cfn=(36) +calls=22 -19 +* 722 + +fn=(40) +53 232 ++1 231 ++11 171 ++3 57 +-3 57 ++3 114 +-3 3 ++3 1 +-3 1 ++3 210 ++4 24 ++1 18 ++6 42 +cfi=(21) +cfn=(60) +calls=6 +3 +* 36 ++2 12 ++3 12 ++1 12 +-1 6 ++1 12 ++3 6 ++1 6 ++2 24 +-3 52 ++1 52 ++2 208 +-31 2 +-1 5 + +fn=(66) +320 6 ++3 18 ++2 6 ++1 12 ++4 32 ++5 8 +-5 264 ++5 356 ++2 720 ++8 90 +-15 272 ++18 2 ++4 8 +-13 4 ++2 4 ++7 2 ++4 4 + +fl=(24) +fn=(74) +160 182 ++9 26 ++2 26 +cfi=(2) +cfn=(76) _dl_initial_error_catch_tsd +calls=26 794 +* 52 +* 26 ++1 26 ++2 52 +-2 26 ++2 26 +cfi=(25) +cfn=(78) +calls=26 26 +* 494 ++1 26 +-1 26 ++1 26 ++2 52 ++1 26 +-1 26 ++1 26 +cfi=(29) +cfn=(108) +calls=25 62 +* 57078 +cfi=(2) +cfn=(80) map_doit +calls=1 627 +* 2192 ++1 78 ++1 26 ++1 26 +-1 26 ++2 26 +-1 26 ++1 26 ++10 104 + +fn=(126) _dl_receive_error +198 10 ++1 1 +cfi=(2) +cfn=(76) +calls=1 794 +* 2 ++5 1 +-1 1 +-4 1 ++9 1 ++2 1 +-3 1 ++3 1 +cfi=(2) +cfn=(128) version_check_doit +calls=1 658 +* 26410 ++2 1 ++1 1 ++1 8 + +fl=(27) +fn=(96) +37 10 +-1 10 ++1 10 ++1 60 ++4 10 + +fl=(55) /build/buildd/eglibc-2.11.1/elf/../elf/dl-runtime.c +fn=(358) _dl_fixup +73 375 ++6 750 +-6 375 ++6 375 +-6 1125 ++6 375 ++1 375 +-4 375 ++3 375 +-3 375 ++4 375 ++1 375 +-1 1875 ++6 375 +-5 375 +-1 375 ++6 375 ++4 750 ++4 1125 ++5 2244 ++1 1122 ++8 1500 ++7 750 ++3 3750 +cfi=(6) +cfn=(152) +calls=375 698 +* 488484 +* 375 ++4 1125 ++4 1500 ++6 2625 ++8 375 ++7 1500 ++4 1125 +fi=(5) ++85 375 +fe=(55) +-81 2250 +-55 192 ++48 6 +cob=(4) +cfi=(136) /build/buildd/eglibc-2.11.1/string/../sysdeps/x86_64/multiarch/strcmp.S +cfn=(3194) strcmp +calls=1 -86 +* 9 +cob=(4) +cfi=(135) /build/buildd/eglibc-2.11.1/string/../sysdeps/x86_64/multiarch/strcpy.S +cfn=(3026) strncpy +calls=1 -86 +* 7 +cob=(4) +cfi=(121) /build/buildd/eglibc-2.11.1/string/../sysdeps/x86_64/multiarch/memcmp.S +cfn=(2148) bcmp +calls=1 29 +* 6 +cob=(4) +cfi=(80) /build/buildd/eglibc-2.11.1/string/../sysdeps/x86_64/multiarch/strlen.S +cfn=(940) strlen +calls=3 32 +* 18 +* 6 + +fl=(23) +fn=(68) +52 22 ++5 11 +-5 11 ++5 22 ++4 1 +-1 1 ++1 1 ++1 2 +-1 1 ++1 3 ++1 2 ++4 11 +-10 20 + +fn=(70) _dl_debug_state +77 2 + +fl=(152) /build/buildd/eglibc-2.11.1/elf/dl-fini.c +fn=(3700) _dl_sort_fini +34 10 ++1 1 +-1 1 ++1 1 ++2 1 ++2 2 ++7 9 +-7 3 ++3 50 ++4 50 ++1 106 +-1 220 ++5 76 ++2 27 ++1 18 +-1 111 ++1 83 ++3 200 ++23 99 +-24 544 ++27 138 +-32 202 +-12 27 ++76 8 +-53 13 +cfi=(33) +cfn=(124) +calls=1 -15 +* 73 ++4 1 +-2 1 ++2 3 +-2 1 ++2 1 ++9 2 ++2 1 + +fn=(3698) _dl_fini +121 11 ++22 8 ++3 2 +cfi=(2) +cfn=(896) rtld_lock_default_lock_recursive +calls=1 835 +* 2 ++3 1 ++3 2 ++2 1 +-2 1 ++2 1 +-2 4 ++13 5 ++16 3 ++2 22 ++2 22 ++2 22 ++1 11 ++5 11 +-4 11 +-2 11 +-6 33 ++14 2 ++4 2 ++2 5 ++9 1 +-9 1 +cfn=(3700) +calls=1 34 +* 2083 ++9 2 +cfi=(2) +cfn=(898) rtld_lock_default_unlock_recursive +calls=1 841 +* 2 +* 3 ++6 2 ++2 3 +-2 20 ++2 30 ++3 22 ++3 33 ++4 2 ++7 20 ++4 4 ++2 3 ++1 4 ++1 4 +cob=(4) +cfi=(46) /build/buildd/eglibc-2.11.1/elf/soinit.c +cfn=(3924) __libc_fini +calls=1 19 +* 6 +-1 4 ++5 30 ++1 27 +cob=(2) +cfi=(13) +cfn=(3904) 0x0000000005cc23c8 +calls=1 0 +* 2267 +cob=(2) +cfi=(13) +cfn=(3884) 0x0000000005a707f8 +calls=1 0 +* 2267 +cob=(2) +cfi=(13) +cfn=(3862) 0x00000000057e9238 +calls=1 0 +* 2310 +cob=(2) +cfi=(13) +cfn=(3842) 0x0000000005514ce8 +calls=1 0 +* 2267 +cob=(2) +cfi=(13) +cfn=(3824) 0x000000000528ded8 +calls=1 0 +* 2267 +cob=(2) +cfi=(13) +cfn=(3804) 0x0000000004c33d38 +calls=1 0 +* 2267 +cob=(2) +cfi=(13) +cfn=(3736) 0x0000000004eb8368 +calls=1 0 +* 10837 +cob=(2) +cfi=(13) +cfn=(3712) 0x0000000004a23748 +calls=1 0 +* 1546 +cob=(2) +cfi=(13) +cfn=(3702) 0x00000000004d8fd8 +calls=1 0 +* 22 ++5 55 +-39 11 ++55 11 +-55 33 +-71 2 ++71 1 +-71 1 +274 5 ++6 2 ++7 8 +-62 20 ++3 18 +-61 2 ++3 8 + +fl=(6) +fn=(156) check_match.12169 +132 12654 ++1 4218 ++2 4218 ++2 10545 ++10 6327 ++3 4218 ++5 2109 +-1 2109 ++1 2109 +-1 2109 ++1 2109 ++2 2994 ++19 2994 ++1 7485 ++1 1497 +-1 2994 ++1 4488 +cfi=(16) +cfn=(44) +calls=1496 63 +* 128810 +-1 2992 ++46 14763 +-73 1540 +cfi=(16) +cfn=(44) +calls=308 -87 +* 55321 +* 924 ++29 3 +-2 4 ++28 1836 ++2 7344 +-72 4216 + +fn=(152) +698 6393 +459 2131 +698 8524 +459 2131 +698 14917 +459 10655 ++1 4262 +-1 2131 ++1 6393 +-1 6393 ++1 152016 +-1 76008 ++1 228024 +-1 232286 +700 2131 ++4 2131 ++4 2131 +-8 2131 ++1 4262 ++7 5125 ++5 10655 ++6 19179 ++8 44 +-8 110 ++2 31965 +cfn=(154) do_lookup_x +calls=2131 82 +* 1322969 ++3 4262 +-5 2131 ++33 4262 ++23 6327 ++1 12654 ++35 8436 ++14 6327 ++3 6327 +962 2109 +833 2109 ++1 2109 ++1 17048 +-81 154 ++17 44 ++1 22 ++54 2 + +fn=(10) +843 11 ++4 33 ++5 11 ++3 22 ++2 11 +-1 11 ++3 33 ++5 11 +-4 11 ++1 11 ++3 11 +-3 11 ++7 11 +-5 11 ++1 11 ++4 22 +-7 11 ++5 11 ++2 33 ++13 22 + +fn=(154) +82 21310 ++1 2131 +-6 2131 ++5 4262 +-5 19179 +272 2131 +-42 6393 ++4 2131 +-4 2131 ++42 2131 +-38 2131 +98 2131 +-3 2131 ++1 2131 ++2 2131 ++3 2131 +-3 2131 ++3 2131 +-3 10795 +-3 10795 ++1 10795 ++2 10795 ++3 10795 +-3 10795 ++3 10795 ++4 25852 ++4 25852 ++4 25852 ++7 38778 ++4 12926 ++1 12926 +226 12926 +124 25852 ++1 25852 +226 12926 ++1 25852 ++4 12926 ++3 12926 +-3 25852 ++3 142186 ++24 10817 ++24 21634 +444 32451 ++1 9445 +-1 26676 ++4 43290 ++4 17048 +287 11456 ++4 8280 ++14 2109 +-1 2109 ++1 4218 ++1 2109 +445 8295 +cfi=(26) +cfn=(84) +calls=1659 301 +* 90979 +-1 8295 +241 16380 ++1 5460 ++2 18067 ++10 10856 +-7 29425 ++2 4218 ++1 2109 +-1 2109 ++1 8436 +-1 6327 ++1 8436 +cfn=(156) +calls=2109 132 +* 292930 ++1 12654 ++45 1888 +fi=(37) /build/buildd/eglibc-2.11.1/elf/../sysdeps/generic/dl-hash.h +65 8436 +fe=(6) + +fl=(54) /build/buildd/eglibc-2.11.1/elf/../sysdeps/x86_64/dl-trampoline.S +fn=(356) _dl_runtime_resolve +30 375 ++2 375 ++1 375 ++1 375 ++1 375 ++1 375 ++1 375 ++1 375 ++1 375 ++1 375 ++1 375 +cfi=(55) +cfn=(358) +calls=375 +32 +* 520219 ++1 375 ++1 375 ++1 375 ++1 375 ++1 375 ++1 375 ++1 375 ++1 375 ++1 375 ++2 375 + +fl=(8) +fn=(14) +29 1 ++3 4 ++2 2 +-2 1 ++2 1 ++7 2 + +fl=(2) +fn=(2) +363 9 ++18 4 +fi=(5) +76 2 +fe=(2) +381 1 ++29 2 +-3 1 +fi=(3) +119 1 +fe=(2) +410 1 +fi=(3) +119 2 ++3 1 ++4 1 ++5 1 ++3 1 ++1 1 +-3 1 +-5 2 +-5 13 ++15 13 +-18 39 ++18 1 +-18 3 ++2 36 ++5 20 ++1 12 ++10 4 +-18 13 ++25 2 ++20 4 ++1 4 ++1 4 ++1 4 ++2 4 ++5 4 ++1 4 ++1 4 ++6 3 ++5 2 ++7 3 ++1 3 ++8 3 ++2 3 ++3 2 ++1 2 +fe=(2) +538 2 ++7 1 +286 2 ++12 2 +cfi=(6) +cfn=(10) +calls=1 843 +* 29 ++1 1 ++1 1 ++1 1 +-2 1 ++3 1 +-2 1 ++1 1 ++1 1 ++21 1 ++10 1 +-10 3 ++10 1 +-6 1 +-4 1 ++10 1 +cfi=(7) +cfn=(12) +calls=1 88 +* 2123081 +* 1 ++9 1 ++7 1 +-4 1 ++4 1 +570 9 +fi=(3) +128 4 ++3 4 +fe=(2) +543 14 +fi=(4) +76 1 +-1 1 ++2 1 +-2 1 ++2 1 ++2 8 ++25 2 +fi=(5) +466 14 +fi=(4) +105 14 +fi=(5) +466 14 ++1 28 +-2 14 +fi=(4) +104 28 +fi=(5) +467 14 +fi=(4) +104 15 ++5 2 ++11 8 ++2 8 +fi=(5) +288 24 +fi=(4) +120 24 +fi=(5) +296 24 ++4 8 +-4 16 ++4 24 ++6 24 ++1 16 +fi=(4) +117 27 +fi=(3) ++17 4 ++1 4 +fe=(2) +286 67 + +fn=(80) +627 2 ++2 2 +-2 1 ++2 6 +cfi=(19) +cfn=(82) +calls=1 1958 +* 2177 +* 1 ++3 3 + +fn=(128) +658 2 ++3 4 +cfi=(34) +cfn=(130) +calls=1 383 +* 26400 +-1 2 ++4 2 + +fn=(896) +835 2 ++1 2 + +fn=(22) +886 1 ++19 1 ++7 1 +-26 6 ++32 1 +-32 4 ++27 1 +-5 1 ++10 1 ++3 1 +-16 1 ++7 1 +-4 1 ++5 1 ++8 1 +cfn=(24) process_envvars +calls=1 2494 +* 534 ++7 4 +1090 7 +cfi=(12) +cfn=(28) +calls=1 36 +* 248 ++2 1 +-2 1 ++2 1 ++1 2 ++2 1 ++1 2 +-2 1 ++1 1 ++1 2 ++29 1 +-3 1 ++3 1 +-8 1 ++1 1 ++2 1 ++5 6 ++1 28 +-1 27 ++1 52 ++95 2 ++1 3 +-5 2 ++1 1 +-88 3 ++1 1 ++49 2 ++1 2 +-1 8 ++2 4 ++1 2 ++3 2 ++1 2 +-1 2 ++1 2 ++1 2 ++1 6 ++1 2 +-46 1 ++10 1 +-10 1 ++10 1 +-7 2 +-3 1 ++10 1 ++68 2 +-87 3 ++1 1 ++92 3 ++3 2 ++2 2 ++2 3 ++13 3 ++1 6 +cfi=(16) +cfn=(44) +calls=1 63 +* 7 +-1 2 ++11 1 +-3 1 +-2 1 ++3 1 ++2 2 ++1 2 ++4 2 ++2 2 +fi=(3) +104 1 ++9 2 ++6 1 +-2 1 ++2 2 ++7 1 ++5 1 ++3 1 ++1 1 +-3 1 +-5 2 +-1 16 ++1 9 ++10 3 +-18 9 ++18 1 +-18 3 ++2 54 ++8 23 ++8 23 +-18 69 ++25 3 ++38 3 ++5 2 ++7 2 ++1 4 ++16 3 ++14 3 ++7 2 +fe=(2) +1271 2 +cfi=(6) +cfn=(10) +calls=1 843 +* 29 ++3 2 ++20 4 +fi=(3) +128 4 +fe=(2) +1383 1 +cfi=(17) +cfn=(48) +calls=1 67 +* 92 +* 8 ++5 2 +cfi=(19) +cfn=(52) +calls=1 622 +* 2979 ++3 3 +cfi=(23) +cfn=(68) +calls=1 52 +* 18 ++7 1 +-7 1 ++2 1 ++5 1 ++4 1 ++3 1 +-2 1 ++3 1 +-2 1 +-2 2 ++9 1 +-9 1 ++1 1 ++8 1 ++5 1 ++4 1 +-3 2 ++3 1 ++4 1 +-5 1 ++5 2 ++1 2 ++1 1 +-1 2 ++1 3 ++2 2 ++1 2 ++5 2 ++5 4 +1620 3 ++3 2 ++4 3 ++5 2 ++1 1 +cfi=(23) +cfn=(70) +calls=1 77 +* 1 ++4 3 ++15 3 ++4 4 ++31 3 +cfi=(20) +cfn=(56) +calls=1 82 +* 11 +* 2 ++77 1 ++11 1 +-11 3 ++17 1 ++1 2 +-1 1 ++1 2 +-1 1 ++1 3 +cfi=(29) +cfn=(106) +calls=1 149 +* 65597 ++1 1 ++2 5 ++3 1 +-3 2 ++3 1 +-3 1 ++3 1 +-3 1 ++3 1 ++1 5 +-1 2 ++1 40 +-1 21 ++4 3 ++1 3 ++1 1 ++2 2 ++1 52 +-1 27 +fi=(3) +131 4 ++3 4 ++1 4 +fe=(2) +1797 2 ++13 1 +-1 2 ++1 1 ++2 4 ++5 1 +-5 1 ++4 2 ++12 1 ++2 3 ++1 1 ++1 1 +-1 1 ++1 3 ++11 2 ++2 3 +-2 2 ++1 4 ++1 1 +cfi=(24) +cfn=(126) +calls=1 198 +* 26440 ++10 1 ++1 1 +-1 1 ++1 1 ++3 2 ++3 1 +cfn=(142) security_init +calls=1 848 +* 32 ++2 2 +2093 3 +2239 1 ++2 7 ++6 1 +-6 1 ++6 1 ++9 4 ++1 1 ++5 2 +cfi=(32) +cfn=(164) +calls=1 380 +* 283 ++4 2 ++8 4 ++15 1 ++2 1 ++1 1 +-3 1 ++3 3 +-3 1 ++3 1 +cfi=(36) +cfn=(146) +calls=1 158 +* 9118 ++1 1 ++2 9 ++8 1 +cfi=(7) +cfn=(166) +calls=1 251 +* 1 ++4 3 ++20 3 +cfi=(23) +cfn=(68) +calls=1 52 +* 9 ++1 1 ++1 1 +cfi=(23) +cfn=(70) +calls=1 77 +* 1 ++4 1 +cfi=(31) +cfn=(168) _dl_unload_cache +calls=1 306 +* 15 ++5 8 +2149 2 ++4 4 ++48 2 ++7 1 +-7 1 ++7 1 ++3 45 ++3 4 ++22 11 ++2 22 +-18 22 ++2 22 ++6 33 ++1 70 +cfi=(36) +cfn=(146) +calls=10 158 +* 2011896 ++4 26 ++1 4 +cfi=(32) +cfn=(162) +calls=2 820 +* 40 +* 2 +1828 2 +1412 4 +-11 4 +1857 1 +cfn=(136) init_tls +calls=1 780 +* 687 +* 3 +-89 9 ++4 3 ++1 1 ++1 2 ++1 2 +1663 59 +cfi=(15) +cfn=(42) +calls=1 56 +* 65 +* 1 ++3 4 ++3 3 +cfi=(14) +cfn=(66) +calls=1 320 +* 909 +* 3 +cfi=(14) +cfn=(66) +calls=1 320 +* 9 +* 6 ++1 4 ++3 4 +cfn=(72) do_preload +calls=1 800 +* 2277 +* 2 ++2 1 ++2 12 +2224 1 ++1 1 +-3 2 + +fn=(24) +2494 1 ++8 2 +-8 4 ++23 1 +-23 4 ++8 1 +-8 1 ++8 2 +-7 1 ++6 2 +fi=(156) /build/buildd/eglibc-2.11.1/elf/../sysdeps/unix/sysv/linux/dl-librecon.h +32 1 +fe=(2) +2501 1 +-6 1 +fi=(156) +32 2 +fe=(2) +2504 2 +cfi=(11) +cfn=(26) +calls=1 31 +* 54 +* 4 +cfi=(11) +cfn=(26) +calls=2 31 +* 252 +* 9 ++4 6 +-4 2 ++4 38 ++1 19 +-1 57 ++9 12 +2666 1 +-4 1 ++4 1 +-4 1 ++4 1 ++30 2 ++21 8 +2591 17 +-53 5 ++7 12 ++2 2 ++1 1 ++45 2 ++1 1 + +fn=(136) +780 1 +-56 1 +-4 1 +-2 1 ++2 1 ++4 1 ++60 3 +-54 1 ++3 4 +cfi=(14) +cfn=(32) +calls=1 111 +* 62 ++12 1 +-12 1 ++7 1 ++1 1 ++4 1 ++2 5 ++2 22 ++4 2 ++2 2 +-2 4 +-5 2 +-1 4 ++1 9 +-1 19 ++10 2 ++3 1 +cfi=(32) +cfn=(138) +calls=1 116 +* 101 ++7 1 +cfi=(32) +cfn=(140) +calls=1 332 +* 418 ++1 1 +-1 1 ++1 1 ++6 1 ++4 1 +-4 1 ++4 6 ++3 1 ++2 1 + +fn=(72) +800 6 ++6 1 ++1 1 ++6 5 +-11 1 ++6 1 ++1 1 ++2 1 ++2 1 +cfi=(24) +cfn=(74) +calls=1 160 +* 2249 ++1 2 ++2 3 ++12 5 + +fn=(76) +794 54 + +fn=(898) +841 2 ++1 2 + +fn=(142) +848 4 ++2 1 +fi=(35) /build/buildd/eglibc-2.11.1/elf/../sysdeps/unix/sysv/linux/dl-osinfo.h +68 1 ++4 1 ++3 2 ++48 7 +fe=(2) +852 1 ++6 3 ++2 1 +fi=(35) +132 2 ++11 1 +fe=(2) +863 1 ++2 1 ++6 1 ++1 5 + +fl=(10) +fn=(20) +35 3 ++8 1 +-8 1 ++8 5 ++4 2 ++11 5 + +fl=(31) +fn=(118) _dl_cache_libcmp +169 216 +-29 144 ++2 216 ++20 216 ++2 144 ++4 72 ++1 144 +cfn=(119) _dl_cache_libcmp'2 +calls=72 * +* 6029 + +fn=(119) +169 1086 +-29 746 ++2 1086 ++2 33 ++6 22 ++1 11 +-1 11 ++2 11 +-1 22 ++1 33 ++2 44 ++2 22 ++6 1053 ++2 702 ++4 290 ++1 580 +cfn=(119) +calls=290 * +* 19015 ++3 22 ++1 11 +-8 244 + +fn=(114) +182 56 ++8 14 ++3 21 ++45 14 ++6 21 ++15 14 +-6 7 ++6 7 +cfi=(20) +cfn=(56) +calls=7 82 +* 77 +* 7 ++17 35 +-23 7 ++23 14 +-23 7 ++23 1090 +cfn=(118) +calls=61 169 +* 5686 +* 317 ++21 63 +196 4 +cfi=(26) +cfn=(116) +calls=1 44 +* 68 ++8 2 ++1 1 +-1 2 ++1 3 +-1 13 ++8 1 +-3 2 ++3 3 ++3 1 ++1 2 +-1 1 ++1 1 ++19 2 +-17 2 +-2 22 ++60 141 +cfn=(118) +calls=4 169 +* 356 +* 35 +cfn=(118) +calls=7 169 +* 1139 +* 285 ++16 28 + +fn=(168) +306 1 ++1 4 ++2 2 +cfi=(21) +cfn=(170) +calls=1 82 +* 5 ++1 1 ++2 2 + +fl=(22) +fn=(62) +26 36 ++1 36 ++1 36 ++1 36 ++1 36 ++1 36 ++1 36 ++1 36 ++1 36 ++1 36 ++1 36 ++1 36 ++1 36 ++1 36 ++1 36 ++1 36 ++1 36 ++1 36 ++1 36 ++1 36 ++1 36 ++2 27 ++1 27 ++1 27 ++1 27 ++1 27 ++1 27 ++1 27 ++1 27 ++1 27 ++2 36 ++1 36 ++1 1 ++1 1 ++1 1 ++1 1 ++1 35 ++1 36 + +fl=(30) +fn=(112) +37 8 +-1 8 ++1 8 ++1 48 ++4 2 +-4 24 + +ob=(10) /lib/libz.so.1.2.3.3 +fl=(59) ??? +fn=(3806) 0x0000000000002280 +0 10 +cob=(4) +cfi=(153) /build/buildd/eglibc-2.11.1/stdlib/cxa_finalize.c +cfn=(3726) __cxa_finalize +calls=1 31 +0 430 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1810 +0 13 + +fn=(448) 0x0000000000002300 +0 6 + +fn=(442) 0x0000000000002260 +0 6 + +fn=(454) 0x000000000000ed00 +0 11 + +ob=(7) /usr/lib/libstdc++.so.6.0.13 +fl=(53) ??? +fn=(2684) std::ostream& std::ostream::_M_insert(long) +0 65 +cfn=(1400) std::ostream::sentry::sentry(std::ostream&) +calls=5 0 +0 105 +0 86 +cfn=(2686) std::num_put > >::do_put(std::ostreambuf_iterator >, std::ios_base&, char, long) const +calls=3 0 +0 622 +0 22 +cfn=(2686) +calls=2 0 +0 5116 +0 124 + +fn=(2686) +0 25 +cfn=(2692) std::ostreambuf_iterator > std::num_put > >::_M_insert_int(std::ostreambuf_iterator >, std::ios_base&, char, long) const +calls=5 0 +0 3953 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1740 +0 20 + +fn=(296) 0x00000000000ac590 +0 49 + +fn=(532) std::locale::facet::_S_create_c_locale(__locale_struct*&, char const*, __locale_struct*) +0 4 +cob=(4) +cfi=(61) /build/buildd/eglibc-2.11.1/locale/newlocale.c +cfn=(538) newlocale +calls=1 46 +0 42 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1796 +0 5 + +fn=(544) std::locale::_Impl::_M_install_facet(std::locale::id const*, std::locale::facet const*) +0 364 +cfn=(550) std::locale::id::_M_id() const +calls=28 0 +0 392 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1024 +0 6328 + +fn=(634) std::ctype::_M_convert_to_wmask(unsigned short) const +0 100 +cob=(4) +cfi=(68) /build/buildd/eglibc-2.11.1/wctype/wctype_l.c +cfn=(640) wctype_l +calls=1 28 +0 134 +0 13 +cob=(4) +cfi=(68) +cfn=(640) +calls=1 28 +0 254 +0 17 +cob=(4) +cfi=(68) +cfn=(640) +calls=1 28 +0 387 +0 3 +cob=(4) +cfi=(68) +cfn=(640) +calls=1 28 +0 230 +0 3 +cob=(4) +cfi=(68) +cfn=(640) +calls=1 28 +0 350 +0 3 +cob=(4) +cfi=(68) +cfn=(640) +calls=1 28 +0 98 +0 3 +cob=(4) +cfi=(68) +cfn=(640) +calls=1 28 +0 171 +0 3 +cob=(4) +cfi=(68) +cfn=(640) +calls=1 28 +0 74 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1796 +0 3 +cob=(4) +cfi=(68) +cfn=(640) +calls=1 28 +0 164 + +fn=(654) std::numpunct::_M_initialize_numpunct(__locale_struct*) +0 345 + +fn=(672) std::__timepunct::__timepunct(std::__timepunct_cache*, unsigned long) +0 13 +cfn=(512) std::locale::facet::_S_get_c_name() +calls=1 0 +0 2 +0 4 +cfn=(678) std::__timepunct::_M_initialize_timepunct(__locale_struct*) +calls=1 0 +0 112 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1409 +0 3 + +fn=(688) 0x000000000006a230 +0 17210 +cfn=(696) __cxa_guard_acquire +calls=1 0 +0 24 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 980 +0 6 +cfn=(708) __cxa_guard_release +calls=1 0 +0 5 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1022 +0 1 + +fn=(746) std::locale::~locale() +0 17064 + +fn=(786) std::num_put > > const& std::use_facet > > >(std::locale const&) +0 2840 +cfn=(550) +calls=710 0 +0 3550 +0 7810 +cfn=(764) __dynamic_cast +calls=710 0 +0 41890 +0 2840 + +fn=(840) bool std::has_facet > > >(std::locale const&) +0 16 +cfn=(550) +calls=4 0 +0 20 +0 44 +cfn=(764) +calls=4 0 +0 236 +0 16 + +fn=(1338) std::string::reserve(unsigned long) +0 13200 +cfn=(1344) std::string::_Rep::_M_clone(std::allocator const&, unsigned long) +calls=825 0 +0 135750 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1075 +0 7568 +cfn=(1308) std::string::_Rep::_M_destroy(std::allocator const&) +calls=5 0 +0 410 +0 138 + +fn=(1360) std::string::append(std::string const&) +0 341 +cfn=(1338) +calls=8 0 +0 2462 +0 107 +cob=(4) +cfi=(81) /build/buildd/eglibc-2.11.1/string/../sysdeps/x86_64/memcpy.S +cfn=(966) memcpy +calls=16 56 +0 609 +0 190 + +fn=(1454) std::ostreambuf_iterator > std::num_put > >::_M_insert_int(std::ostreambuf_iterator >, std::ios_base&, char, unsigned long) const +0 66 +cfn=(1456) 0x000000000008ba20 +calls=3 0 +0 84 +0 63 +cfn=(1462) 0x00000000000874e0 +calls=3 0 +0 223 +0 68 +cfn=(2694) std::basic_streambuf >::xsputn(char const*, long) +calls=2 0 +0 1188 +cfn=(1402) __gnu_cxx::stdio_sync_filebuf >::xsputn(char const*, long) +calls=1 0 +0 247 +0 73 + +fn=(1692) std::basic_streambuf >::sbumpc() +0 1225 + +fn=(1710) 0x00000000000a8b30 +0 18657 +cfn=(952) std::string::_Rep::_S_create(unsigned long, unsigned long, std::allocator const&) +calls=1239 0 +0 167364 +0 9708 +cob=(4) +cfi=(81) +cfn=(966) +calls=1188 56 +0 38057 +0 12633 + +fn=(1904) std::__basic_file::close() +0 50 +cfn=(1556) std::__basic_file::is_open() const +calls=10 0 +0 30 +0 95 +cob=(4) +cfi=(95) /build/buildd/eglibc-2.11.1/csu/errno-loc.c +cfn=(1302) __errno_location +calls=5 34 +0 15 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1834 +0 20 +cob=(4) +cfi=(120) /build/buildd/eglibc-2.11.1/libio/iofclose.c +cfn=(1914) fclose@@GLIBC_2.2.5 +calls=5 43 +0 2992 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1698 +0 25 + +fn=(2274) std::num_get > >::do_get(std::istreambuf_iterator >, std::istreambuf_iterator >, std::ios_base&, std::_Ios_Iostate&, long&) const +0 90 +cfn=(2280) std::istreambuf_iterator > std::num_get > >::_M_extract_int(std::istreambuf_iterator >, std::istreambuf_iterator >, std::ios_base&, std::_Ios_Iostate&, long&) const +calls=9 0 +0 2435 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1905 +0 18 + +fn=(2728) std::num_put > >::do_put(std::ostreambuf_iterator >, std::ios_base&, char, void const*) const +0 13 +cfn=(1454) +calls=1 0 +0 816 +0 7 + +fn=(3152) std::basic_filebuf >::seekpos(std::fpos<__mbstate_t>, std::_Ios_Openmode) +0 10 +cfn=(1556) +calls=1 0 +0 3 +0 11 +cfn=(3158) std::basic_filebuf >::_M_seek(long, std::_Ios_Seekdir, __mbstate_t) +calls=1 0 +0 3062 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1527 +0 6 + +fn=(2696) std::basic_stringbuf, std::allocator >::overflow(int) +0 152 +cfn=(1338) +calls=4 0 +0 1832 +0 76 +cfn=(2702) std::string::swap(std::string&) +calls=4 0 +0 44 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 999 +0 28 +cfn=(1758) std::basic_stringbuf, std::allocator >::_M_sync(char*, unsigned long, unsigned long) +calls=4 0 +0 108 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1372 +0 16 + +fn=(282) 0x00000000000c9500 +0 11 + +fn=(292) 0x00000000000c8ea0 +0 52 + +fn=(368) 0x00000000000639f0 +0 1 + +fn=(492) std::locale::locale() +0 8604 +cfn=(494) 0x000000000006c5c0 +calls=1434 0 +0 76167 +0 1434 +cfn=(688) +calls=1434 0 +0 19248 +0 17208 + +fn=(518) std::ctype::ctype(unsigned short const*, bool, unsigned long) +0 14 +cfn=(524) std::locale::facet::_S_get_c_locale() +calls=1 0 +0 3244 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1149 +0 94 + +fn=(526) 0x0000000000069060 +0 4 +cfn=(532) +calls=1 0 +0 1847 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1384 + +fn=(722) std::ios_base::ios_base() +0 20938 +cfn=(492) +calls=361 0 +0 14079 + +fn=(758) bool std::has_facet >(std::locale const&) +0 2840 +cfn=(550) +calls=710 0 +0 3550 +0 7810 +cfn=(764) +calls=710 0 +0 66740 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 959 +0 2840 + +fn=(778) bool std::has_facet > > >(std::locale const&) +0 2840 +cfn=(550) +calls=710 0 +0 3550 +0 7810 +cfn=(764) +calls=710 0 +0 41890 +0 2840 + +fn=(780) __cxxabiv1::__si_class_type_info::__do_dyncast(long, __cxxabiv1::__class_type_info::__sub_kind, __cxxabiv1::__class_type_info const*, void const*, __cxxabiv1::__class_type_info const*, void const*, __cxxabiv1::__class_type_info::__dyncast_result&) const +0 48858 + +fn=(828) bool std::has_facet > > >(std::locale const&) +0 16 +cfn=(550) +calls=4 0 +0 20 +0 44 +cfn=(764) +calls=4 0 +0 236 +0 16 + +fn=(1142) operator delete(void*) +0 6973172778 +cob=(4) +cfi=(71) /build/buildd/eglibc-2.11.1/malloc/malloc.c +cfn=(1148) free +calls=2324390926 3692 +0 181303823584 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1642 + +fn=(1254) std::basic_string, std::allocator >::basic_string(std::string const&) +0 17182973961 +cfn=(1344) +calls=21 0 +0 4162 +0 5727657514 + +fn=(1446) std::ctype::do_widen(char) const +0 2 + +fn=(1562) std::__basic_file::open(char const*, std::_Ios_Openmode, int) +0 40 +cfn=(1564) 0x00000000000c8480 +calls=5 0 +0 50 +0 25 +cfn=(1556) +calls=5 0 +0 15 +0 25 +cob=(4) +cfi=(108) /build/buildd/eglibc-2.11.1/libio/../sysdeps/wordsize-64/../../libio/iofopen.c +cfn=(1574) fopen@@GLIBC_2.2.5 +calls=5 107 +0 3691 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1723 +0 55 + +fn=(1612) std::basic_filebuf >::_M_allocate_internal_buffer() +0 40 +cfn=(1618) operator new[](unsigned long) +calls=5 0 +0 2739 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 877 +0 20 + +fn=(1650) std::string::_M_mutate(unsigned long, unsigned long, unsigned long) +0 4370 +cfn=(952) +calls=16 0 +0 2561 +0 3374 + +fn=(1824) std::ios_base::_M_call_callbacks(std::ios_base::event) +0 4236 + +fn=(2266) std::istream::operator>>(int&) +0 28 +cfn=(2272) std::istream& std::istream::_M_extract(long&) +calls=4 0 +0 3445 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1080 +0 72 + +fn=(2272) +0 81 +cfn=(1644) std::istream::sentry::sentry(std::istream&, bool) +calls=9 0 +0 449 +0 207 +cfn=(2274) +calls=9 0 +0 4448 +0 108 +cfn=(1630) std::basic_ios >::clear(std::_Ios_Iostate) +calls=9 0 +0 72 +0 45 + +fn=(2280) +0 144 +cfn=(1456) +calls=9 0 +0 252 +0 1791 +cfn=(1798) std::basic_stringbuf, std::allocator >::underflow() +calls=1 0 +0 16 +0 64 +cfn=(1798) +calls=8 0 +0 128 +0 40 + +fn=(2760) std::basic_stringbuf, std::allocator >::str() const +0 19 +cfn=(2766) std::basic_string, std::allocator >::basic_string(char*, char*, std::allocator const&) +calls=1 0 +0 229 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1047 +0 3 +cfn=(1260) std::string::assign(std::string const&) +calls=1 0 +0 28 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 992 +0 18 + +fn=(2694) +0 223 +cfn=(2696) +calls=4 0 +0 4627 +0 212 +cob=(4) +cfi=(81) +cfn=(966) +calls=12 56 +0 222 +0 60 + +fn=(524) +0 3660 +cfn=(526) +calls=1 0 +0 3235 +0 3 + +fn=(568) std::moneypunct::_M_initialize_moneypunct(__locale_struct*, char const*) +0 112 + +fn=(728) std::basic_ios >::init(std::basic_streambuf >*) +0 4260 +cfn=(734) std::ios_base::_M_init() +calls=710 0 +0 64451 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1040 +0 2130 +cfn=(752) std::basic_ios >::_M_cache_locale(std::locale const&) +calls=710 0 +0 434340 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1442 +0 9230 + +fn=(764) +0 116019 +cfn=(780) +calls=2874 0 +0 48858 +cfn=(766) __cxxabiv1::__vmi_class_type_info::__do_dyncast(long, __cxxabiv1::__class_type_info::__sub_kind, __cxxabiv1::__class_type_info const*, void const*, __cxxabiv1::__class_type_info const*, void const*, __cxxabiv1::__class_type_info::__dyncast_result&) const +calls=1423 0 +0 73996 +0 64455 + +fn=(942) 0x00000000000a8880 +0 8585969064 +cfn=(952) +calls=572397936 0 +0 74012132505 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1077 +0 4579183364 +cob=(4) +cfi=(81) +cfn=(966) +calls=572397905 56 +0 12635859943 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1708 +0 5723979483 + +fn=(952) +0 8013600365 +cfn=(880) operator new(unsigned long) +calls=39 0 +0 5535 +0 572400001 +cfn=(880) +calls=572400001 0 +0 63136811529 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 869 +0 2289600160 + +fn=(1532) std::__basic_file::__basic_file(pthread_mutex_t*) +0 15 + +fn=(1630) +0 3304 + +fn=(1652) std::basic_filebuf >::underflow() +0 216 +cfn=(1654) std::codecvt::do_always_noconv() const +calls=6 0 +0 12 +0 36 +cfn=(1660) std::__basic_file::xsgetn(char*, long) +calls=6 0 +0 4622 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1121 +0 21 +cfn=(1624) std::basic_filebuf >::_M_set_buffer(long) +calls=1 0 +0 15 +0 28 +cfn=(1624) +calls=5 0 +0 80 +0 35 + +fn=(1686) std::string::append(char const*, unsigned long) +0 6090 +cfn=(1338) +calls=193 0 +0 39899 +0 1571 +cob=(4) +cfi=(81) +cfn=(966) +calls=193 56 +0 10202 +0 1037 + +fn=(1702) std::string::find(char, unsigned long) const +0 5130 +cob=(4) +cfi=(89) /build/buildd/eglibc-2.11.1/string/../sysdeps/x86_64/memchr.S +cfn=(1248) memchr +calls=513 25 +0 16648 +0 2565 + +fn=(1752) std::basic_string, std::allocator >::basic_string(char const*, unsigned long, std::allocator const&) +0 2752 +cfn=(942) +calls=344 0 +0 63891 +0 1376 + +fn=(1886) std::basic_filebuf >::_M_terminate_output() +0 180 + +fn=(1892) std::basic_filebuf >::_M_destroy_internal_buffer() +0 40 +cfn=(1898) operator delete[](void*) +calls=5 0 +0 1358 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 888 +0 55 + +fn=(2196) std::string::compare(unsigned long, unsigned long, char const*) const +0 32 +cob=(4) +cfi=(69) /build/buildd/eglibc-2.11.1/string/../sysdeps/x86_64/multiarch/../strlen.S +cfn=(642) __GI_strlen +calls=2 26 +0 38 +0 79 + +fn=(2312) std::istream& std::istream::_M_extract(float&) +0 2331 +cfn=(1644) +calls=259 0 +0 12432 +0 5957 +cfn=(2314) std::num_get > >::do_get(std::istreambuf_iterator >, std::istreambuf_iterator >, std::ios_base&, std::_Ios_Iostate&, float&) const +calls=259 0 +0 393954 +0 3108 +cfn=(1630) +calls=259 0 +0 2072 +0 1295 + +fn=(2420) std::_Rb_tree_rotate_left(std::_Rb_tree_node_base*, std::_Rb_tree_node_base*&) +0 9662 + +fn=(2766) +0 8 +cfn=(1710) +calls=1 0 +0 217 +0 4 + +fn=(2830) std::_Rb_tree_increment(std::_Rb_tree_node_base*) +0 17296504 + +fn=(3164) std::__basic_file::seekoff(long, std::_Ios_Seekdir) +0 6 +cfn=(1666) std::__basic_file::fd() +calls=1 0 +0 9 +0 7 +cob=(4) +cfi=(103) /build/buildd/eglibc-2.11.1/misc/../sysdeps/unix/syscall-template.S +cfn=(3170) lseek +calls=1 82 +0 7 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1721 + +fn=(3282) std::basic_ifstream >::~basic_ifstream() +0 36 +cfn=(1880) std::basic_filebuf >::close() +calls=2 0 +0 40 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1272 +0 4 +cfn=(1940) std::__basic_file::~__basic_file() +calls=2 0 +0 34 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1042 +0 10 +cfn=(746) +calls=2 0 +0 24 +0 34 +cfn=(1818) std::ios_base::~ios_base() +calls=2 0 +0 116 + +fn=(3614) std::ostream& std::ostream::_M_insert(double) +0 12 +cfn=(1400) +calls=1 0 +0 21 +0 22 +cfn=(3616) std::num_put > >::do_put(std::ostreambuf_iterator >, std::ios_base&, char, double) const +calls=1 0 +0 8307 +0 19 + +fn=(272) 0x000000000005a540 +0 6 + +fn=(512) +0 10 + +fn=(562) std::numpunct::_M_initialize_numpunct(__locale_struct*) +0 410 + +fn=(708) +0 5 + +fn=(822) std::ctype const& std::use_facet >(std::locale const&) +0 16 +cfn=(550) +calls=4 0 +0 20 +0 44 +cfn=(764) +calls=4 0 +0 236 +0 16 + +fn=(1242) std::string::find_last_of(char const*, unsigned long, unsigned long) const +0 290 +cob=(4) +cfi=(89) +cfn=(1248) +calls=40 25 +0 892 +0 20 +cob=(4) +cfi=(89) +cfn=(1248) +calls=5 25 +0 110 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1682 +0 249 + +fn=(1344) +0 9306 +cfn=(952) +calls=846 0 +0 115610 +0 12882 +cob=(4) +cfi=(81) +cfn=(966) +calls=48 56 +0 2018 +0 96 + +fn=(1474) std::ostream::put(char) +0 30 +cfn=(1400) +calls=3 0 +0 63 +0 69 +cfn=(1476) __gnu_cxx::stdio_sync_filebuf >::overflow(int) +calls=3 0 +0 2232 +0 6 + +fn=(1538) bool std::has_facet >(std::locale const&) +0 20 +cfn=(550) +calls=5 0 +0 25 +0 55 +cfn=(764) +calls=5 0 +0 295 +0 20 + +fn=(1644) +0 25630 +cfn=(1630) +calls=61 0 +0 488 +0 11529 + +fn=(1758) +0 7332 + +fn=(1772) std::num_get > >::_M_extract_float(std::istreambuf_iterator >, std::istreambuf_iterator >, std::ios_base&, std::_Ios_Iostate&, std::string&) const +0 8192 +cfn=(1456) +calls=512 0 +0 14336 +0 218126 +cfn=(1844) 0x000000000008a190 +calls=193 0 +0 5404 +0 772 +cfn=(1856) 0x000000000008a140 +calls=193 0 +0 2316 +0 13808 +cfn=(1798) +calls=14 0 +0 224 +0 2054 +cfn=(1798) +calls=315 0 +0 6474 +0 1575 + +fn=(1856) +0 2316 + +fn=(1898) +0 5 +cfn=(1142) +calls=5 0 +0 1353 + +fn=(2246) std::string::find_first_of(char const*, unsigned long, unsigned long) const +0 240 +cob=(4) +cfi=(89) +cfn=(1248) +calls=10 25 +0 238 +0 16 +cob=(4) +cfi=(89) +cfn=(1248) +calls=4 25 +0 97 +0 147 + +fn=(2504) std::basic_istream >& std::operator>>, std::allocator >(std::basic_istream >&, std::basic_string, std::allocator >&) +0 28 +cfn=(1644) +calls=2 0 +0 96 +0 36 +cfn=(1650) +calls=2 0 +0 76 +0 24 +cfn=(2510) std::locale::locale(std::locale const&) +calls=2 0 +0 12 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1013 +0 4 +cfn=(772) std::ctype const& std::use_facet >(std::locale const&) +calls=2 0 +0 236 +0 6 +cfn=(746) +calls=2 0 +0 24 +0 72 +cfn=(1686) +calls=2 0 +0 448 +0 52 + +fn=(2510) +0 12 + +fn=(3158) +0 11 +cfn=(1886) +calls=1 0 +0 30 +0 13 +cfn=(3164) +calls=1 0 +0 1750 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1240 +0 18 + +fn=(3444) std::_Rb_tree_rotate_right(std::_Rb_tree_node_base*, std::_Rb_tree_node_base*&) +0 9636 + +fn=(266) 0x000000000005a4a0 +0 6 + +fn=(278) 0x00000000000d1200 +0 11 +cfn=(282) +calls=1 0 +0 11 +0 16 +cfn=(372) 0x000000000005c2d0 +calls=1 0 +0 57 +cfn=(370) 0x000000000005fef0 +calls=1 0 +0 1 +cfn=(368) +calls=1 0 +0 1 +cfn=(348) 0x0000000000072400 +calls=1 0 +0 1917 +cfn=(322) 0x0000000000087050 +calls=1 0 +0 49 +cfn=(296) +calls=1 0 +0 49 +cfn=(294) 0x00000000000c3ba0 +calls=1 0 +0 1 +cfn=(292) +calls=1 0 +0 52 +0 31 + +fn=(348) +0 8 +cob=(4) +cfi=(56) /build/buildd/eglibc-2.11.1/stdlib/cxa_atexit.c +cfn=(362) __cxa_atexit +calls=1 57 +0 62 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1778 +0 7 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 + +fn=(486) std::ios_base::Init::Init() +0 2067 +cfn=(492) +calls=1 0 +0 66774 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 952 +0 16 +cfn=(492) +calls=1 0 +0 39 +0 14 +cfn=(492) +calls=1 0 +0 39 +0 6 +cfn=(722) +calls=1 0 +0 97 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 970 +0 15 +cfn=(728) +calls=1 0 +0 14921 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1451 +0 3 +cfn=(722) +calls=1 0 +0 97 +0 16 +cfn=(728) +calls=1 0 +0 708 +0 3 +cfn=(722) +calls=1 0 +0 97 +0 14 +cfn=(728) +calls=1 0 +0 708 +0 3 +cfn=(722) +calls=1 0 +0 97 +0 14 +cfn=(728) +calls=1 0 +0 708 +0 16 +cfn=(492) +calls=1 0 +0 39 +0 16 +cfn=(492) +calls=1 0 +0 39 +0 14 +cfn=(492) +calls=1 0 +0 39 +0 6 +cfn=(722) +calls=1 0 +0 97 +0 15 +cfn=(804) std::basic_ios >::init(std::basic_streambuf >*) +calls=1 0 +0 10851 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1453 +0 3 +cfn=(722) +calls=1 0 +0 97 +0 16 +cfn=(804) +calls=1 0 +0 638 +0 3 +cfn=(722) +calls=1 0 +0 97 +0 14 +cfn=(804) +calls=1 0 +0 638 +0 3 +cfn=(722) +calls=1 0 +0 97 +0 14 +cfn=(804) +calls=1 0 +0 638 +0 547 + +fn=(494) +0 5 +cfn=(506) std::locale::_Impl::_Impl(unsigned long) +calls=1 0 +0 63678 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1006 +0 11478 + +fn=(574) std::moneypunct::_M_initialize_moneypunct(__locale_struct*, char const*) +0 112 + +fn=(592) std::messages::messages(unsigned long) +0 11 +cfn=(524) +calls=1 0 +0 7 +0 2 +cfn=(512) +calls=1 0 +0 2 +0 4 + +fn=(648) std::codecvt::codecvt(unsigned long) +0 11 +cfn=(524) +calls=1 0 +0 7 +0 4 + +fn=(666) std::moneypunct::_M_initialize_moneypunct(__locale_struct*, char const*) +0 101 + +fn=(734) +0 6426 +cfn=(492) +calls=714 0 +0 27846 +0 2142 +cfn=(740) std::locale::operator=(std::locale const&) +calls=714 0 +0 13566 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 995 +0 1428 +cfn=(746) +calls=714 0 +0 8568 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 976 +0 2856 + +fn=(752) +0 4970 +cfn=(758) +calls=710 0 +0 84739 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1216 +0 2840 +cfn=(772) +calls=710 0 +0 83780 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1219 +0 2130 +cfn=(778) +calls=710 0 +0 58930 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1580 +0 2840 +cfn=(786) +calls=710 0 +0 58930 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1599 +0 2130 +cfn=(792) bool std::has_facet > > >(std::locale const&) +calls=710 0 +0 58930 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1572 +0 2840 +cfn=(798) std::num_get > > const& std::use_facet > > >(std::locale const&) +calls=710 0 +0 58930 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1615 +0 3550 + +fn=(798) +0 2840 +cfn=(550) +calls=710 0 +0 3550 +0 7810 +cfn=(764) +calls=710 0 +0 41890 +0 2840 + +fn=(880) +0 20969242173 +cob=(4) +cfi=(71) +cfn=(886) malloc +calls=2329915797 3615 +0 222199402928 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1742 +0 13979494782 + +fn=(1260) +0 1626209 +cfn=(1308) +calls=328 0 +0 26896 +0 4072 + +fn=(1332) std::string::append(unsigned long, char) +0 2970 +cfn=(1338) +calls=99 0 +0 19202 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 950 +0 783 +cob=(4) +cfi=(82) /build/buildd/eglibc-2.11.1/string/../sysdeps/x86_64/memset.S +cfn=(986) memset +calls=96 44 +0 1738 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1690 +0 501 + +fn=(1394) std::basic_ostream >& std::__ostream_insert >(std::basic_ostream >&, char const*, long) +0 112 +cfn=(1400) +calls=8 0 +0 168 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1011 +0 256 +cfn=(2694) +calls=6 0 +0 956 +cfn=(1402) +calls=2 0 +0 4248 +0 24 + +fn=(1498) std::ostream::flush() +0 60 +cfn=(1500) __gnu_cxx::stdio_sync_filebuf >::sync() +calls=6 0 +0 2025 +0 42 + +fn=(1500) +0 12 +cob=(4) +cfi=(107) /build/buildd/eglibc-2.11.1/libio/iofflush.c +cfn=(1506) fflush +calls=6 36 +0 324 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1689 + +fn=(1556) +0 99 + +fn=(1606) std::basic_filebuf >::is_open() const +0 15 +cfn=(1556) +calls=5 0 +0 15 +0 10 + +fn=(1624) +0 170 + +fn=(1660) +0 60 +cfn=(1666) +calls=6 0 +0 1736 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1051 +0 24 +cob=(4) +cfi=(106) /build/buildd/eglibc-2.11.1/io/../sysdeps/unix/syscall-template.S +cfn=(1678) read +calls=6 82 +0 42 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1649 +0 60 + +fn=(1666) +0 14 +cob=(4) +cfi=(111) /build/buildd/eglibc-2.11.1/libio/fileno.c +cfn=(1672) fileno +calls=7 37 +0 49 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1682 + +fn=(1778) void std::__convert_to_v(char const*, double&, std::_Ios_Iostate&, __locale_struct* const&) +0 2530 +cob=(4) +cfi=(112) /build/buildd/eglibc-2.11.1/stdlib/strtod_l.c +cfn=(1784) strtod_l +calls=253 1601 +0 155848 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1788 +0 4048 + +fn=(2006) std::string::rfind(char, unsigned long) const +0 154 + +fn=(2414) std::string::compare(std::string const&) const +0 1494615164 + +fn=(2524) std::istreambuf_iterator > std::num_get > >::_M_extract_int(std::istreambuf_iterator >, std::istreambuf_iterator >, std::ios_base&, std::_Ios_Iostate&, unsigned long&) const +0 16 +cfn=(1456) +calls=1 0 +0 28 +0 352 +cfn=(1798) +calls=1 0 +0 16 +0 5 + +fn=(2812) std::_Rb_tree_decrement(std::_Rb_tree_node_base const*) +0 897 +cfn=(2818) std::_Rb_tree_decrement(std::_Rb_tree_node_base*) +calls=897 0 +0 13461 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1313 + +fn=(2824) std::_Rb_tree_increment(std::_Rb_tree_node_base const*) +0 1258072 +cfn=(2830) +calls=1258072 0 +0 17296325 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1247 + +fn=(3218) std::_Rb_tree_rebalance_for_erase(std::_Rb_tree_node_base*, std::_Rb_tree_node_base&) +0 259 + +fn=(3244) std::istream::read(char*, long) +0 636 +cfn=(1644) +calls=53 0 +0 1696 +0 795 +cfn=(3246) std::basic_filebuf >::xsgetn(char*, long) +calls=53 0 +0 6866 +0 159 + +fn=(3254) std::basic_streambuf >::uflow() +0 4 +cfn=(1652) +calls=1 0 +0 115 +0 8 + +fn=(3628) std::__num_base::_S_format_float(std::ios_base const&, char*, char) +0 27 + +fn=(3794) std::basic_ostream >::flush() +0 30 +cfn=(3796) __gnu_cxx::stdio_sync_filebuf >::sync() +calls=3 0 +0 168 +0 21 + +fn=(506) +0 217 +cfn=(512) +calls=1 0 +0 2 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1179 +0 56 +cfn=(518) +calls=1 0 +0 4501 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1014 +0 4 +cfn=(544) +calls=1 0 +0 1277 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1354 +0 3 +cfn=(556) std::codecvt::codecvt(unsigned long) +calls=1 0 +0 22 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1130 +0 4 +cfn=(544) +calls=1 0 +0 253 +0 23 +cfn=(562) +calls=1 0 +0 410 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1356 +0 5 +cfn=(544) +calls=1 0 +0 253 +0 8 +cfn=(544) +calls=1 0 +0 253 +0 8 +cfn=(544) +calls=1 0 +0 253 +0 5 +cfn=(524) +calls=1 0 +0 7 +0 5 +cfn=(544) +calls=1 0 +0 253 +0 35 +cfn=(568) +calls=1 0 +0 112 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1464 +0 5 +cfn=(544) +calls=1 0 +0 253 +0 35 +cfn=(574) +calls=1 0 +0 112 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1464 +0 5 +cfn=(544) +calls=1 0 +0 253 +0 8 +cfn=(544) +calls=1 0 +0 253 +0 8 +cfn=(544) +calls=1 0 +0 253 +0 56 +cfn=(580) std::__timepunct::__timepunct(std::__timepunct_cache*, unsigned long) +calls=1 0 +0 1537 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1273 +0 5 +cfn=(544) +calls=1 0 +0 253 +0 8 +cfn=(544) +calls=1 0 +0 253 +0 8 +cfn=(544) +calls=1 0 +0 253 +0 3 +cfn=(592) +calls=1 0 +0 26 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1020 +0 4 +cfn=(544) +calls=1 0 +0 253 +0 3 +cfn=(598) std::ctype::ctype(unsigned long) +calls=1 0 +0 25829 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 978 +0 4 +cfn=(544) +calls=1 0 +0 253 +0 3 +cfn=(648) +calls=1 0 +0 22 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1190 +0 4 +cfn=(544) +calls=1 0 +0 253 +0 23 +cfn=(654) +calls=1 0 +0 345 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1372 +0 4 +cfn=(544) +calls=1 0 +0 253 +0 8 +cfn=(544) +calls=1 0 +0 253 +0 8 +cfn=(544) +calls=1 0 +0 253 +0 5 +cfn=(524) +calls=1 0 +0 7 +0 5 +cfn=(544) +calls=1 0 +0 253 +0 35 +cfn=(660) std::moneypunct::_M_initialize_moneypunct(__locale_struct*, char const*) +calls=1 0 +0 101 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1464 +0 4 +cfn=(544) +calls=1 0 +0 253 +0 35 +cfn=(666) +calls=1 0 +0 101 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1472 +0 4 +cfn=(544) +calls=1 0 +0 253 +0 8 +cfn=(544) +calls=1 0 +0 253 +0 8 +cfn=(544) +calls=1 0 +0 253 +0 56 +cfn=(672) +calls=1 0 +0 1543 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1291 +0 4 +cfn=(544) +calls=1 0 +0 253 +0 8 +cfn=(544) +calls=1 0 +0 253 +0 8 +cfn=(544) +calls=1 0 +0 253 +0 3 +cfn=(684) std::messages::messages(unsigned long) +calls=1 0 +0 26 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 996 +0 4 +cfn=(544) +calls=1 0 +0 253 +0 3 +cfn=(550) +calls=1 0 +0 5 +0 5 +cfn=(550) +calls=1 0 +0 5 +0 5 +cfn=(550) +calls=1 0 +0 5 +0 5 +cfn=(550) +calls=1 0 +0 5 +0 5 +cfn=(550) +calls=1 0 +0 5 +0 5 +cfn=(550) +calls=1 0 +0 5 +0 5 +cfn=(550) +calls=1 0 +0 5 +0 5 +cfn=(550) +calls=1 0 +0 5 +0 10 + +fn=(598) +0 11 +cfn=(524) +calls=1 0 +0 7 +0 4 +cfn=(604) std::ctype::_M_initialize_ctype() +calls=1 0 +0 24637 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1167 +0 3 + +fn=(660) +0 101 + +fn=(766) +0 73996 + +fn=(804) +0 24 +cfn=(734) +calls=4 0 +0 352 +0 12 +cfn=(810) std::basic_ios >::_M_cache_locale(std::locale const&) +calls=4 0 +0 10877 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1448 +0 52 + +fn=(816) bool std::has_facet >(std::locale const&) +0 16 +cfn=(550) +calls=4 0 +0 20 +0 44 +cfn=(764) +calls=4 0 +0 236 +0 16 + +fn=(846) std::num_get > > const& std::use_facet > > >(std::locale const&) +0 16 +cfn=(550) +calls=4 0 +0 20 +0 44 +cfn=(764) +calls=4 0 +0 236 +0 16 + +fn=(1400) +0 420 + +fn=(1402) +0 20 +cob=(4) +cfi=(98) /build/buildd/eglibc-2.11.1/libio/iofwrite.c +cfn=(1408) fwrite +calls=4 37 +0 3008 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1725 + +fn=(1442) std::ctype::_M_widen_init() const +0 1041 +cfn=(1444) std::ctype::do_widen(char const*, char const*, char*) const +calls=1 0 +0 121 +0 270 + +fn=(1456) +0 4779 +cfn=(550) +calls=531 0 +0 2655 +0 7434 + +fn=(1462) +0 376 + +fn=(1526) std::basic_filebuf >::basic_filebuf() +0 85 +cfn=(492) +calls=5 0 +0 195 +0 55 +cfn=(1532) +calls=5 0 +0 15 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1219 +0 100 +cfn=(1538) +calls=5 0 +0 415 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1302 +0 20 +cfn=(1544) std::codecvt const& std::use_facet >(std::locale const&) +calls=5 0 +0 415 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1337 +0 25 + +fn=(1544) +0 20 +cfn=(550) +calls=5 0 +0 25 +0 55 +cfn=(764) +calls=5 0 +0 295 +0 20 + +fn=(1618) +0 10 +cfn=(880) +calls=5 0 +0 2719 +0 10 + +fn=(1638) std::basic_istream >& std::getline, std::allocator >(std::basic_istream >&, std::basic_string, std::allocator >&, char) +0 2715 +cfn=(1644) +calls=181 0 +0 5792 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 994 +0 579 +cfn=(1630) +calls=6 0 +0 48 +0 2715 +cfn=(1650) +calls=181 0 +0 8747 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 978 +0 6164 +cob=(4) +cfi=(89) +cfn=(1248) +calls=175 25 +0 7095 +0 1575 +cfn=(1686) +calls=175 0 +0 50836 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 994 +0 2812 +cfn=(1692) +calls=175 0 +0 1225 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1283 +0 377 +cfn=(1798) +calls=5 0 +0 80 +cfn=(1652) +calls=4 0 +0 5956 +0 66 + +fn=(1708) std::basic_string, std::allocator >::basic_string(std::string const&, unsigned long, unsigned long) +0 21199 +cfn=(1710) +calls=1247 0 +0 246202 +0 4988 + +fn=(1798) +0 2752 +cfn=(1804) std::basic_stringbuf, std::allocator >::_M_update_egptr() +calls=344 0 +0 1720 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1434 +0 1032 + +fn=(1818) +0 2824 +cfn=(1824) +calls=353 0 +0 4236 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1226 +0 706 +cfn=(1830) std::ios_base::_M_dispose_callbacks() +calls=353 0 +0 5648 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1164 +0 2824 +cfn=(746) +calls=353 0 +0 4236 + +fn=(2138) std::string::compare(char const*) const +0 10488 +cob=(4) +cfi=(69) +cfn=(642) +calls=1311 26 +0 23544 +0 27652 + +fn=(2220) std::string::resize(unsigned long, char) +0 1152 +cfn=(1332) +calls=96 0 +0 24977 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 958 + +fn=(2314) +0 5957 +cfn=(1338) +calls=259 0 +0 46736 +0 2849 +cfn=(1772) +calls=259 0 +0 136644 +0 1813 +cfn=(524) +calls=259 0 +0 1813 +0 1554 +cfn=(2320) void std::__convert_to_v(char const*, float&, std::_Ios_Iostate&, __locale_struct* const&) +calls=259 0 +0 163547 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1443 +0 9065 +cfn=(1308) +calls=259 0 +0 21238 +0 1295 + +fn=(2448) std::string::_M_replace_safe(unsigned long, unsigned long, char const*, unsigned long) +0 66 +cfn=(1650) +calls=6 0 +0 1254 +0 96 +cob=(4) +cfi=(81) +cfn=(966) +calls=6 56 +0 144 +0 6 + +fn=(2516) std::istream& std::istream::_M_extract(unsigned long&) +0 9 +cfn=(1644) +calls=1 0 +0 65 +0 23 +cfn=(2518) std::num_get > >::do_get(std::istreambuf_iterator >, std::istreambuf_iterator >, std::ios_base&, std::_Ios_Iostate&, unsigned long&) const +calls=1 0 +0 2350 +0 12 +cfn=(1630) +calls=1 0 +0 8 +0 5 + +fn=(2542) std::basic_istringstream, std::allocator >::~basic_istringstream() +0 22 +cfn=(746) +calls=1 0 +0 12 +0 12 +cfn=(1818) +calls=1 0 +0 58 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 994 +0 10 +cfn=(1308) +calls=1 0 +0 82 +0 5 + +fn=(3098) std::basic_ifstream >::basic_ifstream() +0 20 +cfn=(722) +calls=2 0 +0 194 +0 44 +cfn=(728) +calls=2 0 +0 1416 +0 16 +cfn=(1526) +calls=2 0 +0 530 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1228 +0 6 +cfn=(728) +calls=2 0 +0 1416 +0 14 + +fn=(3150) std::istream::seekg(std::fpos<__mbstate_t>) +0 20 +cfn=(3152) +calls=1 0 +0 4619 +0 8 + +fn=(3252) std::basic_streambuf >::xsgetn(char*, long) +0 962 +cfn=(3254) +calls=1 0 +0 127 +0 908 +cob=(4) +cfi=(81) +cfn=(966) +calls=53 56 +0 1440 +0 265 + +fn=(3680) std::ios_base::Init::~Init() +0 756 +cfn=(1498) +calls=1 0 +0 73 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 958 +0 2 +cfn=(1498) +calls=1 0 +0 73 +0 2 +cfn=(1498) +calls=1 0 +0 73 +0 2 +cfn=(3794) +calls=1 0 +0 73 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1264 +0 2 +cfn=(3794) +calls=1 0 +0 73 +0 2 +cfn=(3794) +calls=1 0 +0 73 +0 542 + +fn=(3876) 0x0000000000072380 +0 4 + +fn=(294) +0 1 + +fn=(322) +0 49 + +fn=(370) +0 1 + +fn=(372) +0 57 + +fn=(556) +0 11 +cfn=(524) +calls=1 0 +0 7 +0 4 + +fn=(586) std::__timepunct::_M_initialize_timepunct(__locale_struct*) +0 10 +cfn=(524) +calls=1 0 +0 7 +0 97 + +fn=(696) +0 24 + +fn=(740) +0 13566 + +fn=(834) std::num_put > > const& std::use_facet > > >(std::locale const&) +0 16 +cfn=(550) +calls=4 0 +0 20 +0 44 +cfn=(764) +calls=4 0 +0 236 +0 16 + +fn=(1308) +0 571019610 +cfn=(1142) +calls=571019610 0 +0 46252589218 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 870 + +fn=(1448) std::num_put > >::do_put(std::ostreambuf_iterator >, std::ios_base&, char, unsigned long) const +0 10 +cfn=(1454) +calls=2 0 +0 1196 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1724 +0 8 + +fn=(1550) std::basic_filebuf >::open(char const*, std::_Ios_Openmode) +0 55 +cfn=(1556) +calls=5 0 +0 15 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1163 +0 65 +cfn=(1562) +calls=5 0 +0 5624 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1249 +0 10 +cfn=(1606) +calls=5 0 +0 40 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1317 +0 20 +cfn=(1612) +calls=5 0 +0 3676 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1481 +0 30 +cfn=(1624) +calls=5 0 +0 75 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1395 +0 35 + +fn=(1654) +0 12 + +fn=(1830) +0 5648 + +fn=(1880) +0 56 +cfn=(1556) +calls=7 0 +0 21 +0 68 +cfn=(1886) +calls=5 0 +0 150 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1391 +0 30 +cfn=(1892) +calls=5 0 +0 2341 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1446 +0 70 +cfn=(1904) +calls=5 0 +0 6679 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1110 +0 20 + +fn=(2442) std::string::assign(char const*, unsigned long) +0 126 +cfn=(2448) +calls=6 0 +0 1566 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1076 + +fn=(2726) std::ostream& std::ostream::_M_insert(void const*) +0 13 +cfn=(1400) +calls=1 0 +0 21 +0 21 +cfn=(2728) +calls=1 0 +0 836 +0 32 + +fn=(3246) +0 1325 +cfn=(3252) +calls=53 0 +0 3702 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1309 +0 530 + +fn=(550) +0 24572 + +fn=(604) +0 10 +cob=(4) +cfi=(62) /build/buildd/eglibc-2.11.1/locale/uselocale.c +cfn=(610) uselocale +calls=1 32 +0 21 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1748 +0 898 +cob=(4) +cfi=(63) /build/buildd/eglibc-2.11.1/wcsmbs/wctob.c +cfn=(616) wctob +calls=128 33 +0 2432 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1674 +0 260 +cob=(4) +cfi=(64) /build/buildd/eglibc-2.11.1/wcsmbs/btowc.c +cfn=(622) btowc +calls=1 35 +0 20 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1683 +0 510 +cob=(4) +cfi=(64) +cfn=(622) +calls=255 35 +0 9196 +0 1091 +cfn=(634) +calls=8 0 +0 3013 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1150 +0 16 +cfn=(634) +calls=4 0 +0 793 +0 99 +cob=(4) +cfi=(62) +cfn=(610) +calls=1 32 +0 21 +0 2 + +fn=(684) +0 11 +cfn=(524) +calls=1 0 +0 7 +0 2 +cfn=(512) +calls=1 0 +0 2 +0 4 + +fn=(772) +0 2852 +cfn=(550) +calls=713 0 +0 3565 +0 7843 +cfn=(764) +calls=713 0 +0 67022 +0 2852 + +fn=(1326) std::string::_M_leak_hard() +0 3156 + +fn=(1436) std::ostream& std::ostream::_M_insert(unsigned long) +0 26 +cfn=(1400) +calls=2 0 +0 42 +0 42 +cfn=(1448) +calls=2 0 +0 2938 +0 65 +cfn=(1442) +calls=1 0 +0 1432 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1117 +0 4 +cfn=(1446) +calls=1 0 +0 2 +0 1 + +fn=(1444) +0 5 +cob=(4) +cfi=(81) +cfn=(966) +calls=1 56 +0 113 +0 3 + +fn=(1476) +0 24 +cob=(4) +cfi=(105) /build/buildd/eglibc-2.11.1/libio/putc.c +cfn=(1482) putc +calls=3 29 +0 543 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1665 + +fn=(1564) +0 50 + +fn=(1732) std::string::find_last_not_of(char const*, unsigned long, unsigned long) const +0 5621 +cob=(4) +cfi=(89) +cfn=(1248) +calls=1 25 +0 22 +0 1404 +cob=(4) +cfi=(89) +cfn=(1248) +calls=351 25 +0 8069 +0 3164 + +fn=(1764) std::istream& std::istream::_M_extract(double&) +0 2826 +cfn=(1644) +calls=314 0 +0 17085 +0 5941 +cfn=(1766) std::num_get > >::do_get(std::istreambuf_iterator >, std::istreambuf_iterator >, std::ios_base&, std::_Ios_Iostate&, double&) const +calls=253 0 +0 395031 +0 3341 +cfn=(1630) +calls=70 0 +0 560 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1346 +0 350 + +fn=(1844) +0 5404 + +fn=(1940) +0 5 +cfn=(1904) +calls=5 0 +0 80 + +fn=(2818) +0 15481 + +fn=(3188) std::istream::get(char*, long, char) +0 15 +cfn=(1644) +calls=1 0 +0 32 +0 814 +cfn=(1652) +calls=1 0 +0 115 +0 2 + +fn=(3616) +0 6 +cfn=(3622) std::ostreambuf_iterator > std::num_put > >::_M_insert_float(std::ostreambuf_iterator >, std::ios_base&, char, char, double) const +calls=1 0 +0 6538 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1759 +0 4 + +fn=(3622) +0 26 +cfn=(1456) +calls=1 0 +0 28 +0 9 +cfn=(3628) +calls=1 0 +0 27 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1359 +0 3 +cfn=(524) +calls=1 0 +0 7 +0 10 +cfn=(3630) 0x0000000000089420 +calls=1 0 +0 4570 +0 5 +cfn=(772) +calls=1 0 +0 118 +0 17 +cob=(4) +cfi=(89) +cfn=(1248) +calls=1 25 +0 25 +0 27 +cfn=(1402) +calls=1 0 +0 258 +0 21 +cob=(4) +cfi=(81) +cfn=(966) +calls=1 56 +0 27 +0 1 + +fn=(3630) +0 19 +cob=(4) +cfi=(62) +cfn=(610) +calls=1 32 +0 21 +0 12 +cob=(4) +cfi=(139) /build/buildd/eglibc-2.11.1/libio/vsnprintf.c +cfn=(3640) vsnprintf +calls=1 101 +0 2758 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1729 +0 3 +cob=(4) +cfi=(62) +cfn=(610) +calls=1 32 +0 21 +0 7 + +fn=(3796) +0 6 +cob=(4) +cfi=(107) +cfn=(1506) +calls=3 36 +0 162 + +fn=(3864) 0x000000000005a4c0 +0 10 +cob=(4) +cfi=(153) +cfn=(3726) +calls=1 31 +0 473 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1810 +0 13 + +fn=(3874) 0x0000000000072390 +0 4 + +fn=(2692) +0 110 +cfn=(1456) +calls=5 0 +0 140 +0 125 +cfn=(1462) +calls=5 0 +0 153 +0 140 +cfn=(2694) +calls=5 0 +0 3200 +0 85 + +fn=(580) +0 13 +cfn=(512) +calls=1 0 +0 2 +0 4 +cfn=(586) +calls=1 0 +0 114 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1401 +0 3 + +fn=(678) +0 9 +cfn=(524) +calls=1 0 +0 7 +0 96 + +fn=(792) +0 2840 +cfn=(550) +calls=710 0 +0 3550 +0 7810 +cfn=(764) +calls=710 0 +0 41890 +0 2840 + +fn=(810) +0 28 +cfn=(816) +calls=4 0 +0 332 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1166 +0 16 +cfn=(822) +calls=4 0 +0 332 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1193 +0 12 +cfn=(828) +calls=4 0 +0 332 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1580 +0 16 +cfn=(834) +calls=4 0 +0 332 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1631 +0 12 +cfn=(840) +calls=4 0 +0 332 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1572 +0 16 +cfn=(846) +calls=4 0 +0 332 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1623 +0 20 + +fn=(934) std::basic_string, std::allocator >::basic_string(char const*, std::allocator const&) +0 6868771140 +cob=(4) +cfi=(69) +cfn=(642) +calls=572397595 26 +0 9158423470 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1690 +0 2861987975 +cfn=(942) +calls=572397595 0 +0 105537063253 +0 3434385570 + +fn=(1380) std::basic_string, std::allocator >::~basic_string() +0 20024140331 +cfn=(1308) +calls=571017252 0 +0 46823414711 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1077 +0 7437212116 + +fn=(1726) std::string::find_first_not_of(char const*, unsigned long, unsigned long) const +0 7082 +cob=(4) +cfi=(89) +cfn=(1248) +calls=445 25 +0 10148 +0 3355 + +fn=(1766) +0 5819 +cfn=(1338) +calls=253 0 +0 45900 +0 2783 +cfn=(1772) +calls=253 0 +0 136637 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1951 +0 1771 +cfn=(524) +calls=253 0 +0 1771 +0 1518 +cfn=(1778) +calls=253 0 +0 164214 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1435 +0 9221 +cfn=(1308) +calls=253 0 +0 20746 +0 1265 + +fn=(1804) +0 1720 + +fn=(2320) +0 2590 +cob=(4) +cfi=(112) +cfn=(2326) strtof_l +calls=259 1601 +0 155302 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1770 +0 3885 + +fn=(2402) std::_Rb_tree_insert_and_rebalance(bool, std::_Rb_tree_node_base*, std::_Rb_tree_node_base*, std::_Rb_tree_node_base&) +0 15140729663 +cfn=(2420) +calls=217 0 +0 3491 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1327 +0 510 +cfn=(2420) +calls=102 0 +0 1637 +0 7471 +cfn=(3444) +calls=219 0 +0 3557 +0 1325 +cfn=(3444) +calls=265 0 +0 4337 +0 1274 +cfn=(3444) +calls=102 0 +0 1742 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1336 +0 2246538262 +cfn=(2420) +calls=265 0 +0 4534 +0 530 + +fn=(2518) +0 10 +cfn=(2524) +calls=1 0 +0 417 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1921 +0 2 + +fn=(2702) +0 44 + +ob=(2) +fl=(13) +fn=(224) +0 2 +cob=(5) /lib/libgcc_s.so.1 +cfi=(51) ??? +cfn=(226) 0x0000000000002d80 +calls=1 0 +0 6 +0 1 +cob=(5) +cfi=(51) +cfn=(232) 0x0000000000002e20 +calls=1 0 +0 6 +0 1 +cob=(5) +cfi=(51) +cfn=(238) 0x0000000000013390 +calls=1 0 +0 11 +0 2 + +fn=(440) +0 2 +cob=(10) +cfi=(59) +cfn=(442) +calls=1 0 +0 6 +0 1 +cob=(10) +cfi=(59) +cfn=(448) +calls=1 0 +0 6 +0 1 +cob=(10) +cfi=(59) +cfn=(454) +calls=1 0 +0 11 +0 2 + +fn=(3884) +0 2 +cob=(6) /lib/libm-2.11.1.so +cfi=(52) ??? +cfn=(3886) 0x0000000000003f10 +calls=1 0 +0 2263 +0 2 + +fn=(3804) +0 2 +cob=(10) +cfi=(59) +cfn=(3806) +calls=1 0 +0 2263 +0 2 + +fn=(3862) +0 2 +cob=(7) +cfi=(53) +cfn=(3864) +calls=1 0 +0 2306 +0 2 + +fn=(244) +0 2 +cob=(6) +cfi=(52) +cfn=(246) 0x0000000000003ef0 +calls=1 0 +0 6 +0 1 +cob=(6) +cfi=(52) +cfn=(252) 0x0000000000003f90 +calls=1 0 +0 6 +0 1 +cob=(6) +cfi=(52) +cfn=(258) 0x00000000000447c0 +calls=1 0 +0 11 +0 2 + +fn=(460) +0 2 +cob=(11) /home/tclose/Code/MRtrix3/lib/libmrtrix-0_3_4.so +cfi=(60) ??? +cfn=(462) 0x0000000000013ce0 +calls=1 0 +0 6 +0 1 +cob=(11) +cfi=(60) +cfn=(468) 0x0000000000013d80 +calls=1 0 +0 6 +0 1 +cob=(11) +cfi=(60) +cfn=(474) 0x000000000007c330 +calls=1 0 +0 189529 +0 2 + +fn=(3736) +0 2 +cob=(11) +cfi=(60) +cfn=(3738) 0x0000000000013d00 +calls=1 0 +0 10833 +0 2 + +fn=(3904) +0 2 +cob=(5) +cfi=(51) +cfn=(3906) 0x0000000000002da0 +calls=1 0 +0 2263 +0 2 + +fn=(264) +0 2 +cob=(7) +cfi=(53) +cfn=(266) +calls=1 0 +0 6 +0 1 +cob=(7) +cfi=(53) +cfn=(272) +calls=1 0 +0 6 +0 1 +cob=(7) +cfi=(53) +cfn=(278) +calls=1 0 +0 2196 + +ob=(8) /usr/lib/libgslcblas.so.0.0.0 +fl=(57) ??? +fn=(402) 0x00000000000024d0 +0 6 + +fn=(414) 0x0000000000036cb0 +0 11 + +fn=(2918) cblas_dnrm2 +0 13176 + +fn=(2936) cblas_dtrmv +0 37210 + +fn=(2970) cblas_dgemv +0 256444 + +fn=(2892) cblas_dgemm +0 1037 + +ob=(2) +fl=(13) +fn=(264) +0 2 + +fn=(3824) +0 2 +cob=(9) /usr/lib/libgsl.so.0.14.0 +cfi=(58) ??? +cfn=(3826) 0x000000000004aba0 +calls=1 0 +0 2263 +0 2 + +fn=(176) +0 2 +cob=(3) /usr/lib/valgrind/vgpreload_core-amd64-linux.so +cfi=(39) ??? +cfn=(178) 0x0000000000000510 +calls=1 0 +0 6 +0 1 +cob=(3) +cfi=(39) +cfn=(184) 0x00000000000005b0 +calls=1 0 +0 6 +0 1 +cob=(3) +cfi=(39) +cfn=(190) 0x0000000000000710 +calls=1 0 +0 11 +0 2 + +ob=(8) +fl=(57) +fn=(2892) +0 1268556 + +fn=(2944) cblas_dscal +0 6466 + +fn=(2910) cblas_ddot +0 47580 + +fn=(408) 0x0000000000002570 +0 6 + +fn=(2956) cblas_dsymm +0 94123 + +ob=(2) +fl=(13) +fn=(400) +0 2 +cob=(8) +cfi=(57) +cfn=(402) +calls=1 0 +0 6 +0 1 +cob=(8) +cfi=(57) +cfn=(408) +calls=1 0 +0 6 +0 1 +cob=(8) +cfi=(57) +cfn=(414) +calls=1 0 +0 11 +0 2 + +fn=(3712) +0 2 +cob=(3) +cfi=(39) +cfn=(3714) 0x0000000000000530 +calls=1 0 +0 1542 +0 2 + +fn=(420) +0 2 +cob=(9) +cfi=(58) +cfn=(422) 0x000000000004ab80 +calls=1 0 +0 6 +0 1 +cob=(9) +cfi=(58) +cfn=(428) 0x000000000004ac20 +calls=1 0 +0 6 +0 1 +cob=(9) +cfi=(58) +cfn=(434) 0x00000000001b6ea0 +calls=1 0 +0 11 +0 2 + +fn=(3842) +0 2 +cob=(8) +cfi=(57) +cfn=(3844) 0x00000000000024f0 +calls=1 0 +0 2263 + +ob=(8) +fl=(57) +fn=(2956) +0 1520242 + +fn=(3844) +0 6 + +ob=(2) +fl=(13) +fn=(3842) +0 2 + +fn=(1052) 0x000000000040d710 +0 2 +cob=(12) +cfi=(84) +cfn=(1054) 0x000000000040e38c +calls=1 0 +0 6 +0 1 +cob=(12) +cfi=(84) +cfn=(1060) 0x000000000040e420 +calls=1 0 +0 6 +0 1 +cob=(12) +cfi=(84) +cfn=(1066) 0x00000000004d8fa0 +calls=1 0 +0 217013 +0 2 + +fn=(3702) +0 2 +cob=(12) +cfi=(84) +cfn=(3704) 0x000000000040e3b0 +calls=1 0 +0 18 +0 2 + +ob=(8) +fl=(57) +fn=(3844) +0 4 +cob=(4) +cfi=(153) +cfn=(3726) +calls=1 31 +0 430 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1810 +0 13 + +ob=(3) +fl=(39) +fn=(184) +0 6 + +fn=(178) +0 6 + +fn=(190) +0 11 + +fn=(3714) +0 10 +cob=(4) +cfi=(153) +cfn=(3726) +calls=1 31 +0 430 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1089 + +ob=(5) +fl=(51) +fn=(232) +0 6 + +fn=(226) +0 6 + +fn=(238) +0 11 + +fn=(3906) +0 10 +cob=(4) +cfi=(153) +cfn=(3726) +calls=1 31 +0 430 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1810 +0 13 + +ob=(3) +fl=(39) +fn=(3714) +0 13 + +ob=(11) +fl=(60) +fn=(858) global constructors keyed to quick_scan.cpp +0 3 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 + +fn=(862) global constructors keyed to dict.cpp +0 5 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 78 +cob=(6) +cfi=(70) /build/buildd/eglibc-2.11.1/math/../sysdeps/ieee754/flt-32/s_ceilf.c +cfn=(868) ceilf +calls=1 39 +0 15 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1414 +0 8 +cfn=(874) std::tr1::_Hashtable, std::allocator >, std::_Select1st >, std::equal_to, std::tr1::hash, std::tr1::__detail::_Mod_range_hashing, std::tr1::__detail::_Default_ranged_hash, std::tr1::__detail::_Prime_rehash_policy, false, false, true>::_M_allocate_buckets(unsigned long) +calls=1 0 +0 63871 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 2458 +0 8 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 + +fn=(926) global constructors keyed to mri.cpp +0 3 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 + +fn=(1000) global constructors keyed to patient.cpp +0 3 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 + +fn=(1020) global constructors keyed to mosaic.cpp +0 3 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 + +fn=(2028) std::vector >::_M_insert_aux(__gnu_cxx::__normal_iterator > >, MR::Image::NameParserItem const&) +0 48 +cfn=(2034) std::vector >::_M_check_len(unsigned long, char const*) const +calls=2 0 +0 40 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1154 +0 16 +cfn=(2040) std::_Vector_base >::_M_allocate(unsigned long) +calls=2 0 +0 298 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1172 +0 20 +cfn=(2046) MR::Image::NameParserItem::NameParserItem(MR::Image::NameParserItem const&) +calls=2 0 +0 1874 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 874 +0 12 +cfn=(2056) MR::Image::NameParserItem* std::__uninitialized_move_a >(MR::Image::NameParserItem*, MR::Image::NameParserItem*, MR::Image::NameParserItem*, std::allocator&) +calls=2 0 +0 42 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1297 +0 12 +cfn=(2056) +calls=2 0 +0 42 +0 28 + +fn=(2062) MR::Image::NameParserItem::~NameParserItem() +0 16 +cob=(7) +cfi=(53) +cfn=(1380) +calls=2 0 +0 30 + +fn=(2108) void std::__final_insertion_sort<__gnu_cxx::__normal_iterator*, std::vector, std::allocator > > > >(__gnu_cxx::__normal_iterator*, std::vector, std::allocator > > >, __gnu_cxx::__normal_iterator*, std::vector, std::allocator > > >) +0 22 +cfn=(2114) void std::__insertion_sort<__gnu_cxx::__normal_iterator*, std::vector, std::allocator > > > >(__gnu_cxx::__normal_iterator*, std::vector, std::allocator > > >, __gnu_cxx::__normal_iterator*, std::vector, std::allocator > > >) +calls=2 0 +0 44 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1676 +0 12 + +fn=(2202) MR::File::KeyValue::next() +0 3654 +cob=(7) +cfi=(53) +cfn=(1638) +calls=97 0 +0 48451 +0 970 +cob=(7) +cfi=(53) +cfn=(1702) +calls=97 0 +0 5341 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1500 +0 485 +cob=(7) +cfi=(53) +cfn=(1708) +calls=97 0 +0 23920 +0 485 +cob=(7) +cfi=(53) +cfn=(1726) +calls=97 0 +0 4789 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1722 +0 776 +cob=(7) +cfi=(53) +cfn=(1732) +calls=97 0 +0 5006 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1690 +0 873 +cob=(7) +cfi=(53) +cfn=(1708) +calls=97 0 +0 23950 +0 291 +cob=(7) +cfi=(53) +cfn=(1260) +calls=97 0 +0 11931 +0 1067 +cob=(7) +cfi=(53) +cfn=(2138) +calls=97 0 +0 4288 +0 954 +cob=(7) +cfi=(53) +cfn=(1702) +calls=95 0 +0 4472 +0 760 +cob=(7) +cfi=(53) +cfn=(1708) +calls=95 0 +0 19620 +0 475 +cob=(7) +cfi=(53) +cfn=(1726) +calls=95 0 +0 4691 +0 760 +cob=(7) +cfi=(53) +cfn=(1732) +calls=95 0 +0 5141 +0 1140 +cob=(7) +cfi=(53) +cfn=(1708) +calls=95 0 +0 20206 +0 285 +cob=(7) +cfi=(53) +cfn=(1260) +calls=95 0 +0 11495 +0 1520 +cob=(7) +cfi=(53) +cfn=(1708) +calls=95 0 +0 22903 +0 475 +cob=(7) +cfi=(53) +cfn=(1726) +calls=95 0 +0 7920 +0 755 +cob=(7) +cfi=(53) +cfn=(1732) +calls=94 0 +0 4818 +0 1034 +cob=(7) +cfi=(53) +cfn=(1708) +calls=94 0 +0 23484 +0 285 +cob=(7) +cfi=(53) +cfn=(1260) +calls=95 0 +0 9394 +0 1052 +cob=(12) +cfi=(84) +cfn=(1962) std::basic_string, std::allocator > std::operator+, std::allocator >(char const*, std::basic_string, std::allocator > const&) +calls=1 0 +0 381 +0 3 +cob=(7) +cfi=(53) +cfn=(1254) +calls=1 0 +0 20 +0 4 +cob=(7) +cfi=(53) +cfn=(1686) +calls=1 0 +0 371 +0 6 +cob=(12) +cfi=(84) +cfn=(1350) std::basic_string, std::allocator > std::operator+, std::allocator >(std::basic_string, std::allocator > const&, std::basic_string, std::allocator > const&) +calls=1 0 +0 421 +0 4 +cob=(7) +cfi=(53) +cfn=(1254) +calls=1 0 +0 20 +0 4 +cob=(7) +cfi=(53) +cfn=(1686) +calls=1 0 +0 387 +0 2 +cfn=(1980) MR::cmdline_info(std::string const&) +calls=1 0 +0 7 +0 1766 +cob=(7) +cfi=(53) +cfn=(1326) +calls=97 0 +0 1164 +0 1828 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 57 +0 9 +cob=(7) +cfi=(53) +cfn=(1630) +calls=2 0 +0 16 +0 586 +cob=(7) +cfi=(53) +cfn=(1308) +calls=97 0 +0 7954 +0 491 +cob=(7) +cfi=(53) +cfn=(1308) +calls=1 0 +0 82 +0 7 +cob=(7) +cfi=(53) +cfn=(1308) +calls=1 0 +0 126 +0 7 +cob=(7) +cfi=(53) +cfn=(1308) +calls=1 0 +0 82 +0 7 +cob=(7) +cfi=(53) +cfn=(1308) +calls=1 0 +0 82 +0 565 +cob=(7) +cfi=(53) +cfn=(1308) +calls=94 0 +0 7708 +0 664 +cob=(7) +cfi=(53) +cfn=(1308) +calls=95 0 +0 7790 +0 101 +cob=(7) +cfi=(53) +cfn=(1308) +calls=1 0 +0 124 +0 3345 +cob=(7) +cfi=(53) +cfn=(1308) +calls=96 0 +0 7872 +0 968 + +fn=(2240) MR::parse_ints(std::string const&, int) +0 43 +cob=(7) +cfi=(53) +cfn=(2246) +calls=1 0 +0 88 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1634 +0 15 +cob=(7) +cfi=(53) +cfn=(2246) +calls=3 0 +0 266 +0 48 +cob=(7) +cfi=(53) +cfn=(1708) +calls=4 0 +0 804 +0 20 +cob=(7) +cfi=(53) +cfn=(1726) +calls=4 0 +0 196 +0 32 +cob=(7) +cfi=(53) +cfn=(1732) +calls=4 0 +0 204 +0 36 +cob=(7) +cfi=(53) +cfn=(1708) +calls=4 0 +0 891 +0 40 +cob=(7) +cfi=(53) +cfn=(1326) +calls=4 0 +0 48 +0 26 +cob=(4) +cfi=(124) /build/buildd/eglibc-2.11.1/ctype/ctype.c +cfn=(2234) tolower +calls=5 47 +0 60 +0 86 +cob=(7) +cfi=(53) +cfn=(2138) +calls=4 0 +0 176 +0 125 +cob=(7) +cfi=(53) +cfn=(1708) +calls=4 0 +0 748 +0 8 +cob=(7) +cfi=(53) +cfn=(722) +calls=4 0 +0 388 +0 108 +cob=(7) +cfi=(53) +cfn=(728) +calls=4 0 +0 2832 +0 68 +cob=(7) +cfi=(53) +cfn=(492) +calls=4 0 +0 156 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1459 +0 40 +cob=(7) +cfi=(53) +cfn=(1752) +calls=4 0 +0 983 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1514 +0 28 +cob=(7) +cfi=(53) +cfn=(1758) +calls=4 0 +0 84 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 2194 +0 16 +cob=(7) +cfi=(53) +cfn=(728) +calls=4 0 +0 2832 +0 12 +cob=(7) +cfi=(53) +cfn=(2266) +calls=4 0 +0 4625 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1394 +0 76 +cob=(7) +cfi=(53) +cfn=(746) +calls=4 0 +0 48 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1483 +0 44 +cob=(7) +cfi=(53) +cfn=(1818) +calls=4 0 +0 232 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1515 +0 52 +cob=(7) +cfi=(53) +cfn=(1308) +calls=4 0 +0 328 +0 22 +cob=(12) +cfi=(84) +cfn=(2294) std::vector >::_M_insert_aux(__gnu_cxx::__normal_iterator > >, int const&) +calls=3 0 +0 998 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1646 +0 27 +cob=(7) +cfi=(53) +cfn=(1308) +calls=4 0 +0 328 +0 44 +cob=(7) +cfi=(53) +cfn=(1308) +calls=4 0 +0 328 +0 32 +cob=(7) +cfi=(53) +cfn=(1308) +calls=4 0 +0 328 +0 52 + +fn=(2658) std::vector, std::allocator > >::_M_fill_insert(__gnu_cxx::__normal_iterator*, std::vector, std::allocator > > >, unsigned long, MR::RefPtr const&) +0 84 +cob=(7) +cfi=(53) +cfn=(880) +calls=1 0 +0 223 +0 6 + +fn=(3776) MR::Image::Format::NIfTI::~NIfTI() +0 4 + +fn=(3780) MR::Image::Format::MRtrix::~MRtrix() +0 4 + +fn=(478) global constructors keyed to select_cmdline.cpp +0 3 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 102651 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1579 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1778 + +fn=(860) global constructors keyed to mrtrix.cpp +0 3 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 3 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 + +fn=(912) global constructors keyed to data_type.cpp +0 3 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 + +fn=(988) global constructors keyed to progressbar.cpp +0 3 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 + +fn=(1002) global constructors keyed to header.cpp +0 3 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 + +fn=(1022) global constructors keyed to confirm.cpp +0 3 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 + +fn=(1266) MR::App::sort_arguments(int, char**) +0 20 + +fn=(2140) MR::Image::Format::DICOM::read(MR::Image::Header&) const +0 12 +cob=(4) +cfi=(94) /build/buildd/eglibc-2.11.1/io/../sysdeps/unix/sysv/linux/wordsize-64/xstat.c +cfn=(1296) _xstat +calls=1 37 +0 10 +0 15 + +fn=(2348) MR::split(std::string const&, char const*, bool, unsigned long) +0 42 +cob=(4) +cfi=(69) +cfn=(642) +calls=2 26 +0 32 +0 12 +cob=(4) +cfi=(69) +cfn=(642) +calls=6 26 +0 96 +0 40 +cob=(7) +cfi=(53) +cfn=(2246) +calls=8 0 +0 384 +0 80 +cob=(7) +cfi=(53) +cfn=(1708) +calls=8 0 +0 312 +0 32 +cob=(7) +cfi=(53) +cfn=(1254) +calls=2 0 +0 30 +0 150 +cob=(12) +cfi=(84) +cfn=(2358) std::vector >::_M_insert_aux(__gnu_cxx::__normal_iterator > >, std::string const&) +calls=6 0 +0 2036 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1710 +0 6 + +fn=(2426) MR::Image::Axes::Dim::operator=(unsigned long) +0 27 +cob=(7) +cfi=(53) +cfn=(1380) +calls=1 0 +0 7 +0 2 +cob=(7) +cfi=(53) +cfn=(1380) +calls=1 0 +0 7 +0 13 +cob=(4) +cfi=(69) +cfn=(642) +calls=1 26 +0 22 +0 6 +cob=(4) +cfi=(69) +cfn=(642) +calls=2 26 +0 44 +0 12 +cob=(7) +cfi=(53) +cfn=(2442) +calls=3 0 +0 1965 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1534 +0 12 +cob=(4) +cfi=(69) +cfn=(642) +calls=3 26 +0 48 +0 12 +cob=(7) +cfi=(53) +cfn=(2442) +calls=3 0 +0 803 +0 59 +cob=(7) +cfi=(53) +cfn=(1650) +calls=1 0 +0 38 +0 6 +cob=(7) +cfi=(53) +cfn=(1650) +calls=1 0 +0 38 +0 21 +cob=(12) +cfi=(84) +cfn=(2432) std::vector >::_M_fill_insert(__gnu_cxx::__normal_iterator > >, unsigned long, MR::Image::Axes::Axis const&) +calls=1 0 +0 523 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 2086 +0 1 + +fn=(2460) MR::Image::Axes::parse(unsigned long, std::string const&) +0 22 +cob=(7) +cfi=(53) +cfn=(880) +calls=1 0 +0 110 +0 133 +cob=(7) +cfi=(53) +cfn=(1708) +calls=4 0 +0 784 +0 8 +cob=(7) +cfi=(53) +cfn=(722) +calls=4 0 +0 388 +0 84 +cob=(7) +cfi=(53) +cfn=(728) +calls=4 0 +0 2832 +0 64 +cob=(7) +cfi=(53) +cfn=(492) +calls=4 0 +0 156 +0 36 +cob=(7) +cfi=(53) +cfn=(1752) +calls=4 0 +0 748 +0 24 +cob=(7) +cfi=(53) +cfn=(1758) +calls=4 0 +0 84 +0 12 +cob=(7) +cfi=(53) +cfn=(728) +calls=4 0 +0 2832 +0 12 +cob=(7) +cfi=(53) +cfn=(2272) +calls=4 0 +0 1465 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1664 +0 76 +cob=(7) +cfi=(53) +cfn=(746) +calls=4 0 +0 48 +0 44 +cob=(7) +cfi=(53) +cfn=(1818) +calls=4 0 +0 232 +0 112 +cfn=(2470) MR::Image::Axes::check(std::vector > const&, unsigned long) +calls=1 0 +0 139 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 955 +0 37 +cob=(7) +cfi=(53) +cfn=(1308) +calls=4 0 +0 328 +0 48 +cob=(7) +cfi=(53) +cfn=(1308) +calls=4 0 +0 328 +0 20 + +fn=(2640) MR::Image::Handler::Default::execute() +0 55 +cfn=(2646) MR::DataType::bits() const +calls=1 0 +0 22 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 750 +0 5 +cfn=(2646) +calls=1 0 +0 22 +0 19 +cfn=(2652) MR::Image::Handler::Default::map_files() +calls=1 0 +0 33462 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 961 +0 6 + +fn=(914) global constructors keyed to name_parser.cpp +0 3 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 + +fn=(990) global constructors keyed to app.cpp +0 3 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 7 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 66 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 + +fn=(1004) global constructors keyed to image.cpp +0 3 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 + +fn=(1024) global constructors keyed to element.cpp +0 3 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 + +fn=(1980) +0 21 + +fn=(1996) MR::Image::NameParser::parse(std::string const&, unsigned long) +0 28 +cob=(7) +cfi=(53) +cfn=(1260) +calls=2 0 +0 56 +0 10 +cob=(4) +cfi=(94) +cfn=(1296) +calls=2 37 +0 20 +0 38 +cob=(7) +cfi=(53) +cfn=(1242) +calls=2 0 +0 688 +0 14 +cob=(7) +cfi=(53) +cfn=(1260) +calls=2 0 +0 56 +0 4 +cob=(7) +cfi=(53) +cfn=(1380) +calls=2 0 +0 30 +0 10 +cob=(7) +cfi=(53) +cfn=(1242) +calls=2 0 +0 688 +0 22 +cob=(7) +cfi=(53) +cfn=(1708) +calls=2 0 +0 468 +0 52 +cob=(7) +cfi=(53) +cfn=(2006) +calls=2 0 +0 154 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1466 +0 14 +cfn=(2012) MR::Image::NameParser::insert_str(std::string const&) +calls=2 0 +0 12581 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 911 +0 38 +cob=(7) +cfi=(53) +cfn=(1708) +calls=2 0 +0 754 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1434 +0 14 +cob=(7) +cfi=(53) +cfn=(1380) +calls=2 0 +0 30 +0 2 + +fn=(2012) +0 36 +cob=(7) +cfi=(53) +cfn=(1650) +calls=2 0 +0 76 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1506 +0 12 +cob=(7) +cfi=(53) +cfn=(1260) +calls=2 0 +0 56 +0 8 +cfn=(2022) std::vector >::insert(__gnu_cxx::__normal_iterator > >, MR::Image::NameParserItem const&) +calls=2 0 +0 8512 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1477 +0 4 +cfn=(2062) +calls=2 0 +0 46 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 838 +0 10 + +fn=(2074) MR::Image::NameParser::name(std::vector > const&) +0 58 +cob=(7) +cfi=(53) +cfn=(1254) +calls=2 0 +0 40 +0 8 +cfn=(2080) MR::Path::join(std::string const&, std::string const&) +calls=2 0 +0 3848 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 774 +0 4 +cob=(7) +cfi=(53) +cfn=(1380) +calls=2 0 +0 30 +0 2 + +fn=(2080) +0 60 +cob=(7) +cfi=(53) +cfn=(934) +calls=2 0 +0 458 +0 14 +cob=(7) +cfi=(53) +cfn=(1326) +calls=2 0 +0 24 +0 14 +cob=(7) +cfi=(53) +cfn=(1254) +calls=2 0 +0 40 +0 8 +cob=(7) +cfi=(53) +cfn=(1332) +calls=2 0 +0 574 +0 8 +cob=(7) +cfi=(53) +cfn=(1254) +calls=2 0 +0 40 +0 6 +cob=(7) +cfi=(53) +cfn=(1360) +calls=2 0 +0 644 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1548 +0 4 +cob=(7) +cfi=(53) +cfn=(1380) +calls=2 0 +0 200 +0 4 +cob=(7) +cfi=(53) +cfn=(1380) +calls=2 0 +0 200 +0 2 + +fn=(2652) +0 17 +cob=(12) +cfi=(84) +cfn=(1962) +calls=1 0 +0 405 +0 3 +cob=(7) +cfi=(53) +cfn=(1254) +calls=1 0 +0 20 +0 4 +cob=(7) +cfi=(53) +cfn=(1686) +calls=1 0 +0 307 +0 2 +cfn=(2170) MR::cmdline_debug(std::string const&) +calls=1 0 +0 7 +0 12 +cob=(7) +cfi=(53) +cfn=(880) +calls=1 0 +0 126 +0 55 +cob=(7) +cfi=(53) +cfn=(880) +calls=1 0 +0 180 +0 10 +cob=(7) +cfi=(53) +cfn=(1254) +calls=1 0 +0 20 +0 7 +cfn=(2670) MR::File::MMap::map() +calls=1 0 +0 27692 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 741 +0 23 +cfn=(2664) std::vector >::_M_fill_insert(__gnu_cxx::__normal_iterator > >, unsigned long, unsigned char* const&) +calls=1 0 +0 315 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1332 +0 7 +cfn=(2658) +calls=1 0 +0 313 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1645 +0 8 +cob=(7) +cfi=(53) +cfn=(1308) +calls=1 0 +0 82 +0 7 +cob=(7) +cfi=(53) +cfn=(1308) +calls=1 0 +0 113 +0 9 + +fn=(2834) MR::Image::Handler::Default::~Default() +0 24 +cfn=(2840) MR::File::MMap::~MMap() +calls=1 0 +0 4683 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 747 +0 2 +cob=(7) +cfi=(53) +cfn=(1142) +calls=1 0 +0 81 +0 3 +cob=(7) +cfi=(53) +cfn=(1142) +calls=1 0 +0 81 +0 7 +cob=(7) +cfi=(53) +cfn=(1142) +calls=1 0 +0 81 +0 7 +cob=(7) +cfi=(53) +cfn=(1142) +calls=1 0 +0 81 +0 4 +cob=(7) +cfi=(53) +cfn=(1142) +calls=1 0 +0 81 +0 2 +cob=(7) +cfi=(53) +cfn=(1142) +calls=1 0 +0 81 +0 7 + +fn=(3752) MR::Thread::Mutex::~Mutex() +0 1 +cob=(4) +cfi=(83) /build/buildd/eglibc-2.11.1/nptl/forward.c +cfn=(3758) pthread_mutex_destroy +calls=1 176 +0 5 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1914 + +fn=(3762) std::map, std::allocator > >::~map() +0 3 +cob=(12) +cfi=(84) +cfn=(2618) std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::_M_erase(std::_Rb_tree_node >*) +calls=1 0 +0 11 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 2038 +0 2 + +fn=(3778) MR::Image::Format::MRI::~MRI() +0 4 + +fn=(3782) MR::Image::Format::Pipe::~Pipe() +0 4 + +fn=(916) global constructors keyed to base.cpp +0 3 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 + +fn=(1026) global constructors keyed to nifti1_utils.cpp +0 3 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 + +fn=(1990) MR::Image::ParsedNameList::parse_scan_check(std::string const&, unsigned long) +0 52 +cfn=(1996) +calls=2 0 +0 19582 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 867 +0 6 +cfn=(2068) MR::Image::ParsedNameList::scan(MR::Image::NameParser&) +calls=2 0 +0 9734 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1011 +0 32 +cfn=(2102) void std::__introsort_loop<__gnu_cxx::__normal_iterator*, std::vector, std::allocator > > >, long>(__gnu_cxx::__normal_iterator*, std::vector, std::allocator > > >, __gnu_cxx::__normal_iterator*, std::vector, std::allocator > > >, long) +calls=2 0 +0 42 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1762 +0 6 +cfn=(2108) +calls=2 0 +0 1754 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1730 +0 6 +cfn=(2120) MR::Image::ParsedNameList::count() const +calls=2 0 +0 58 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 876 +0 16 +cfn=(2126) MR::Image::NameParser::~NameParser() +calls=2 0 +0 1979 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 794 +0 18 + +fn=(2022) +0 36 +cfn=(2028) +calls=2 0 +0 6929 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1523 +0 24 + +fn=(2380) void std::vector >::_M_range_insert<__gnu_cxx::__normal_iterator > > >(__gnu_cxx::__normal_iterator > >, __gnu_cxx::__normal_iterator > >, __gnu_cxx::__normal_iterator > >, std::forward_iterator_tag) +0 2154 +cob=(4) +cfi=(113) /build/buildd/eglibc-2.11.1/string/memmove.c +cfn=(1794) memmove +calls=54 47 +0 1296 +0 170 +cob=(7) +cfi=(53) +cfn=(880) +calls=10 0 +0 2398 +0 100 +cob=(4) +cfi=(113) +cfn=(1794) +calls=10 47 +0 835 +0 70 +cob=(4) +cfi=(113) +cfn=(1794) +calls=10 47 +0 620 +0 100 +cob=(4) +cfi=(113) +cfn=(1794) +calls=10 47 +0 240 +0 38 +cob=(7) +cfi=(53) +cfn=(1142) +calls=8 0 +0 725 +0 714 +cob=(4) +cfi=(113) +cfn=(1794) +calls=54 47 +0 3348 +0 324 +cob=(4) +cfi=(113) +cfn=(1794) +calls=54 47 +0 1296 +0 418 + +fn=(2386) std::vector >::~vector() +0 271 +cob=(7) +cfi=(53) +cfn=(1142) +calls=67 0 +0 5460 +0 1 + +fn=(2570) MR::Image::Header::sanitise() +0 18 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 298 +0 2 +cfn=(2170) +calls=1 0 +0 7 +0 2 +cob=(7) +cfi=(53) +cfn=(1380) +calls=1 0 +0 100 +0 8 +cfn=(2576) void MR::DataSet::Stride::sanitise(MR::Image::Axes&) +calls=1 0 +0 265 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1052 +0 3 +cfn=(2582) std::vector > MR::DataSet::Stride::order(MR::Image::Axes const&) +calls=1 0 +0 352 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1144 +0 62 +cob=(7) +cfi=(53) +cfn=(1142) +calls=1 0 +0 81 +0 16 +cob=(9) +cfi=(58) +cfn=(2592) gsl_permutation_alloc +calls=1 0 +0 212 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 955 +0 3 +cob=(9) +cfi=(58) +cfn=(2598) gsl_permutation_data +calls=1 0 +0 2 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 931 +0 36 +cob=(9) +cfi=(58) +cfn=(2598) +calls=1 0 +0 2 +0 38 +cob=(9) +cfi=(58) +cfn=(2598) +calls=1 0 +0 2 +0 38 +cob=(9) +cfi=(58) +cfn=(2598) +calls=1 0 +0 2 +0 3 +cob=(9) +cfi=(58) +cfn=(2598) +calls=1 0 +0 2 +0 7 +cob=(9) +cfi=(58) +cfn=(2598) +calls=1 0 +0 2 +0 3 +cob=(9) +cfi=(58) +cfn=(2598) +calls=1 0 +0 2 +0 8 +cob=(9) +cfi=(58) +cfn=(2598) +calls=1 0 +0 2 +0 3 +cob=(9) +cfi=(58) +cfn=(2598) +calls=1 0 +0 2 +0 9 +cob=(9) +cfi=(58) +cfn=(2598) +calls=1 0 +0 2 +0 21 +cob=(9) +cfi=(58) +cfn=(2604) gsl_permutation_free +calls=1 0 +0 165 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 931 +0 13 +cob=(9) +cfi=(58) +cfn=(2598) +calls=1 0 +0 2 +0 4 +cob=(9) +cfi=(58) +cfn=(2598) +calls=1 0 +0 2 +0 177 + +fn=(2576) +0 265 + +fn=(2582) +0 22 +cob=(7) +cfi=(53) +cfn=(880) +calls=1 0 +0 110 +0 58 +cfn=(2584) void std::__introsort_loop<__gnu_cxx::__normal_iterator > >, long, MR::DataSet::Stride::(anonymous namespace)::Compare >(__gnu_cxx::__normal_iterator > >, __gnu_cxx::__normal_iterator > >, long, MR::DataSet::Stride::(anonymous namespace)::Compare) +calls=1 0 +0 22 +0 6 +cfn=(2586) void std::__insertion_sort<__gnu_cxx::__normal_iterator > >, MR::DataSet::Stride::(anonymous namespace)::Compare >(__gnu_cxx::__normal_iterator > >, __gnu_cxx::__normal_iterator > >, MR::DataSet::Stride::(anonymous namespace)::Compare) +calls=1 0 +0 127 +0 7 + +fn=(918) global constructors keyed to series.cpp +0 3 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 + +fn=(928) global constructors keyed to axis.cpp +0 5 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 5663 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1498 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 + +fn=(972) global constructors keyed to mmap.cpp +0 3 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 + +fn=(992) global constructors keyed to mapper.cpp +0 3 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 + +fn=(1028) global constructors keyed to reslice.cpp +0 3 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 10 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 8 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 + +fn=(1030) global constructors keyed to LU.cpp +0 3 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 + +fn=(1290) MR::File::Config::init() +0 15 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 315 +0 6 +cob=(4) +cfi=(94) +cfn=(1296) +calls=1 37 +0 14 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1738 +0 3 +cob=(4) +cfi=(95) +cfn=(1302) +calls=1 34 +0 3 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1834 +0 16 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 314 +0 2 +cob=(4) +cfi=(96) /build/buildd/eglibc-2.11.1/stdlib/getenv.c +cfn=(1318) getenv +calls=1 36 +0 138 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1708 +0 7 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 308 +0 17 +cob=(4) +cfi=(94) +cfn=(1296) +calls=1 37 +0 14 +0 3 +cob=(4) +cfi=(95) +cfn=(1302) +calls=1 34 +0 3 +0 23 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 285 +0 7 +cob=(7) +cfi=(53) +cfn=(1326) +calls=1 0 +0 12 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1538 +0 7 +cob=(7) +cfi=(53) +cfn=(1254) +calls=1 0 +0 20 +0 4 +cob=(7) +cfi=(53) +cfn=(1332) +calls=1 0 +0 2283 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1458 +0 7 +cob=(12) +cfi=(84) +cfn=(1350) +calls=1 0 +0 3373 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1238 +0 14 +cob=(7) +cfi=(53) +cfn=(1308) +calls=1 0 +0 82 +0 7 +cob=(7) +cfi=(53) +cfn=(1308) +calls=1 0 +0 82 +0 15 +cob=(7) +cfi=(53) +cfn=(1308) +calls=1 0 +0 952 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1682 +0 12 +cob=(7) +cfi=(53) +cfn=(1308) +calls=1 0 +0 82 +0 7 +cob=(7) +cfi=(53) +cfn=(1308) +calls=1 0 +0 82 +0 15 +cob=(7) +cfi=(53) +cfn=(1308) +calls=1 0 +0 82 +0 5 + +fn=(2040) +0 20 +cob=(7) +cfi=(53) +cfn=(880) +calls=2 0 +0 278 + +fn=(2114) +0 44 + +fn=(2126) +0 12 +cob=(7) +cfi=(53) +cfn=(1380) +calls=2 0 +0 14 +0 4 +cob=(7) +cfi=(53) +cfn=(1380) +calls=2 0 +0 30 +0 4 +cob=(7) +cfi=(53) +cfn=(1380) +calls=2 0 +0 200 +0 26 +cob=(7) +cfi=(53) +cfn=(1380) +calls=2 0 +0 200 +0 20 +cob=(7) +cfi=(53) +cfn=(1142) +calls=2 0 +0 162 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1307 + +fn=(2168) MR::File::KeyValue::open(std::string const&, char const*) +0 40 +cob=(7) +cfi=(53) +cfn=(1650) +calls=2 0 +0 76 +0 12 +cob=(12) +cfi=(84) +cfn=(1962) +calls=2 0 +0 867 +0 6 +cob=(7) +cfi=(53) +cfn=(1254) +calls=2 0 +0 40 +0 8 +cob=(7) +cfi=(53) +cfn=(1686) +calls=2 0 +0 762 +0 4 +cfn=(2170) +calls=2 0 +0 14 +0 32 +cob=(7) +cfi=(53) +cfn=(1550) +calls=2 0 +0 2509 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 2282 +0 14 +cob=(7) +cfi=(53) +cfn=(1630) +calls=2 0 +0 16 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 2154 +0 40 +cob=(7) +cfi=(53) +cfn=(1638) +calls=2 0 +0 1273 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 2531 +0 12 +cob=(4) +cfi=(69) +cfn=(642) +calls=2 26 +0 38 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1690 +0 10 +cob=(7) +cfi=(53) +cfn=(2196) +calls=2 0 +0 149 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1538 +0 24 +cob=(7) +cfi=(53) +cfn=(1308) +calls=2 0 +0 164 +0 8 +cob=(7) +cfi=(53) +cfn=(1260) +calls=2 0 +0 56 +0 26 +cob=(7) +cfi=(53) +cfn=(1326) +calls=2 0 +0 24 +0 18 +cob=(7) +cfi=(53) +cfn=(1308) +calls=2 0 +0 164 +0 14 +cob=(7) +cfi=(53) +cfn=(1308) +calls=2 0 +0 385 +0 26 + +fn=(2306) MR::parse_floats(std::string const&) +0 6436 +cob=(7) +cfi=(53) +cfn=(1702) +calls=195 0 +0 8265 +0 260 +cob=(7) +cfi=(53) +cfn=(1702) +calls=65 0 +0 3040 +0 2860 +cob=(7) +cfi=(53) +cfn=(1708) +calls=260 0 +0 52465 +0 780 +cob=(7) +cfi=(53) +cfn=(2138) +calls=260 0 +0 11450 +0 2852 +cob=(7) +cfi=(53) +cfn=(1708) +calls=259 0 +0 52333 +0 777 +cob=(7) +cfi=(53) +cfn=(722) +calls=259 0 +0 25123 +0 6734 +cob=(7) +cfi=(53) +cfn=(728) +calls=259 0 +0 183372 +0 4144 +cob=(7) +cfi=(53) +cfn=(492) +calls=259 0 +0 10101 +0 2331 +cob=(7) +cfi=(53) +cfn=(1752) +calls=259 0 +0 50060 +0 1554 +cob=(7) +cfi=(53) +cfn=(1758) +calls=259 0 +0 5439 +0 777 +cob=(7) +cfi=(53) +cfn=(728) +calls=259 0 +0 183372 +0 777 +cob=(7) +cfi=(53) +cfn=(2312) +calls=259 0 +0 421149 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1648 +0 4921 +cob=(7) +cfi=(53) +cfn=(746) +calls=259 0 +0 3108 +0 2590 +cob=(7) +cfi=(53) +cfn=(1818) +calls=259 0 +0 15022 +0 3108 +cob=(7) +cfi=(53) +cfn=(1308) +calls=259 0 +0 21238 +0 1429 +cfn=(2336) std::vector >::_M_insert_aux(__gnu_cxx::__normal_iterator > >, float const&) +calls=195 0 +0 60192 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1243 +0 1755 +cob=(7) +cfi=(53) +cfn=(1308) +calls=260 0 +0 21320 +0 1814 +cob=(7) +cfi=(53) +cfn=(1308) +calls=259 0 +0 21238 +0 3371 + +fn=(2454) MR::DataType::parse(std::string const&) +0 36 +cob=(7) +cfi=(53) +cfn=(2220) +calls=2 0 +0 647 +0 12 +cob=(7) +cfi=(53) +cfn=(1326) +calls=2 0 +0 24 +0 24 +cob=(4) +cfi=(124) +cfn=(2234) +calls=2 47 +0 24 +0 64 +cob=(4) +cfi=(124) +cfn=(2234) +calls=16 47 +0 192 +0 96 +cob=(7) +cfi=(53) +cfn=(2138) +calls=2 0 +0 107 +0 34 +cob=(7) +cfi=(53) +cfn=(2138) +calls=2 0 +0 109 +0 9 +cob=(7) +cfi=(53) +cfn=(2138) +calls=1 0 +0 55 +0 5 +cfn=(3136) bool std::operator==, std::allocator >(std::basic_string, std::allocator > const&, char const*) +calls=1 0 +0 64 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1010 +0 5 +cfn=(3136) +calls=1 0 +0 72 +0 16 +cob=(7) +cfi=(53) +cfn=(1308) +calls=2 0 +0 164 +0 10 + +fn=(2638) MR::Image::Handler::Base::prepare() +0 23 +cfn=(2640) +calls=1 0 +0 35302 +0 18 +cob=(7) +cfi=(53) +cfn=(880) +calls=1 0 +0 110 +0 63 +cfn=(2742) std::vector >::operator=(std::vector > const&) +calls=1 0 +0 226 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 794 +0 4 +cob=(7) +cfi=(53) +cfn=(1142) +calls=1 0 +0 81 +0 87 +cob=(7) +cfi=(53) +cfn=(1142) +calls=1 0 +0 81 +0 42 +cob=(7) +cfi=(53) +cfn=(722) +calls=1 0 +0 97 +0 23 +cob=(7) +cfi=(53) +cfn=(728) +calls=1 0 +0 708 +0 16 +cob=(7) +cfi=(53) +cfn=(492) +calls=1 0 +0 39 +0 11 +cob=(7) +cfi=(53) +cfn=(728) +calls=1 0 +0 708 +0 4 +cob=(7) +cfi=(53) +cfn=(1394) +calls=1 0 +0 761 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 2456 +0 11 +cob=(7) +cfi=(53) +cfn=(2684) +calls=1 0 +0 290 +0 9 +cob=(7) +cfi=(53) +cfn=(2684) +calls=3 0 +0 850 +0 16 +cob=(7) +cfi=(53) +cfn=(1394) +calls=4 0 +0 492 +0 32 +cob=(7) +cfi=(53) +cfn=(1394) +calls=1 0 +0 123 +0 25 +cob=(7) +cfi=(53) +cfn=(746) +calls=1 0 +0 12 +0 9 +cob=(7) +cfi=(53) +cfn=(1818) +calls=1 0 +0 58 +0 2 +cob=(7) +cfi=(53) +cfn=(722) +calls=1 0 +0 97 +0 19 +cob=(7) +cfi=(53) +cfn=(728) +calls=1 0 +0 708 +0 15 +cob=(7) +cfi=(53) +cfn=(492) +calls=1 0 +0 39 +0 9 +cob=(7) +cfi=(53) +cfn=(728) +calls=1 0 +0 708 +0 3 +cob=(7) +cfi=(53) +cfn=(1436) +calls=1 0 +0 805 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1648 +0 5 +cob=(7) +cfi=(53) +cfn=(2760) +calls=1 0 +0 2336 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 2108 +0 16 +cob=(7) +cfi=(53) +cfn=(746) +calls=1 0 +0 12 +0 9 +cob=(7) +cfi=(53) +cfn=(1818) +calls=1 0 +0 58 +0 10 +cob=(7) +cfi=(53) +cfn=(1338) +calls=1 0 +0 414 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1450 +0 4 +cob=(7) +cfi=(53) +cfn=(1686) +calls=1 0 +0 64 +0 3 +cob=(7) +cfi=(53) +cfn=(1360) +calls=1 0 +0 86 +0 4 +cob=(7) +cfi=(53) +cfn=(1254) +calls=1 0 +0 20 +0 4 +cob=(7) +cfi=(53) +cfn=(1686) +calls=1 0 +0 478 +0 5 +cob=(12) +cfi=(84) +cfn=(1350) +calls=1 0 +0 557 +0 4 +cob=(7) +cfi=(53) +cfn=(1254) +calls=1 0 +0 20 +0 4 +cob=(7) +cfi=(53) +cfn=(1686) +calls=1 0 +0 374 +0 5 +cob=(12) +cfi=(84) +cfn=(1350) +calls=1 0 +0 337 +0 2 +cfn=(1980) +calls=1 0 +0 7 +0 34 +cob=(7) +cfi=(53) +cfn=(1308) +calls=1 0 +0 82 +0 7 +cob=(7) +cfi=(53) +cfn=(880) +calls=1 0 +0 110 +0 56 +cfn=(2744) void std::__introsort_loop<__gnu_cxx::__normal_iterator > >, long, MR::DataSet::Stride::(anonymous namespace)::Compare > >(__gnu_cxx::__normal_iterator > >, __gnu_cxx::__normal_iterator > >, long, MR::DataSet::Stride::(anonymous namespace)::Compare >) +calls=1 0 +0 22 +0 6 +cob=(12) +cfi=(84) +cfn=(2712) char* std::string::_S_construct(char*, char*, std::allocator const&, std::forward_iterator_tag) +calls=1 0 +0 184 +0 7 +cob=(7) +cfi=(53) +cfn=(1260) +calls=1 0 +0 28 +0 12 +cfn=(2746) void std::__insertion_sort<__gnu_cxx::__normal_iterator > >, MR::DataSet::Stride::(anonymous namespace)::Compare > >(__gnu_cxx::__normal_iterator > >, __gnu_cxx::__normal_iterator > >, MR::DataSet::Stride::(anonymous namespace)::Compare >) +calls=1 0 +0 120 +0 12 +cob=(7) +cfi=(53) +cfn=(1308) +calls=1 0 +0 82 +0 15 +cob=(7) +cfi=(53) +cfn=(1308) +calls=1 0 +0 82 +0 7 +cob=(7) +cfi=(53) +cfn=(1308) +calls=1 0 +0 124 +0 15 +cob=(7) +cfi=(53) +cfn=(1308) +calls=1 0 +0 82 +0 7 +cob=(7) +cfi=(53) +cfn=(1308) +calls=1 0 +0 124 +0 15 +cob=(7) +cfi=(53) +cfn=(1308) +calls=1 0 +0 82 +0 11 +cob=(7) +cfi=(53) +cfn=(1308) +calls=1 0 +0 113 +0 11 +cob=(7) +cfi=(53) +cfn=(1308) +calls=1 0 +0 124 +0 5 + +fn=(2746) +0 120 + +fn=(2840) +0 17 +cob=(12) +cfi=(84) +cfn=(1962) +calls=1 0 +0 381 +0 4 +cob=(7) +cfi=(53) +cfn=(1254) +calls=1 0 +0 20 +0 4 +cob=(7) +cfi=(53) +cfn=(1686) +calls=1 0 +0 553 +0 2 +cfn=(2170) +calls=1 0 +0 7 +0 12 +cob=(4) +cfi=(103) +cfn=(2846) munmap +calls=1 82 +0 5 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1741 +0 4 +cob=(4) +cfi=(106) +cfn=(2852) close +calls=1 82 +0 7 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1673 +0 18 +cob=(7) +cfi=(53) +cfn=(1308) +calls=1 0 +0 82 +0 11 +cob=(7) +cfi=(53) +cfn=(1308) +calls=1 0 +0 129 +0 13 + +fn=(3676) MR::App::~App() +0 31 + +fn=(3784) std::tr1::unordered_map, std::equal_to, std::allocator > >::~unordered_map() +0 109 +cob=(7) +cfi=(53) +cfn=(1142) +calls=1 0 +0 81 + +fn=(468) +0 6 + +fn=(920) global constructors keyed to tree.cpp +0 3 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 + +fn=(974) global constructors keyed to analyse.cpp +0 3 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 + +fn=(994) global constructors keyed to default.cpp +0 3 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 + +fn=(1032) global constructors keyed to study.cpp +0 3 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 + +fn=(2120) +0 58 + +fn=(2142) MR::Image::Format::MRtrix::read(MR::Image::Header&) const +0 18 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 225 +0 16 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 219 +0 16 +cob=(7) +cfi=(53) +cfn=(1708) +calls=1 0 +0 259 +0 7 +cob=(7) +cfi=(53) +cfn=(1380) +calls=1 0 +0 100 +0 5 +cob=(7) +cfi=(53) +cfn=(1380) +calls=1 0 +0 100 +0 9 +cob=(7) +cfi=(53) +cfn=(1708) +calls=1 0 +0 201 +0 8 +cob=(7) +cfi=(53) +cfn=(1380) +calls=1 0 +0 100 +0 32 +cob=(7) +cfi=(53) +cfn=(722) +calls=1 0 +0 97 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1491 +0 23 +cob=(7) +cfi=(53) +cfn=(728) +calls=1 0 +0 708 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 2322 +0 8 +cob=(7) +cfi=(53) +cfn=(1526) +calls=1 0 +0 265 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1938 +0 5 +cob=(7) +cfi=(53) +cfn=(728) +calls=1 0 +0 708 +0 4 +cfn=(2168) +calls=1 0 +0 13682 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 848 +0 53 +cfn=(2202) +calls=1 0 +0 8334 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 786 +0 348 +cfn=(2202) +calls=87 0 +0 296451 +0 785 +cob=(7) +cfi=(53) +cfn=(2220) +calls=87 0 +0 24670 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1516 +0 522 +cob=(7) +cfi=(53) +cfn=(1326) +calls=87 0 +0 1044 +0 870 +cob=(4) +cfi=(124) +cfn=(2234) +calls=87 47 +0 1044 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1724 +0 2220 +cob=(4) +cfi=(124) +cfn=(2234) +calls=740 47 +0 8880 +0 3830 +cob=(7) +cfi=(53) +cfn=(2138) +calls=87 0 +0 3908 +0 182 +cfn=(2240) +calls=1 0 +0 31910 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 783 +0 3 +cfn=(2300) std::vector >::operator=(std::vector > const&) +calls=1 0 +0 222 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 810 +0 5 +cob=(7) +cfi=(53) +cfn=(1142) +calls=2 0 +0 162 +0 870 +cob=(7) +cfi=(53) +cfn=(1308) +calls=87 0 +0 7134 +0 603 +cob=(7) +cfi=(53) +cfn=(2138) +calls=86 0 +0 3794 +0 178 +cfn=(2306) +calls=1 0 +0 19952 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 776 +0 5 +cfn=(2342) std::vector >::operator=(std::vector > const&) +calls=1 0 +0 222 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 876 +0 513 +cob=(7) +cfi=(53) +cfn=(2138) +calls=85 0 +0 4265 +0 175 +cob=(7) +cfi=(53) +cfn=(1260) +calls=1 0 +0 28 +0 505 +cob=(7) +cfi=(53) +cfn=(2138) +calls=84 0 +0 3776 +0 173 +cob=(7) +cfi=(53) +cfn=(1260) +calls=1 0 +0 28 +0 499 +cob=(7) +cfi=(53) +cfn=(2138) +calls=83 0 +0 4161 +0 171 +cob=(7) +cfi=(53) +cfn=(1260) +calls=1 0 +0 28 +0 493 +cob=(7) +cfi=(53) +cfn=(2138) +calls=82 0 +0 4101 +0 177 +cfn=(2426) +calls=1 0 +0 7286 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 775 +0 589 +cob=(7) +cfi=(53) +cfn=(2138) +calls=82 0 +0 3608 +0 656 +cob=(7) +cfi=(53) +cfn=(2138) +calls=82 0 +0 4112 +0 174 +cfn=(2348) +calls=1 0 +0 1597 +0 4 +cob=(12) +cfi=(84) +cfn=(2366) std::vector >::operator=(std::vector > const&) +calls=1 0 +0 288 +0 4 +cob=(12) +cfi=(84) +cfn=(2374) std::vector >::~vector() +calls=2 0 +0 290 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 846 +0 488 +cob=(7) +cfi=(53) +cfn=(2138) +calls=81 0 +0 3577 +0 172 +cfn=(2348) +calls=1 0 +0 3365 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 749 +0 5 +cob=(12) +cfi=(84) +cfn=(2366) +calls=1 0 +0 346 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 894 +0 2 +cob=(4) +cfi=(122) /build/buildd/eglibc-2.11.1/string/../sysdeps/x86_64/multiarch/../memcmp.S +cfn=(2150) __GI_memcmp +calls=1 25 +0 31 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1698 +0 10 +cfn=(2454) +calls=1 0 +0 777 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 785 +0 483 +cob=(7) +cfi=(53) +cfn=(2138) +calls=80 0 +0 4049 +0 622 +cob=(7) +cfi=(53) +cfn=(2138) +calls=77 0 +0 4368 +0 1721 +cfn=(2306) +calls=3 0 +0 48001 +0 24 +cfn=(2380) +calls=3 0 +0 1156 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1573 +0 128 +cfn=(2386) +calls=64 0 +0 5440 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 758 +0 72 +cfn=(2460) +calls=1 0 +0 13825 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 870 +0 55 +cob=(7) +cfi=(53) +cfn=(1260) +calls=1 0 +0 118 +0 15 +cob=(7) +cfi=(53) +cfn=(1260) +calls=3 0 +0 247 +0 70 +cob=(7) +cfi=(53) +cfn=(1260) +calls=1 0 +0 118 +0 15 +cob=(7) +cfi=(53) +cfn=(1260) +calls=3 0 +0 247 +0 270 +cob=(7) +cfi=(53) +cfn=(1260) +calls=16 0 +0 448 +0 20 +cfn=(2472) T.1670 +calls=1 0 +0 1188 +0 150 +cob=(12) +cfi=(84) +cfn=(2484) MR::Math::Matrix::operator=(MR::Math::Matrix const&) +calls=1 0 +0 1378 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 886 +0 4 +cob=(9) +cfi=(58) +cfn=(2494) gsl_block_float_free +calls=1 0 +0 1807 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 947 +0 14 +cob=(4) +cfi=(122) +cfn=(2150) +calls=1 25 +0 22 +0 9 +cob=(7) +cfi=(53) +cfn=(722) +calls=1 0 +0 97 +0 22 +cob=(7) +cfi=(53) +cfn=(728) +calls=1 0 +0 708 +0 16 +cob=(7) +cfi=(53) +cfn=(492) +calls=1 0 +0 39 +0 9 +cob=(7) +cfi=(53) +cfn=(1752) +calls=1 0 +0 197 +0 6 +cob=(7) +cfi=(53) +cfn=(1758) +calls=1 0 +0 21 +0 3 +cob=(7) +cfi=(53) +cfn=(728) +calls=1 0 +0 708 +0 6 +cob=(7) +cfi=(53) +cfn=(2504) +calls=1 0 +0 1570 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 2395 +0 6 +cob=(7) +cfi=(53) +cfn=(2516) +calls=1 0 +0 2472 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1656 +0 3 +cob=(7) +cfi=(53) +cfn=(2138) +calls=1 0 +0 52 +0 7 +cob=(7) +cfi=(53) +cfn=(1260) +calls=1 0 +0 123 +0 10 +cfn=(1990) +calls=1 0 +0 4284 +0 10 +cob=(7) +cfi=(53) +cfn=(1380) +calls=1 0 +0 15 +0 2 +cob=(7) +cfi=(53) +cfn=(1380) +calls=1 0 +0 15 +0 20 +cob=(7) +cfi=(53) +cfn=(1254) +calls=1 0 +0 20 +0 3 +cob=(7) +cfi=(53) +cfn=(1254) +calls=1 0 +0 20 +0 9 +cfn=(2530) std::vector >::_M_insert_aux(__gnu_cxx::__normal_iterator > >, MR::File::Entry const&) +calls=1 0 +0 314 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1440 +0 6 +cfn=(2536) MR::Image::ParsedNameList::~ParsedNameList() +calls=1 0 +0 296 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 864 +0 2 +cob=(7) +cfi=(53) +cfn=(1380) +calls=1 0 +0 15 +0 2 +cob=(7) +cfi=(53) +cfn=(2542) +calls=1 0 +0 1195 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 2140 +0 4 +cob=(7) +cfi=(53) +cfn=(1142) +calls=1 0 +0 81 +0 2 +cob=(12) +cfi=(84) +cfn=(2374) +calls=1 0 +0 145 +0 2 +cob=(12) +cfi=(84) +cfn=(2374) +calls=1 0 +0 145 +0 2 +cfn=(2386) +calls=1 0 +0 4 +0 2 +cfn=(2386) +calls=1 0 +0 85 +0 2 +cfn=(2386) +calls=1 0 +0 118 +0 2 +cfn=(2386) +calls=1 0 +0 85 +0 4 +cob=(7) +cfi=(53) +cfn=(1142) +calls=1 0 +0 81 +0 2 +cob=(7) +cfi=(53) +cfn=(1380) +calls=1 0 +0 15 +0 2 +cob=(7) +cfi=(53) +cfn=(1380) +calls=1 0 +0 100 +0 2 +cob=(7) +cfi=(53) +cfn=(1380) +calls=1 0 +0 100 +0 2 +cob=(12) +cfi=(84) +cfn=(2552) MR::File::KeyValue::~KeyValue() +calls=1 0 +0 971 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 790 +0 8 +cob=(7) +cfi=(53) +cfn=(1308) +calls=1 0 +0 82 +0 433 +cob=(7) +cfi=(53) +cfn=(1254) +calls=16 0 +0 3425 +0 64 +cob=(7) +cfi=(53) +cfn=(1254) +calls=16 0 +0 240 +0 64 +cob=(12) +cfi=(84) +cfn=(2392) std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::_M_insert_unique_(std::_Rb_tree_const_iterator >, std::pair const&) +calls=16 0 +0 10614 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 2422 +0 80 +cob=(12) +cfi=(84) +cfn=(2408) std::pair::~pair() +calls=16 0 +0 496 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 766 +0 48 +cob=(7) +cfi=(53) +cfn=(1380) +calls=16 0 +0 112 +0 321 +cfn=(2306) +calls=61 0 +0 1132495 +0 488 +cfn=(2380) +calls=61 0 +0 13690 +0 69 +cfn=(2472) +calls=1 0 +0 619 +0 2210 +cob=(12) +cfi=(84) +cfn=(2484) +calls=1 0 +0 2968 +0 4 +cob=(9) +cfi=(58) +cfn=(2494) +calls=1 0 +0 196 +0 1 + +fn=(2336) +0 5850 +cob=(7) +cfi=(53) +cfn=(880) +calls=195 0 +0 21582 +0 2925 +cob=(4) +cfi=(113) +cfn=(1794) +calls=195 47 +0 9490 +0 1560 +cob=(4) +cfi=(113) +cfn=(1794) +calls=195 47 +0 4680 +0 715 +cob=(7) +cfi=(53) +cfn=(1142) +calls=130 0 +0 10530 +0 2860 + +fn=(2470) +0 139 + +fn=(2558) MR::Image::Header::Header(MR::Image::Header const&) +0 19 +cob=(12) +cfi=(84) +cfn=(2564) std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::_M_copy(std::_Rb_tree_node > const*, std::_Rb_tree_node >*) +calls=1 0 +0 4094 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 2102 +0 269 +cob=(7) +cfi=(53) +cfn=(880) +calls=1 0 +0 458 +0 62 +cob=(7) +cfi=(53) +cfn=(1254) +calls=4 0 +0 60 +0 12 +cob=(7) +cfi=(53) +cfn=(1254) +calls=4 0 +0 60 +0 2777 +cob=(9) +cfi=(58) +cfn=(2478) gsl_block_float_alloc +calls=1 0 +0 212 +0 8 +cob=(9) +cfi=(58) +cfn=(2478) +calls=1 0 +0 464 +0 3 + +fn=(2586) +0 127 + +fn=(3738) +0 10 +cob=(4) +cfi=(153) +cfn=(3726) +calls=1 31 +0 9000 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1810 +0 13 + +fn=(3768) MR::Image::Format::DICOM::~DICOM() +0 4 + +fn=(3772) MR::Image::Format::Analyse::~Analyse() +0 4 + +fn=(462) +0 6 + +fn=(474) +0 11 +cfn=(478) +calls=1 0 +0 106078 +0 78 +cfn=(1032) +calls=1 0 +0 94 +cfn=(1030) +calls=1 0 +0 94 +cfn=(1028) +calls=1 0 +0 236 +cfn=(1026) +calls=1 0 +0 94 +cfn=(1024) +calls=1 0 +0 94 +cfn=(1022) +calls=1 0 +0 94 +cfn=(1020) +calls=1 0 +0 94 +cfn=(1018) global constructors keyed to xds.cpp +calls=1 0 +0 94 +cfn=(1016) global constructors keyed to dicom.cpp +calls=1 0 +0 94 +cfn=(1014) global constructors keyed to key_value.cpp +calls=1 0 +0 94 +cfn=(1006) global constructors keyed to exec.cpp +calls=1 0 +0 2048 +cfn=(1004) +calls=1 0 +0 94 +cfn=(1002) +calls=1 0 +0 94 +cfn=(1000) +calls=1 0 +0 94 +cfn=(998) global constructors keyed to nifti1_gz.cpp +calls=1 0 +0 94 +cfn=(996) global constructors keyed to args.cpp +calls=1 0 +0 172 +cfn=(994) +calls=1 0 +0 94 +cfn=(992) +calls=1 0 +0 94 +cfn=(990) +calls=1 0 +0 291 +cfn=(988) +calls=1 0 +0 94 +cfn=(976) global constructors keyed to gz.cpp +calls=1 0 +0 1499 +cfn=(974) +calls=1 0 +0 94 +cfn=(972) +calls=1 0 +0 94 +cfn=(970) global constructors keyed to config.cpp +calls=1 0 +0 167 +cfn=(928) +calls=1 0 +0 7332 +cfn=(926) +calls=1 0 +0 94 +cfn=(856) global constructors keyed to pipe.cpp +calls=1 0 +0 94 +cfn=(924) global constructors keyed to list.cpp +calls=1 0 +0 663 +cfn=(922) global constructors keyed to nifti1.cpp +calls=1 0 +0 94 +cfn=(920) +calls=1 0 +0 94 +cfn=(918) +calls=1 0 +0 94 +cfn=(916) +calls=1 0 +0 94 +cfn=(914) +calls=1 0 +0 94 +cfn=(912) +calls=1 0 +0 94 +cfn=(862) +calls=1 0 +0 68010 +cfn=(860) +calls=1 0 +0 94 +cfn=(860) +calls=1 0 +0 94 +cfn=(858) +calls=1 0 +0 94 +cfn=(856) +calls=1 0 +0 94 +0 124 + +fn=(922) +0 3 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 + +fn=(976) +0 3 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 1467 + +fn=(996) +0 3 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 16 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 + +fn=(1006) +0 5 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(4) +cfi=(83) +cfn=(1012) pthread_mutex_init +calls=1 178 +0 5 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1874 +0 7 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 + +fn=(1014) +0 3 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 + +fn=(1956) MR::Image::Header::open(std::string const&, bool) +0 55 +cob=(12) +cfi=(84) +cfn=(1962) +calls=1 0 +0 5079 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1270 +0 4 +cob=(7) +cfi=(53) +cfn=(1254) +calls=1 0 +0 20 +0 4 +cob=(7) +cfi=(53) +cfn=(1686) +calls=1 0 +0 600 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1508 +0 2 +cfn=(1980) +calls=1 0 +0 7 +0 2 +cob=(7) +cfi=(53) +cfn=(1380) +calls=1 0 +0 147 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1414 +0 2 +cob=(7) +cfi=(53) +cfn=(1380) +calls=1 0 +0 100 +0 10 +cfn=(1990) +calls=1 0 +0 36041 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1043 +0 6 +cob=(7) +cfi=(53) +cfn=(1254) +calls=1 0 +0 20 +0 5 +cob=(7) +cfi=(53) +cfn=(1260) +calls=1 0 +0 28 +0 2 +cob=(7) +cfi=(53) +cfn=(1380) +calls=1 0 +0 15 +0 13 +cfn=(2558) +calls=1 0 +0 10600 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 811 +0 13 +cfn=(2570) +calls=1 0 +0 6991 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 821 +0 5 +cob=(7) +cfi=(53) +cfn=(1260) +calls=1 0 +0 36 +0 2 +cob=(12) +cfi=(84) +cfn=(2610) MR::Image::Header::~Header() +calls=1 0 +0 3735 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 774 +0 5 +cfn=(2536) +calls=1 0 +0 381 +0 26 +cfn=(2142) +calls=1 0 +0 1787686 +cfn=(2140) +calls=1 0 +0 37 +cfn=(2132) MR::Image::Format::Pipe::read(MR::Image::Header&) const +calls=1 0 +0 1573 +0 9 +cob=(7) +cfi=(53) +cfn=(880) +calls=1 0 +0 110 +0 20 + +fn=(2046) +0 32 +cob=(7) +cfi=(53) +cfn=(1254) +calls=2 0 +0 40 +0 40 +cob=(4) +cfi=(113) +cfn=(1794) +calls=2 47 +0 48 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1698 +0 16 + +fn=(2068) +0 68 +cfn=(2074) +calls=2 0 +0 4764 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 984 +0 4 +cob=(7) +cfi=(53) +cfn=(880) +calls=2 0 +0 220 +0 46 +cob=(4) +cfi=(113) +cfn=(1794) +calls=2 47 +0 48 +0 8 +cob=(7) +cfi=(53) +cfn=(1254) +calls=2 0 +0 40 +0 6 +cob=(7) +cfi=(53) +cfn=(880) +calls=2 0 +0 236 +0 14 +cfn=(2096) MR::RefPtr::~RefPtr() +calls=2 0 +0 20 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 955 +0 4 +cob=(7) +cfi=(53) +cfn=(1380) +calls=2 0 +0 30 +0 10 +cfn=(2090) std::vector, std::allocator > >::_M_insert_aux(__gnu_cxx::__normal_iterator*, std::vector, std::allocator > > >, MR::RefPtr const&) +calls=2 0 +0 576 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1699 +0 2 + +fn=(2090) +0 40 +cob=(7) +cfi=(53) +cfn=(880) +calls=2 0 +0 446 +0 90 + +fn=(2096) +0 20 + +fn=(2132) +0 12 +cob=(7) +cfi=(53) +cfn=(2138) +calls=1 0 +0 44 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1506 +0 11 + +fn=(2170) +0 49 + +fn=(2742) +0 38 +cob=(7) +cfi=(53) +cfn=(880) +calls=1 0 +0 110 +0 5 +cob=(4) +cfi=(113) +cfn=(1794) +calls=1 47 +0 66 +0 7 + +fn=(2744) +0 22 + +fn=(3748) std::vector >::~vector() +0 4 + +fn=(924) +0 3 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 9 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 9 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 9 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 9 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 9 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 9 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 9 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 10 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 + +fn=(970) +0 3 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 11 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 + +fn=(1016) +0 3 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 + +fn=(1236) MR::App::App(int, char**, char const**, MR::Argument const*, MR::Option const*, unsigned long const*, char const*, char const*) +0 46 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 308 +0 5 +cob=(7) +cfi=(53) +cfn=(1242) +calls=1 0 +0 1867 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1650 +0 5 +cob=(7) +cfi=(53) +cfn=(1260) +calls=1 0 +0 28 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1506 +0 33 +cfn=(1266) +calls=1 0 +0 20 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 830 +0 2 +cob=(4) +cfi=(90) /build/buildd/eglibc-2.11.1/time/../sysdeps/unix/sysv/linux/x86_64/time.S +cfn=(1272) time +calls=1 32 +0 8 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1642 +0 2 +cob=(4) +cfi=(92) /build/buildd/eglibc-2.11.1/stdlib/random.c +cfn=(1280) srand +calls=1 211 +0 10226 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1673 +0 1 +cfn=(1290) +calls=1 0 +0 19832 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 776 +0 10 +cob=(7) +cfi=(53) +cfn=(1254) +calls=1 0 +0 20 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1426 +0 17 + +fn=(2102) +0 42 + +fn=(2300) +0 38 +cob=(7) +cfi=(53) +cfn=(880) +calls=1 0 +0 110 +0 5 +cob=(4) +cfi=(113) +cfn=(1794) +calls=1 47 +0 62 +0 7 + +fn=(2472) +0 50 +cob=(9) +cfi=(58) +cfn=(2478) +calls=2 0 +0 802 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 947 +0 8 + +fn=(2530) +0 19 +cob=(7) +cfi=(53) +cfn=(880) +calls=1 0 +0 225 +0 9 +cob=(7) +cfi=(53) +cfn=(1254) +calls=1 0 +0 20 +0 41 + +fn=(2536) +0 38 +cob=(7) +cfi=(53) +cfn=(1380) +calls=2 0 +0 115 +0 10 +cob=(7) +cfi=(53) +cfn=(1142) +calls=2 0 +0 162 +0 6 +cob=(7) +cfi=(53) +cfn=(1142) +calls=2 0 +0 162 +0 22 +cob=(7) +cfi=(53) +cfn=(1142) +calls=2 0 +0 162 + +fn=(3770) MR::Image::Format::XDS::~XDS() +0 4 + +fn=(3774) MR::Image::Format::NIfTI_GZ::~NIfTI_GZ() +0 4 + +fn=(2664) +0 60 +cob=(4) +cfi=(113) +cfn=(1794) +calls=1 47 +0 24 +0 9 +cob=(4) +cfi=(113) +cfn=(1794) +calls=1 47 +0 24 +0 11 +cob=(7) +cfi=(53) +cfn=(880) +calls=1 0 +0 180 +0 7 + +fn=(2670) +0 16 +cob=(12) +cfi=(84) +cfn=(1962) +calls=1 0 +0 389 +0 3 +cob=(7) +cfi=(53) +cfn=(1254) +calls=1 0 +0 20 +0 4 +cob=(7) +cfi=(53) +cfn=(1686) +calls=1 0 +0 326 +0 2 +cfn=(2170) +calls=1 0 +0 7 +0 13 +cob=(4) +cfi=(94) +cfn=(1296) +calls=1 37 +0 10 +0 20 +cob=(4) +cfi=(106) +cfn=(1592) open +calls=1 82 +0 7 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1697 +0 14 +cob=(4) +cfi=(103) +cfn=(1422) mmap +calls=1 82 +0 6 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1741 +0 14 +cob=(7) +cfi=(53) +cfn=(722) +calls=1 0 +0 97 +0 21 +cob=(7) +cfi=(53) +cfn=(728) +calls=1 0 +0 708 +0 16 +cob=(7) +cfi=(53) +cfn=(492) +calls=1 0 +0 39 +0 10 +cob=(7) +cfi=(53) +cfn=(728) +calls=1 0 +0 708 +0 3 +cob=(7) +cfi=(53) +cfn=(2684) +calls=1 0 +0 5000 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1600 +0 12 +cob=(12) +cfi=(84) +cfn=(2712) +calls=1 0 +0 3586 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1414 +0 8 +cob=(7) +cfi=(53) +cfn=(1260) +calls=1 0 +0 28 +0 20 +cob=(7) +cfi=(53) +cfn=(746) +calls=1 0 +0 12 +0 10 +cob=(7) +cfi=(53) +cfn=(1818) +calls=1 0 +0 58 +0 5 +cob=(7) +cfi=(53) +cfn=(722) +calls=1 0 +0 97 +0 18 +cob=(7) +cfi=(53) +cfn=(728) +calls=1 0 +0 708 +0 15 +cob=(7) +cfi=(53) +cfn=(492) +calls=1 0 +0 39 +0 9 +cob=(7) +cfi=(53) +cfn=(728) +calls=1 0 +0 708 +0 3 +cob=(7) +cfi=(53) +cfn=(2726) +calls=1 0 +0 923 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1690 +0 12 +cob=(12) +cfi=(84) +cfn=(2712) +calls=1 0 +0 200 +0 8 +cob=(7) +cfi=(53) +cfn=(1260) +calls=1 0 +0 28 +0 20 +cob=(7) +cfi=(53) +cfn=(746) +calls=1 0 +0 12 +0 8 +cob=(7) +cfi=(53) +cfn=(1818) +calls=1 0 +0 58 +0 6 +cob=(12) +cfi=(84) +cfn=(1962) +calls=1 0 +0 494 +0 4 +cob=(7) +cfi=(53) +cfn=(1254) +calls=1 0 +0 20 +0 4 +cob=(7) +cfi=(53) +cfn=(1686) +calls=1 0 +0 420 +0 6 +cob=(12) +cfi=(84) +cfn=(1350) +calls=1 0 +0 345 +0 4 +cob=(7) +cfi=(53) +cfn=(1254) +calls=1 0 +0 20 +0 4 +cob=(7) +cfi=(53) +cfn=(1686) +calls=1 0 +0 496 +0 6 +cob=(12) +cfi=(84) +cfn=(1350) +calls=1 0 +0 465 +0 4 +cob=(7) +cfi=(53) +cfn=(1254) +calls=1 0 +0 20 +0 4 +cob=(7) +cfi=(53) +cfn=(1686) +calls=1 0 +0 476 +0 4 +cob=(7) +cfi=(53) +cfn=(1254) +calls=1 0 +0 20 +0 2 +cob=(4) +cfi=(69) +cfn=(642) +calls=1 26 +0 22 +0 4 +cob=(7) +cfi=(53) +cfn=(1686) +calls=1 0 +0 370 +0 4 +cob=(7) +cfi=(53) +cfn=(1254) +calls=1 0 +0 20 +0 4 +cob=(7) +cfi=(53) +cfn=(1686) +calls=1 0 +0 649 +0 2 +cfn=(2170) +calls=1 0 +0 7 +0 54 +cob=(7) +cfi=(53) +cfn=(1308) +calls=1 0 +0 82 +0 7 +cob=(7) +cfi=(53) +cfn=(1308) +calls=1 0 +0 113 +0 7 +cob=(7) +cfi=(53) +cfn=(1308) +calls=1 0 +0 124 +0 7 +cob=(7) +cfi=(53) +cfn=(1308) +calls=1 0 +0 82 +0 7 +cob=(7) +cfi=(53) +cfn=(1308) +calls=1 0 +0 82 +0 7 +cob=(7) +cfi=(53) +cfn=(1308) +calls=1 0 +0 82 +0 7 +cob=(7) +cfi=(53) +cfn=(1308) +calls=1 0 +0 113 +0 7 +cob=(7) +cfi=(53) +cfn=(1308) +calls=1 0 +0 124 +0 7 +cob=(7) +cfi=(53) +cfn=(1308) +calls=1 0 +0 82 +0 7 +cob=(7) +cfi=(53) +cfn=(1308) +calls=1 0 +0 82 +0 7 +cob=(7) +cfi=(53) +cfn=(1308) +calls=1 0 +0 113 +0 7 +cob=(7) +cfi=(53) +cfn=(1308) +calls=1 0 +0 124 +0 7 +cob=(7) +cfi=(53) +cfn=(1308) +calls=1 0 +0 82 +0 7 +cob=(7) +cfi=(53) +cfn=(1308) +calls=1 0 +0 82 +0 74 + +fn=(856) +0 3 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 3 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 + +fn=(874) +0 8 +cob=(7) +cfi=(53) +cfn=(880) +calls=1 0 +0 62508 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1299 +0 56 + +fn=(998) +0 3 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 + +fn=(1018) +0 3 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 + +fn=(1366) MR::App::parse_arguments() +0 390 + +fn=(2034) +0 40 + +fn=(2056) +0 84 + +fn=(2342) +0 38 +cob=(7) +cfi=(53) +cfn=(880) +calls=1 0 +0 110 +0 5 +cob=(4) +cfi=(113) +cfn=(1794) +calls=1 47 +0 62 +0 7 + +fn=(2584) +0 22 + +fn=(2646) +0 44 + +fn=(3136) +0 4 +cob=(7) +cfi=(53) +cfn=(2138) +calls=2 0 +0 124 +0 8 + +fn=(3760) __tcf_0 +0 40 + +ob=(12) +fl=(84) +fn=(2992) std::vector >, std::allocator > > >::_M_insert_aux(__gnu_cxx::__normal_iterator >*, std::vector >, std::allocator > > > >, std::vector > const&) +0 5820 +cob=(7) +cfi=(53) +cfn=(880) +calls=240 0 +0 36512 +0 2640 +cfn=(2994) std::vector >::vector(std::vector > const&) +calls=240 0 +0 53056 +0 1440 +cfn=(2996) std::vector >* std::__uninitialized_move_a >*, std::vector >*, std::allocator > > >(std::vector >*, std::vector >*, std::vector >*, std::allocator > >&) +calls=240 0 +0 102311 +0 1440 +cfn=(2996) +calls=240 0 +0 5040 +0 3300 +cob=(7) +cfi=(53) +cfn=(1142) +calls=420 0 +0 34020 +0 2100 +cob=(7) +cfi=(53) +cfn=(1142) +calls=180 0 +0 14580 +0 6120 + +fn=(3478) BTS::Fibre::Tract::Tensor_tpl::init() +0 828338 +cob=(7) +cfi=(53) +cfn=(934) +calls=59167 0 +0 16345116 +0 710004 +cob=(7) +cfi=(53) +cfn=(1380) +calls=59167 0 +0 887505 +0 355002 +cob=(7) +cfi=(53) +cfn=(934) +calls=59167 0 +0 16413153 +0 591670 +cob=(7) +cfi=(53) +cfn=(2414) +calls=59167 0 +0 1005839 +0 473336 +cob=(7) +cfi=(53) +cfn=(2414) +calls=59167 0 +0 1005839 +0 355002 +cob=(7) +cfi=(53) +cfn=(1380) +calls=59167 0 +0 887505 +0 769171 +cob=(7) +cfi=(53) +cfn=(1254) +calls=59167 0 +0 1183340 +0 295835 +cfn=(3480) std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::_M_insert_unique_(std::_Rb_tree_const_iterator >, std::pair const&) +calls=59167 0 +0 18193177 +0 177501 +cob=(7) +cfi=(53) +cfn=(1380) +calls=59167 0 +0 887505 +0 295835 +cob=(7) +cfi=(53) +cfn=(1254) +calls=59167 0 +0 1183340 +0 295835 +cfn=(3480) +calls=59167 0 +0 17947063 +0 177501 +cob=(7) +cfi=(53) +cfn=(1380) +calls=59167 0 +0 887505 +0 177501 + +fn=(3484) std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::_M_insert_(std::_Rb_tree_node_base const*, std::_Rb_tree_node_base const*, std::pair const&) +0 1656676 +cob=(7) +cfi=(53) +cfn=(880) +calls=118334 0 +0 19395979 +0 710004 +cob=(7) +cfi=(53) +cfn=(1254) +calls=118334 0 +0 2366680 +0 828338 +cob=(7) +cfi=(53) +cfn=(2402) +calls=118334 0 +0 3845855 +0 1242507 + +fn=(1040) +0 11 +cob=(4) +cfi=(85) /build/buildd/eglibc-2.11.1/csu/libc-start.c +cfn=(1048) (below main) +calls=1 96 +0 1323498943661 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1850 + +fn=(1050) __libc_csu_init +0 15 +cob=(2) +cfi=(13) +cfn=(1052) +calls=1 0 +0 217031 +0 10 + +fn=(1088) global constructors keyed to basic_strand.cpp +0 5 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 324 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 323 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 10 + +fn=(1094) global constructors keyed to file.cpp +0 4 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 6 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 + +fn=(1110) global constructors keyed to flatness.cpp +0 6 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 324 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 323 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 8 + +fn=(1122) T.4971 +0 6 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 324 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 323 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 315 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 314 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 285 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 315 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 50 +cfn=(1126) MR::Option::append(MR::Argument const&) +calls=1 0 +0 1577 +0 3 +cfn=(1134) MR::Option::Option(MR::Option const&) +calls=1 0 +0 275 +0 4 +cfn=(1136) MR::Option::~Option() +calls=1 0 +0 3034 +0 23 +cfn=(1126) +calls=1 0 +0 193 +0 3 +cfn=(1134) +calls=1 0 +0 275 +0 4 +cfn=(1136) +calls=1 0 +0 85 +0 23 +cfn=(1126) +calls=1 0 +0 193 +0 3 +cfn=(1134) +calls=1 0 +0 275 +0 4 +cfn=(1136) +calls=1 0 +0 85 +0 40 +cfn=(1126) +calls=1 0 +0 193 +0 3 +cfn=(1134) +calls=1 0 +0 275 +0 4 +cfn=(1136) +calls=1 0 +0 85 +0 28 +cfn=(1126) +calls=1 0 +0 193 +0 3 +cfn=(1134) +calls=1 0 +0 275 +0 4 +cfn=(1136) +calls=1 0 +0 85 +0 28 +cfn=(1126) +calls=1 0 +0 193 +0 3 +cfn=(1134) +calls=1 0 +0 275 +0 4 +cfn=(1136) +calls=1 0 +0 85 +0 28 +cfn=(1126) +calls=1 0 +0 193 +0 3 +cfn=(1134) +calls=1 0 +0 275 +0 4 +cfn=(1136) +calls=1 0 +0 85 +0 26 +cfn=(1126) +calls=1 0 +0 193 +0 3 +cfn=(1134) +calls=1 0 +0 275 +0 4 +cfn=(1136) +calls=1 0 +0 85 +0 28 +cfn=(1126) +calls=1 0 +0 193 +0 3 +cfn=(1134) +calls=1 0 +0 275 +0 4 +cfn=(1136) +calls=1 0 +0 85 +0 40 +cfn=(1126) +calls=1 0 +0 193 +0 3 +cfn=(1134) +calls=1 0 +0 275 +0 4 +cfn=(1136) +calls=1 0 +0 85 +0 25 +cfn=(1126) +calls=1 0 +0 193 +0 3 +cfn=(1134) +calls=1 0 +0 275 +0 4 +cfn=(1136) +calls=1 0 +0 85 +0 28 +cfn=(1126) +calls=1 0 +0 193 +0 3 +cfn=(1134) +calls=1 0 +0 275 +0 4 +cfn=(1136) +calls=1 0 +0 85 +0 26 +cfn=(1126) +calls=1 0 +0 193 +0 3 +cfn=(1134) +calls=1 0 +0 275 +0 4 +cfn=(1136) +calls=1 0 +0 85 +0 40 +cfn=(1126) +calls=1 0 +0 193 +0 3 +cfn=(1134) +calls=1 0 +0 275 +0 4 +cfn=(1136) +calls=1 0 +0 85 +0 23 +cfn=(1126) +calls=1 0 +0 193 +0 3 +cfn=(1134) +calls=1 0 +0 275 +0 3 +cfn=(1136) +calls=1 0 +0 85 +0 3 +cfn=(1134) +calls=1 0 +0 44 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 8 + +fn=(1152) global constructors keyed to image_diff.cpp +0 5 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 582 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 294 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 324 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 335 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 323 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 7 + +fn=(1194) global constructors keyed to KMrand.cpp +0 7 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 6 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 324 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 323 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 + +fn=(1210) global constructors keyed to flat_top_quadratic.cpp +0 6 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 324 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 407 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 323 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 334 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 5 + +fn=(2358) +0 6377165 +cob=(7) +cfi=(53) +cfn=(880) +calls=296842 0 +0 32940630 +0 2968420 +cob=(7) +cfi=(53) +cfn=(1254) +calls=296842 0 +0 5936810 +0 1781052 +cfn=(2360) std::string* std::__uninitialized_move_a >(std::string*, std::string*, std::string*, std::allocator&) +calls=296842 0 +0 10036694 +0 1781052 +cfn=(2360) +calls=296842 0 +0 5046314 +0 2368152 +cob=(7) +cfi=(53) +cfn=(1380) +calls=146775 0 +0 2201593 +0 6 +cob=(7) +cfi=(53) +cfn=(1380) +calls=2 0 +0 14 +0 1180788 +cob=(7) +cfi=(53) +cfn=(1142) +calls=146775 0 +0 11888775 +0 6520648 + +fn=(2620) MR::Math::Matrix::Matrix(MR::Math::Matrix const&) +0 3322 +cob=(9) +cfi=(58) +cfn=(1868) gsl_block_alloc +calls=2 0 +0 3070 +0 8 + +fn=(2972) BTS::Diffusion::Model::init(MR::Math::Matrix const&, MR::Math::Matrix const&, bool) +0 39 +cfn=(2862) MR::Math::Vector::initialize(unsigned long) +calls=1 0 +0 233 +0 180 +cfn=(2862) +calls=60 0 +0 13980 +0 2565 +cfn=(2862) +calls=61 0 +0 14415 +0 5607 +cfn=(2862) +calls=54 0 +0 12582 +0 4726 +cob=(9) +cfi=(58) +cfn=(2626) gsl_block_free +calls=61 0 +0 10065 +0 244 +cob=(9) +cfi=(58) +cfn=(2626) +calls=61 0 +0 10065 +0 672 +cfn=(2862) +calls=60 0 +0 13980 +0 2760 +cfn=(2978) BTS::Diffusion::Model::SH_to_coeffs(MR::Math::Vector, bool) +calls=60 0 +0 514373 +0 4440 +cob=(9) +cfi=(58) +cfn=(2626) +calls=60 0 +0 9900 +0 240 +cob=(9) +cfi=(58) +cfn=(2626) +calls=60 0 +0 9900 +0 180 +cob=(9) +cfi=(58) +cfn=(2626) +calls=60 0 +0 9900 +0 300 +cob=(9) +cfi=(58) +cfn=(1868) +calls=60 0 +0 12720 +0 328 +cfn=(2974) std::vector >::_M_insert_aux(__gnu_cxx::__normal_iterator > >, BTS::Diffusion::Response const&) +calls=7 0 +0 51005 +0 7 + +fn=(3008) BTS::Image::Expected::Buffer_tpl::Buffer_tpl(BTS::Triple const&, BTS::Triple const&, BTS::Diffusion::Model const&, unsigned int, unsigned int, double, BTS::Triple const&, bool) +0 60 +cfn=(3010) BTS::Diffusion::Model::Model(BTS::Diffusion::Model const&) +calls=1 0 +0 33518 +0 16 +cob=(6) +cfi=(134) /build/buildd/eglibc-2.11.1/math/../sysdeps/ieee754/dbl-64/s_ceil.c +cfn=(3016) ceil +calls=1 44 +0 24 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1398 +0 5 +cfn=(3018) std::_Rb_tree, std::allocator > >, std::_Select1st, std::allocator > > >, std::less, std::allocator, std::allocator > > > >::_M_erase(std::_Rb_tree_node, std::allocator > > >*) +calls=1 0 +0 11 +0 12 + +fn=(3018) +0 22 + +fn=(3060) BTS::Image::Expected::Buffer_tpl::Buffer_tpl(BTS::Image::Expected::Buffer_tpl const&) +0 50 +cfn=(3010) +calls=1 0 +0 30128 +0 14 +cob=(6) +cfi=(134) +cfn=(3016) +calls=1 44 +0 24 +0 5 +cfn=(3018) +calls=1 0 +0 11 +0 10 + +fn=(3228) __gnu_cxx::__normal_iterator > > std::__find<__gnu_cxx::__normal_iterator > >, std::string>(__gnu_cxx::__normal_iterator > >, __gnu_cxx::__normal_iterator > >, std::string const&, std::random_access_iterator_tag) +0 148 + +fn=(3232) BTS::Fibre::Properties::Extended::add_properties(BTS::Fibre::Properties::Header const&, std::vector > const&) +0 33 + +fn=(3234) BTS::Fibre::Base::Reader::next(BTS::Fibre::Tract&, BTS::Fibre::Properties&) +0 65 +cfn=(2618) +calls=5 0 +0 55 +0 40 +cfn=(3236) BTS::Fibre::Base::Reader::next_basic(BTS::Fibre::Tract&) +calls=5 0 +0 29380 +0 108 +cob=(7) +cfi=(53) +cfn=(1638) +calls=4 0 +0 1857 +0 36 +cfn=(3258) BTS::Fibre::Properties::Extended::parse_line(std::string const&) +calls=4 0 +0 17571 +0 60 +cfn=(3260) std::map, std::allocator > >::operator[](std::string const&) +calls=4 0 +0 1516 +0 24 +cfn=(3260) +calls=4 0 +0 1734 +0 24 +cob=(7) +cfi=(53) +cfn=(1260) +calls=8 0 +0 224 +0 72 +cfn=(2374) +calls=4 0 +0 548 +0 8 +cob=(7) +cfi=(53) +cfn=(1380) +calls=4 0 +0 400 +0 16 +cfn=(3262) BTS::Fibre::Tract::set_intrinsic_properties(BTS::Fibre::Properties&) +calls=4 0 +0 32537 +0 44 + +fn=(3274) BTS::Fibre::Tract::~Tract() +0 1302902048 +cob=(7) +cfi=(53) +cfn=(1142) +calls=125886783 0 +0 10196829423 +0 546471371 +cob=(7) +cfi=(53) +cfn=(1142) +calls=42036260 0 +0 3404937060 +0 252217560 +cfn=(3230) std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::_M_erase(std::_Rb_tree_node >*) +calls=42036260 0 +0 17571156680 +0 252217560 + +fn=(3308) double BTS::Prob::Likelihood::ImageDiff::log_prob_tpl(BTS::Fibre::Tract::Set const&, BTS::Fibre::Tract::Set&, BTS::Fibre::Tract::Set::Tensor&) +0 18 +cfn=(3310) BTS::Image::Expected::Quartic::Buffer::expected_image(BTS::Fibre::Tract::Set const&, std::vector, std::allocator > >&, std::vector, std::allocator > >&) +calls=1 0 +0 1321052384417 +0 10 +cfn=(2618) +calls=1 0 +0 554 +0 13 +cfn=(2564) +calls=1 0 +0 759 +0 40 +cfn=(3462) std::vector >::operator=(std::vector > const&) +calls=1 0 +0 1321 +0 5 +cfn=(2366) +calls=1 0 +0 45 +0 5 +cfn=(2366) +calls=1 0 +0 45 +0 5 +cfn=(3552) std::vector >, std::allocator > > >::operator=(std::vector >, std::allocator > > > const&) +calls=1 0 +0 58 +0 10 +cfn=(3086) std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::_M_erase(std::_Rb_tree_node >*) +calls=1 0 +0 11 +0 20 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 375 +0 4 +cfn=(3298) std::map, std::allocator > >::operator[](std::string const&) +calls=1 0 +0 102 +0 5 +cob=(7) +cfi=(53) +cfn=(1380) +calls=1 0 +0 100 +0 2 +cfn=(3554) unsigned int BTS::Fibre::Unzipper::size >(BTS::Fibre::Set const&) +calls=1 0 +0 10608 +0 3 +cfn=(3554) +calls=1 0 +0 9432 +0 5 +cfn=(3360) MR::Math::Matrix::initialize(unsigned long, unsigned long) +calls=1 0 +0 3909 +0 96767 +cfn=(3368) MR::Math::Matrix::operator=(MR::Math::Matrix const&) +calls=1 0 +0 97602 +0 4 +cob=(9) +cfi=(58) +cfn=(2626) +calls=1 0 +0 216 +0 97119 +cfn=(3554) +calls=1 0 +0 9512 +0 35 +cfn=(3556) unsigned int BTS::Fibre::Unzipper::size(BTS::Fibre::Tract const&) +calls=1 0 +0 2086 +0 18 +cfn=(3556) +calls=3 0 +0 6258 +0 82 +cfn=(3558) std::vector >::_M_insert_aux(__gnu_cxx::__normal_iterator > >, unsigned int const&) +calls=3 0 +0 940 +0 12 +cfn=(3558) +calls=3 0 +0 940 +0 23 +cfn=(3560) BTS::Image::Expected::Quartic::Buffer::dim(unsigned int) const +calls=1 0 +0 3 +0 15 +cfn=(3560) +calls=3 0 +0 9 +0 29 +cfn=(3560) +calls=3 0 +0 9 +0 45 +cfn=(3560) +calls=9 0 +0 27 +0 78 +cfn=(3560) +calls=9 0 +0 27 +0 135 +cfn=(3560) +calls=27 0 +0 81 +0 207 +cfn=(3316) BTS::Image::Expected::Quartic::Buffer::num_encodings() const +calls=27 0 +0 162 +0 6588 +cfn=(3316) +calls=1647 0 +0 9882 +0 14877 +cfn=(3562) BTS::Image::Expected::Quartic::Buffer::operator()(int, int, int) +calls=1647 0 +0 269130 +0 23058 +cfn=(2784) BTS::Image::Buffer_tpl::operator()(BTS::Image::Coord const&) +calls=1647 0 +0 206790 +0 16470 +cfn=(3564) BTS::Prob::Likelihood::ImageDiff::Gaussian::log_prob(double, double&, double&) +calls=1647 0 +0 11529 +0 60939 +cfn=(3224) BTS::Fibre::Tract::Tract() +calls=1647 0 +0 3158642 +0 14823 +cob=(7) +cfi=(53) +cfn=(880) +calls=1647 0 +0 1423098 +0 44469 +cfn=(3268) BTS::Fibre::Tract::Tract(BTS::Fibre::Tract const&) +calls=6588 0 +0 10973424 +0 32940 +cfn=(3274) +calls=1647 0 +0 909144 +0 41175 +cob=(7) +cfi=(53) +cfn=(934) +calls=1647 0 +0 385398 +0 6588 +cfn=(3298) +calls=1647 0 +0 523746 +0 8235 +cob=(7) +cfi=(53) +cfn=(1380) +calls=1647 0 +0 24705 +0 9882 +cfn=(2618) +calls=1647 0 +0 18117 +0 6588 +cfn=(3360) +calls=1647 0 +0 3350624 +0 159879963 +cfn=(3448) BTS::Image::Buffer_tpl >::operator()(BTS::Image::Coord const&) +calls=4453 0 +0 562786 +0 44530 +cfn=(3466) std::vector >::operator=(std::vector > const&) +calls=4453 0 +0 3037739 +0 115778 +cfn=(3486) BTS::Image::Buffer_tpl >::operator()(BTS::Image::Coord const&) +calls=4453 0 +0 562786 +0 22265 +cfn=(3566) BTS::Fibre::Flattener::flatten(BTS::Fibre::Tract::Tensor const&) +calls=4453 0 +0 894404448 +0 80803650 +cob=(9) +cfi=(58) +cfn=(2626) +calls=4453 0 +0 903959 +0 65880 +cfn=(3596) MR::Math::Vector BTS::Fibre::Unzipper::unzip >(BTS::Fibre::Set const&) +calls=1647 0 +0 43329093 +0 6588 +cfn=(3596) +calls=1647 0 +0 43171713 +0 6588 +cfn=(3604) MR::Math::Matrix BTS::Math::outer(MR::Math::Vector const&, MR::Math::Vector const&) +calls=1647 0 +0 212664361 +0 6588 +cob=(9) +cfi=(58) +cfn=(2626) +calls=1647 0 +0 312930 +0 6588 +cob=(9) +cfi=(58) +cfn=(2626) +calls=1647 0 +0 312930 +0 928710360 +cob=(7) +cfi=(53) +cfn=(880) +calls=1647 0 +0 545706 +0 49410 +cfn=(3268) +calls=6588 0 +0 15235177 +0 36234 +cfn=(3606) BTS::Fibre::Properties::Extended::Extended(BTS::Fibre::Properties::Extended const&) +calls=1647 0 +0 191052 +0 8235 +cob=(7) +cfi=(53) +cfn=(934) +calls=1647 0 +0 546804 +0 6588 +cfn=(3298) +calls=1647 0 +0 713151 +0 8235 +cob=(7) +cfi=(53) +cfn=(1380) +calls=1647 0 +0 24705 +0 4183380 +cfn=(3302) BTS::Fibre::Properties::Extended::~Extended() +calls=1647 0 +0 92232 +0 4941 +cfn=(3608) std::vector >::~vector() +calls=1647 0 +0 5497686 +0 6588 +cfn=(2618) +calls=1647 0 +0 18117 +0 11529 +cfn=(3230) +calls=1647 0 +0 354105 +0 6588 +cob=(9) +cfi=(58) +cfn=(2626) +calls=1647 0 +0 2411147 +0 6588 +cob=(9) +cfi=(58) +cfn=(2626) +calls=1647 0 +0 576450 +0 9882 +cfn=(3302) +calls=1647 0 +0 92232 +0 4941 +cfn=(3608) +calls=1647 0 +0 5497686 +0 6588 +cfn=(2618) +calls=1647 0 +0 18117 +0 9882 +cfn=(3230) +calls=1647 0 +0 354105 +0 106201 +cob=(7) +cfi=(53) +cfn=(880) +calls=2135 0 +0 244610 +0 68320 +cob=(7) +cfi=(53) +cfn=(880) +calls=2135 0 +0 244610 +0 136640 +cob=(7) +cfi=(53) +cfn=(880) +calls=6405 0 +0 733830 +0 333060 +cob=(7) +cfi=(53) +cfn=(1142) +calls=2135 0 +0 172935 +0 10675 +cob=(7) +cfi=(53) +cfn=(934) +calls=2135 0 +0 485865 +0 8540 +cfn=(3298) +calls=2135 0 +0 688690 +0 10675 +cob=(7) +cfi=(53) +cfn=(1380) +calls=2135 0 +0 32025 +0 10675 +cob=(7) +cfi=(53) +cfn=(934) +calls=2135 0 +0 488000 +0 8540 +cfn=(3298) +calls=2135 0 +0 864980 +0 10675 +cob=(7) +cfi=(53) +cfn=(1380) +calls=2135 0 +0 32025 +0 12810 +cfn=(3466) +calls=2135 0 +0 1461865 +0 12810 +cfn=(3274) +calls=2135 0 +0 1703730 +0 154728 +cob=(7) +cfi=(53) +cfn=(1142) +calls=1 0 +0 81 +0 6 +cob=(7) +cfi=(53) +cfn=(1142) +calls=1 0 +0 81 +0 10 + +fn=(3318) std::vector, std::allocator > >::_M_insert_aux(__gnu_cxx::__normal_iterator*, std::vector, std::allocator > > >, BTS::Image::Container::Buffer const&) +0 71 +cob=(7) +cfi=(53) +cfn=(880) +calls=3 0 +0 5746 +0 27 +cfn=(3320) BTS::Image::Container::Buffer::Buffer(BTS::Image::Container::Buffer const&) +calls=3 0 +0 96 +0 18 +cfn=(3322) BTS::Image::Container::Buffer* std::__uninitialized_move_a*, BTS::Image::Container::Buffer*, std::allocator > >(BTS::Image::Container::Buffer*, BTS::Image::Container::Buffer*, BTS::Image::Container::Buffer*, std::allocator >&) +calls=3 0 +0 33697569 +0 18 +cfn=(3322) +calls=3 0 +0 51 +0 32 +cfn=(3324) std::_Rb_tree >, std::_Select1st > >, std::less, std::allocator > > >::_M_erase(std::_Rb_tree_node > >*) +calls=2 0 +0 6898379 +0 4 +cfn=(3324) +calls=1 0 +0 4040576 +0 19 +cob=(7) +cfi=(53) +cfn=(1142) +calls=2 0 +0 200 +0 84 + +fn=(3370) BTS::Fibre::Strand::create_tangent_matrix(unsigned int, unsigned int, bool) +0 14 +cfn=(3360) +calls=1 0 +0 473 +0 215 +cob=(6) +cfi=(137) /build/buildd/eglibc-2.11.1/math/../sysdeps/ieee754/dbl-64/s_sin.c +cfn=(3376) sin +calls=2 90 +0 94 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1416 +0 290 +cob=(6) +cfi=(137) +cfn=(3376) +calls=58 90 +0 6746 +0 503 + +fn=(3390) std::map, std::allocator >, std::less, std::allocator, std::allocator > > > >::operator[](BTS::Image::Coord const&) +0 8043657 +cfn=(3392) std::_Rb_tree, std::allocator > >, std::_Select1st, std::allocator > > >, std::less, std::allocator, std::allocator > > > >::_M_insert_unique_(std::_Rb_tree_const_iterator, std::allocator > > >, std::pair, std::allocator > > const&) +calls=102 0 +0 29252 +0 408 +cfn=(3398) std::_Rb_tree, std::less, std::allocator >::_M_erase(std::_Rb_tree_node*) +calls=102 0 +0 1122 +0 306 +cfn=(3398) +calls=102 0 +0 1122 +0 332910 + +fn=(3400) BTS::Image::Expected::Buffer_tpl::create_neighbourhood(BTS::Image::Coord const&) +0 14178 +cfn=(3402) BTS::Image::Buffer_tpl::operator()(BTS::Image::Coord const&) +calls=816 0 +0 5724569 +0 29173 +cob=(7) +cfi=(53) +cfn=(2818) +calls=126 0 +0 2020 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 2037 +0 4458 +cfn=(3438) std::_Rb_tree, std::less, std::allocator >::_M_insert_(std::_Rb_tree_node_base const*, std::_Rb_tree_node_base const*, BTS::Image::Expected::Quartic::Voxel* const&) +calls=816 0 +0 175908 +0 1734 + +fn=(3402) +0 227111 +cfn=(3404) non-virtual thunk to BTS::Image::Expected::Quartic::Buffer::new_voxel(BTS::Image::Coord const&) +calls=237 0 +0 3580939 +0 145134 +cfn=(3422) BTS::Image::Expected::Quartic::Voxel::Voxel() +calls=237 0 +0 101673 +0 1896 +cfn=(3424) BTS::Image::Expected::Voxel::Voxel(BTS::Image::Expected::Voxel const&) +calls=237 0 +0 123714 +0 2133 +cfn=(3426) std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::_M_insert_unique_(std::_Rb_tree_const_iterator >, std::pair const&) +calls=237 0 +0 269512 +0 711 +cfn=(3432) BTS::Image::Expected::Quartic::Voxel::~Voxel() +calls=237 0 +0 37920 +0 474 +cfn=(3432) +calls=237 0 +0 37920 +0 948 +cfn=(3436) BTS::Image::Expected::Voxel::operator=(BTS::Image::Expected::Voxel const&) +calls=237 0 +0 1350211 +0 1185 +cfn=(3432) +calls=237 0 +0 95761 +0 1634 + +fn=(3424) +0 16590 +cob=(4) +cfi=(113) +cfn=(1794) +calls=474 47 +0 11376 +0 41712 +cfn=(3414) BTS::Fibre::Strand::Section::Tensor::Tensor() +calls=474 0 +0 171114 +0 6636 + +fn=(3426) +0 4339 +cob=(7) +cfi=(53) +cfn=(2812) +calls=208 0 +0 3317 +0 1500 +cfn=(3430) std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::_M_insert_(std::_Rb_tree_node_base const*, std::_Rb_tree_node_base const*, std::pair const&) +calls=92 0 +0 102131 +0 2148 +cfn=(3428) std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::_M_insert_unique(std::pair const&) +calls=1 0 +0 841 +0 41 +cfn=(3430) +calls=3 0 +0 2627 +0 2138 +cfn=(3430) +calls=141 0 +0 150282 +0 148 + +fn=(3432) +0 19197 +cfn=(3434) BTS::Fibre::Strand::Section::~Section() +calls=711 0 +0 10665 +0 2844 +cfn=(3434) +calls=711 0 +0 10665 +0 2133 +cfn=(3434) +calls=711 0 +0 10665 +0 2844 +cfn=(3434) +calls=711 0 +0 10665 +0 2844 +cfn=(3434) +calls=711 0 +0 10665 +0 2133 +cfn=(3434) +calls=711 0 +0 10665 +0 8769 +cob=(7) +cfi=(53) +cfn=(1142) +calls=237 0 +0 27753 +0 5925 +cob=(7) +cfi=(53) +cfn=(1142) +calls=237 0 +0 29851 +0 3318 + +fn=(3460) BTS::Image::Container::Voxel::~Voxel() +0 13505 +cfn=(3274) +calls=365 0 +0 201480 +0 65700 +cfn=(3274) +calls=21900 0 +0 12088800 +0 71540 +cob=(7) +cfi=(53) +cfn=(1142) +calls=365 0 +0 39462 +0 2920 + +fn=(3494) BTS::Fibre::Tract::Tensor_tpl::~Tensor_tpl() +0 516628 +cfn=(3476) BTS::Fibre::BasicStrand::Tensor_tpl::~Tensor_tpl() +calls=36902 0 +0 105416928 +0 147608 +cfn=(3476) +calls=73804 0 +0 210841873 +0 479726 +cob=(7) +cfi=(53) +cfn=(1142) +calls=36902 0 +0 2989062 +0 73804 +cfn=(3274) +calls=36902 0 +0 23880816 +0 73804 +cfn=(3274) +calls=36902 0 +0 23880816 +0 221412 +cfn=(3496) std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::_M_erase(std::_Rb_tree_node >*) +calls=36902 0 +0 15425036 +0 147608 + +fn=(3496) +0 405922 +cfn=(3497) std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::_M_erase(std::_Rb_tree_node >*)'2 +calls=36902 0 +0 405922 +0 110706 +cfn=(3497) +calls=36902 0 +0 405922 +0 221412 +cob=(7) +cfi=(53) +cfn=(1380) +calls=73804 0 +0 7380400 +0 221412 +cob=(7) +cfi=(53) +cfn=(1142) +calls=73804 0 +0 5978124 +0 295216 + +fn=(3497) +0 811844 + +fn=(3528) BTS::Triple::zero() +0 22586880 +cfn=(3526) T.2795 +calls=1328640 0 +0 3985920 +0 2657280 +cfn=(3526) +calls=1328640 0 +0 3985920 +0 15943680 +cfn=(3526) +calls=1328640 0 +0 3985920 +0 2657280 +cfn=(3526) +calls=1328640 0 +0 3985920 +0 15943680 +cfn=(3526) +calls=1328640 0 +0 3985920 +0 2657280 +cfn=(3526) +calls=1328640 0 +0 3985920 +0 7971840 + +fn=(3532) BTS::Image::Expected::Direction::signal_hessian(BTS::Fibre::Strand::Section const&, BTS::Fibre::Strand::Section::Tensor&, double, double, BTS::Triple const&, BTS::Fibre::Strand::Section const&, BTS::Coord::Tensor const&, BTS::Fibre::Strand::Section::Tensor const&) +0 4822298880 +cfn=(3380) BTS::Triple::outer(BTS::Triple const&) const +calls=40523520 0 +0 1580417280 +0 202617600 +cfn=(3380) +calls=40523520 0 +0 1580417280 +0 3849734400 +cfn=(3380) +calls=40523520 0 +0 1580417280 +0 2188270080 + +fn=(3566) +0 44530 +cfn=(3304) unsigned int BTS::Fibre::Properties::Intrinsic::num_intrinsic_keys() +calls=4453 0 +0 9344346 +0 262727 +cfn=(3360) +calls=4453 0 +0 13108534 +0 22265 +cfn=(3568) void BTS::Fibre::Flattener::flatten_intrinsic(BTS::Fibre::Tract::Tensor const&, MR::Math::Matrix&, unsigned int&) +calls=4453 0 +0 75638658 +0 325069 +cfn=(3594) BTS::Fibre::Flattener::flatten_element(BTS::Fibre::Tract const&, MR::Math::Matrix&, unsigned int&) +calls=13359 0 +0 88744569 +0 213744 +cfn=(3594) +calls=26718 0 +0 176466656 +0 160308 +cfn=(3594) +calls=40077 0 +0 264781175 +0 160308 +cfn=(3594) +calls=40077 0 +0 264623917 +0 507642 + +fn=(3584) MR::Math::Vector::Vector(unsigned long) +0 1033096 +cob=(9) +cfi=(58) +cfn=(1868) +calls=129137 0 +0 29323188 +0 1678781 + +fn=(3590) BTS::Fibre::Properties::Intrinsic_tpl::intrinsic_property(std::string const&) const +0 6026556 +cob=(7) +cfi=(53) +cfn=(2414) +calls=284626 0 +0 7257963 +0 863760 +cob=(7) +cfi=(53) +cfn=(2414) +calls=287920 0 +0 7240822 +0 3011631 +cob=(7) +cfi=(53) +cfn=(2414) +calls=287920 0 +0 9660143 +0 2591280 + +fn=(3694) std::_Rb_tree, std::less, std::allocator > > > >, std::_Select1st, std::less, std::allocator > > > > >, std::less, std::allocator, std::less, std::allocator > > > > > >::_M_erase(std::_Rb_tree_node, std::less, std::allocator > > > > >*) +0 29 +cfn=(3695) std::_Rb_tree, std::less, std::allocator > > > >, std::_Select1st, std::less, std::allocator > > > > >, std::less, std::allocator, std::less, std::allocator > > > > > >::_M_erase(std::_Rb_tree_node, std::less, std::allocator > > > > >*)'2 +calls=2 0 +0 22 +0 8 +cfn=(3348) std::_Rb_tree >, std::_Select1st > >, std::less, std::allocator > > >::_M_erase(std::_Rb_tree_node > >*) +calls=2 0 +0 614 +0 6 +cob=(7) +cfi=(53) +cfn=(1142) +calls=2 0 +0 162 +0 16 + +fn=(3695) +0 22 + +fn=(2996) +0 13620 +cob=(7) +cfi=(53) +cfn=(880) +calls=420 0 +0 51851 +0 5460 +cob=(4) +cfi=(113) +cfn=(1794) +calls=420 47 +0 28560 +0 7860 + +fn=(3476) +0 1931149 +cfn=(3274) +calls=129543 0 +0 103375314 +0 518172 +cfn=(3274) +calls=129543 0 +0 103375314 +0 388629 +cfn=(3274) +calls=129543 0 +0 103375314 +0 980928 +cob=(7) +cfi=(53) +cfn=(1142) +calls=43181 0 +0 4591645 +0 407340 + +fn=(3482) std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::_M_insert_unique(std::pair const&) +0 1597509 +cfn=(3484) +calls=59167 0 +0 14938992 +0 295835 + +fn=(1092) global constructors keyed to sheer.cpp +0 6 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 324 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 323 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 315 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 14 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 324 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 323 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 313 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 8 + +fn=(1102) global constructors keyed to uniform.cpp +0 6 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 324 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 323 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 313 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 8 + +fn=(1112) global constructors keyed to set.cpp +0 6 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 324 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 323 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 315 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 312 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 32 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 324 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 323 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 10 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 324 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 323 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 315 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 33 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 324 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 323 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 27 + +fn=(1114) global constructors keyed to roi.cpp +0 3 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 + +fn=(1170) global constructors keyed to prior.cpp +0 5 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 324 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 323 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 + +fn=(1200) global constructors keyed to common.cpp +0 3 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 5 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 324 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 323 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 + +fn=(1202) global constructors keyed to KMterm.cpp +0 7 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 6 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 324 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 323 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 + +fn=(1948) std::vector >::_M_insert_aux(__gnu_cxx::__normal_iterator > >, BTS::Diffusion::Encoding const&) +0 288 +cob=(7) +cfi=(53) +cfn=(880) +calls=14 0 +0 11522 +0 2238 +cob=(7) +cfi=(53) +cfn=(1142) +calls=12 0 +0 1259 +0 286 + +fn=(1962) +0 80 +cob=(4) +cfi=(69) +cfn=(642) +calls=8 26 +0 194 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1690 +0 72 +cob=(7) +cfi=(53) +cfn=(1338) +calls=8 0 +0 1696 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1450 +0 32 +cob=(7) +cfi=(53) +cfn=(1686) +calls=8 0 +0 535 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1508 +0 24 +cob=(7) +cfi=(53) +cfn=(1360) +calls=8 0 +0 659 +0 56 + +fn=(2360) +0 7111050 +cob=(7) +cfi=(53) +cfn=(1254) +calls=146777 0 +0 2935510 +0 5036448 + +fn=(2396) std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::_M_insert_(std::_Rb_tree_node_base const*, std::_Rb_tree_node_base const*, std::pair const&) +0 561 +cob=(7) +cfi=(53) +cfn=(880) +calls=7 0 +0 786 +0 76 +cob=(7) +cfi=(53) +cfn=(880) +calls=38 0 +0 6059 +0 315 +cob=(7) +cfi=(53) +cfn=(1254) +calls=45 0 +0 900 +0 135 +cob=(7) +cfi=(53) +cfn=(1254) +calls=45 0 +0 755 +0 225 +cob=(7) +cfi=(53) +cfn=(2402) +calls=45 0 +0 4077 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 2251 +0 1325 + +fn=(2436) MR::Image::Axes::Axis* std::__uninitialized_move_a >(MR::Image::Axes::Axis*, MR::Image::Axes::Axis*, MR::Image::Axes::Axis*, std::allocator&) +0 42 + +fn=(2610) +0 16 +cob=(11) +cfi=(60) +cfn=(2834) +calls=1 0 +0 5972 +0 25 +cob=(7) +cfi=(53) +cfn=(1380) +calls=1 0 +0 100 +0 10 +cob=(7) +cfi=(53) +cfn=(1142) +calls=1 0 +0 81 +0 8 +cob=(9) +cfi=(58) +cfn=(2494) +calls=2 0 +0 407 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 947 +0 14 +cfn=(2616) MR::Image::Axes::Axis::~Axis() +calls=2 0 +0 46 +0 12 +cfn=(2616) +calls=6 0 +0 138 +0 32 +cob=(7) +cfi=(53) +cfn=(1142) +calls=2 0 +0 162 +0 8 +cob=(9) +cfi=(58) +cfn=(2494) +calls=2 0 +0 330 +0 4 +cob=(7) +cfi=(53) +cfn=(1380) +calls=2 0 +0 22 +0 6 +cfn=(2618) +calls=2 0 +0 4360 +0 8 + +fn=(2712) +0 45 +cob=(7) +cfi=(53) +cfn=(952) +calls=3 0 +0 419 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1682 +0 24 +cob=(4) +cfi=(81) +cfn=(966) +calls=3 56 +0 62 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1708 +0 30 + +fn=(2802) std::vector >::operator=(std::vector > const&) +0 10032 +cob=(7) +cfi=(53) +cfn=(880) +calls=264 0 +0 80881 +0 1320 +cob=(4) +cfi=(113) +cfn=(1794) +calls=264 47 +0 56760 +0 1848 + +fn=(2854) BTS::Diffusion::Model::factory(MR::Math::Matrix const&, MR::Math::Matrix const&, double, double, bool) +0 23 +cob=(7) +cfi=(53) +cfn=(1142) +calls=1 0 +0 114 +0 15 +cfn=(2856) BTS::Diffusion::Model::Model(MR::Math::Matrix const&, double, double, bool) +calls=1 0 +0 7042633 +0 3 +cfn=(2998) std::vector >::operator=(std::vector > const&) +calls=1 0 +0 30988 +0 249 +cob=(9) +cfi=(58) +cfn=(2626) +calls=61 0 +0 10065 +0 185 + +fn=(2998) +0 48 +cob=(7) +cfi=(53) +cfn=(880) +calls=1 0 +0 1475 +0 921 +cfn=(2862) +calls=61 0 +0 23202 +0 5342 + +fn=(3006) BTS::Image::Expected::Quartic::Buffer::Buffer(BTS::Triple const&, BTS::Triple const&, BTS::Diffusion::Model const&, unsigned int, unsigned int, double, BTS::Triple const&, bool) +0 14 +cfn=(3008) +calls=1 0 +0 35044 +0 7 +cfn=(3020) BTS::Image::Expected::Quartic::Buffer::init() +calls=1 0 +0 1757 +0 4 + +fn=(3066) BTS::Prob::Likelihood::ImageDiff::set_assumed_snr(double) +0 8 +cfn=(3068) BTS::Image::Observed::Buffer::average_b0() const +calls=1 0 +0 39375 +0 13 + +fn=(3202) MR::DWI::Tractography::ROISet::~ROISet() +0 80 + +fn=(3258) +0 48 +cob=(7) +cfi=(53) +cfn=(722) +calls=4 0 +0 388 +0 88 +cob=(7) +cfi=(53) +cfn=(728) +calls=4 0 +0 2832 +0 64 +cob=(7) +cfi=(53) +cfn=(492) +calls=4 0 +0 156 +0 36 +cob=(7) +cfi=(53) +cfn=(1752) +calls=4 0 +0 849 +0 24 +cob=(7) +cfi=(53) +cfn=(1758) +calls=4 0 +0 84 +0 12 +cob=(7) +cfi=(53) +cfn=(728) +calls=4 0 +0 2832 +0 48 +cob=(7) +cfi=(53) +cfn=(1638) +calls=4 0 +0 1742 +0 32 +cob=(7) +cfi=(53) +cfn=(1638) +calls=8 0 +0 4556 +0 56 +cob=(7) +cfi=(53) +cfn=(1380) +calls=4 0 +0 400 +0 36 +cob=(7) +cfi=(53) +cfn=(1380) +calls=4 0 +0 400 +0 20 +cob=(7) +cfi=(53) +cfn=(746) +calls=4 0 +0 48 +0 36 +cob=(7) +cfi=(53) +cfn=(1818) +calls=4 0 +0 232 +0 92 +cfn=(2358) +calls=8 0 +0 2452 +0 8 + +fn=(3268) +0 46038408 +cob=(7) +cfi=(53) +cfn=(880) +calls=1180472 0 +0 210832492 +0 96636444 +cob=(7) +cfi=(53) +cfn=(880) +calls=3120882 0 +0 364021629 +0 206125588 +cfn=(3226) BTS::Fibre::Tract::init() +calls=1180472 0 +0 1700719310 +0 9443776 + +fn=(3302) +0 79112 +cob=(7) +cfi=(53) +cfn=(1380) +calls=9889 0 +0 69223 +0 29667 +cfn=(3086) +calls=9889 0 +0 108779 +0 267003 + +fn=(3316) +0 247137132 + +fn=(3320) +0 96 + +fn=(3354) std::_Rb_tree >, std::_Select1st > >, std::less, std::allocator > > >::_M_insert_unique(std::pair > const&) +0 50 +cfn=(3356) std::_Rb_tree >, std::_Select1st > >, std::less, std::allocator > > >::_M_insert_(std::_Rb_tree_node_base const*, std::_Rb_tree_node_base const*, std::pair > const&) +calls=2 0 +0 510 +0 4 + +fn=(3410) BTS::Image::Expected::Voxel::Voxel(BTS::Image::Expected::Buffer&, BTS::Image::Coord const&, BTS::Diffusion::Model&) +0 4503 +cfn=(3412) BTS::Image::Observed::Voxel::Voxel(unsigned int, BTS::Image::Coord const&) +calls=237 0 +0 180915 +0 12798 +cfn=(3414) +calls=237 0 +0 85557 +0 379437 +cfn=(3420) std::vector >::_M_insert_aux(__gnu_cxx::__normal_iterator > >, BTS::Image::Expected::Direction const&) +calls=1659 0 +0 2905405 +0 6873 + +fn=(3418) T.6698 +0 1458880848 + +fn=(3434) +0 4255033605 + +fn=(3458) std::_Rb_tree >, std::_Select1st > >, std::less, std::allocator > > >::_M_insert_(std::_Rb_tree_node_base const*, std::_Rb_tree_node_base const*, std::pair > const&) +0 4968 +cob=(7) +cfi=(53) +cfn=(880) +calls=196 0 +0 33269 +0 338 +cob=(7) +cfi=(53) +cfn=(880) +calls=169 0 +0 28733 +0 14965 +cob=(7) +cfi=(53) +cfn=(2402) +calls=365 0 +0 26531 +0 6580 + +fn=(3464) BTS::Fibre::Tract* std::__uninitialized_copy_a<__gnu_cxx::__normal_iterator > >, BTS::Fibre::Tract*, BTS::Fibre::Tract>(__gnu_cxx::__normal_iterator > >, __gnu_cxx::__normal_iterator > >, BTS::Fibre::Tract*, std::allocator&) +0 116070 +cfn=(3268) +calls=22265 0 +0 39778251 +0 114245 + +fn=(3486) +0 50780717 +cfn=(3488) BTS::Image::Container::Buffer::new_voxel(BTS::Image::Coord const&) +calls=365 0 +0 126124096 +0 30274212 +cfn=(3498) BTS::Image::Container::Voxel::Voxel(BTS::Image::Container::Voxel const&) +calls=365 0 +0 16425 +0 1460 +cfn=(3500) std::_Rb_tree >, std::_Select1st > >, std::less, std::allocator > > >::_M_insert_unique_(std::_Rb_tree_const_iterator > >, std::pair > const&) +calls=365 0 +0 139111 +0 1095 +cfn=(3506) BTS::Image::Container::Voxel::~Voxel() +calls=365 0 +0 6570 +0 730 +cfn=(3506) +calls=365 0 +0 6570 +0 1095 +cfn=(3508) std::vector >::operator=(std::vector > const&) +calls=365 0 +0 120856035 +0 2190 +cfn=(3506) +calls=365 0 +0 38230928 +0 2159 + +fn=(3506) +0 13505 +cfn=(3512) BTS::Fibre::Tract::Tensor::~Tensor() +calls=365 0 +0 623785 +0 65700 +cfn=(3512) +calls=21900 0 +0 37427100 +0 71540 +cob=(7) +cfi=(53) +cfn=(1142) +calls=365 0 +0 39518 +0 2920 + +fn=(3524) BTS::Triple::norm(BTS::Triple&, BTS::Coord::Tensor&) const +0 41187840 + +fn=(3538) BTS::Fibre::Strand::Strand(BTS::Fibre::Strand const&) +0 9725644800 +cob=(7) +cfi=(53) +cfn=(880) +calls=324188160 0 +0 35660698704 +0 24314112000 +cob=(7) +cfi=(53) +cfn=(934) +calls=324188160 0 +0 72293986929 +0 3241881600 +cob=(7) +cfi=(53) +cfn=(1254) +calls=324188160 0 +0 6483763200 +0 1620940800 +cfn=(3078) std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::_M_insert_unique_(std::_Rb_tree_const_iterator >, std::pair const&) +calls=324188160 0 +0 80723019959 +0 972564480 +cob=(7) +cfi=(53) +cfn=(1380) +calls=324188160 0 +0 4862822400 +0 1620940800 +cob=(7) +cfi=(53) +cfn=(1380) +calls=324188160 0 +0 4862822400 +0 2593505280 + +fn=(3546) BTS::Fibre::Tract::Section::~Section() +0 1245600 + +fn=(3568) +0 57889 +cfn=(3570) std::vector > BTS::Fibre::Properties::Intrinsic_tpl::intrinsic_keys() +calls=4453 0 +0 12054271 +0 75701 +cfn=(3572) void std::__introsort_loop<__gnu_cxx::__normal_iterator > >, long>(__gnu_cxx::__normal_iterator > >, __gnu_cxx::__normal_iterator > >, long) +calls=4453 0 +0 93513 +0 13359 +cfn=(3574) void std::__final_insertion_sort<__gnu_cxx::__normal_iterator > > >(__gnu_cxx::__normal_iterator > >, __gnu_cxx::__normal_iterator > >) +calls=4453 0 +0 890600 +0 31171 +cfn=(3580) BTS::Fibre::Properties::Intrinsic_tpl::intrinsic_property(std::string const&) const +calls=4453 0 +0 574437 +0 13359 +cfn=(3580) +calls=4453 0 +0 561078 +0 26718 +cfn=(3582) MR::Math::Vector BTS::Fibre::Unzipper::unzip(BTS::Fibre::Tract const&) +calls=8906 0 +0 56388339 +0 1727764 +cob=(9) +cfi=(58) +cfn=(2626) +calls=8906 0 +0 1692140 +0 35624 +cfn=(2374) +calls=4453 0 +0 1367071 +0 35624 + +fn=(3574) +0 1500600 +cfn=(3576) void std::__insertion_sort<__gnu_cxx::__normal_iterator > > >(__gnu_cxx::__normal_iterator > >, __gnu_cxx::__normal_iterator > >) +calls=150060 0 +0 27224178 +0 750300 + +fn=(3582) +0 903959 +cfn=(3556) +calls=129137 0 +0 281167910 +0 387411 +cfn=(3584) +calls=129137 0 +0 32035065 +0 645685 +cfn=(3586) void BTS::Fibre::Unzipper::unzip_element(BTS::Fibre::Tract const&, MR::Math::Vector&, unsigned int&) +calls=129137 0 +0 487607465 +0 645685 + +fn=(3604) +0 18117 +cfn=(3360) +calls=1647 0 +0 6049858 +0 206596386 + +fn=(3704) +0 18 + +fn=(2994) +0 6900 +cob=(7) +cfi=(53) +cfn=(880) +calls=300 0 +0 33016 +0 3900 +cob=(4) +cfi=(113) +cfn=(1794) +calls=300 47 +0 20400 +0 2100 + +fn=(1156) global constructors keyed to section.cpp +0 6 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 324 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 323 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 9 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 315 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 18 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 324 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 323 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 9 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 12 + +fn=(1164) global constructors keyed to gaussian.cpp +0 5 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 407 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 324 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 323 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 + +fn=(1182) global constructors keyed to KMfilterCenters.cpp +0 7 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 6 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 324 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 323 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 + +fn=(1198) global constructors keyed to model.cpp +0 5 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 324 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 407 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 323 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 + +fn=(1208) global constructors keyed to midpoint_in_cube.cpp +0 6 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 324 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 323 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 8 + +fn=(1214) global constructors keyed to distribution.cpp +0 3 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 + +fn=(1512) MR::Math::Matrix::load(std::string const&) +0 16 +cob=(7) +cfi=(53) +cfn=(722) +calls=1 0 +0 97 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1491 +0 22 +cob=(7) +cfi=(53) +cfn=(728) +calls=1 0 +0 708 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 2322 +0 7 +cob=(7) +cfi=(53) +cfn=(1526) +calls=1 0 +0 4123 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1938 +0 3 +cob=(7) +cfi=(53) +cfn=(728) +calls=1 0 +0 708 +0 4 +cob=(7) +cfi=(53) +cfn=(1550) +calls=1 0 +0 11370 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 2282 +0 7 +cob=(7) +cfi=(53) +cfn=(1630) +calls=1 0 +0 8 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 2154 +0 5 +cfn=(1632) MR::Math::operator>>(std::istream&, MR::Math::Matrix&) +calls=1 0 +0 787989 +0 9 +cob=(7) +cfi=(53) +cfn=(1880) +calls=1 0 +0 10007 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 2010 +0 2 +cob=(7) +cfi=(53) +cfn=(1940) +calls=1 0 +0 17 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1619 +0 5 +cob=(7) +cfi=(53) +cfn=(746) +calls=1 0 +0 12 +0 9 +cob=(7) +cfi=(53) +cfn=(1818) +calls=1 0 +0 58 +0 12 + +fn=(1946) BTS::Diffusion::Encoding::Set::set(MR::Math::Matrix const&) +0 6294 +cfn=(1948) +calls=14 0 +0 15593 +0 72 + +fn=(2434) void std::__uninitialized_fill_n_a(MR::Image::Axes::Axis*, unsigned long, MR::Image::Axes::Axis const&, std::allocator&) +0 65 +cob=(7) +cfi=(53) +cfn=(1254) +calls=4 0 +0 60 +0 12 +cob=(7) +cfi=(53) +cfn=(1254) +calls=4 0 +0 60 +0 24 + +fn=(2552) +0 40 +cob=(7) +cfi=(53) +cfn=(1880) +calls=2 0 +0 1284 +0 4 +cob=(7) +cfi=(53) +cfn=(1940) +calls=2 0 +0 34 +0 10 +cob=(7) +cfi=(53) +cfn=(746) +calls=2 0 +0 24 +0 24 +cob=(7) +cfi=(53) +cfn=(1818) +calls=2 0 +0 116 +0 60 +cob=(7) +cfi=(53) +cfn=(1308) +calls=2 0 +0 164 +0 12 +cob=(7) +cfi=(53) +cfn=(1308) +calls=1 0 +0 82 +0 25 + +fn=(2786) BTS::Image::Observed::Buffer::new_voxel(BTS::Image::Coord const&) +0 81 +cfn=(2788) BTS::Image::Observed::Voxel::Voxel(BTS::Image::Observed::Buffer&, BTS::Image::Coord const&) +calls=27 0 +0 15370 +0 81 + +fn=(2792) BTS::Image::Observed::Voxel::Voxel(BTS::Image::Observed::Voxel const&) +0 864 +cob=(4) +cfi=(113) +cfn=(1794) +calls=27 47 +0 648 +0 594 + +fn=(2858) MR::Math::Matrix::Matrix(unsigned long, unsigned long) +0 7105 +cob=(9) +cfi=(58) +cfn=(1868) +calls=245 0 +0 100407 +0 1225 + +fn=(2862) +0 4392 +cob=(9) +cfi=(58) +cfn=(1868) +calls=549 0 +0 147975 +0 7137 + +fn=(2978) +0 7680 +cob=(6) +cfi=(131) /build/buildd/eglibc-2.11.1/math/w_pow.c +cfn=(2984) pow +calls=300 29 +0 75780 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1382 +0 2640 +cob=(7) +cfi=(53) +cfn=(1142) +calls=60 0 +0 4860 +0 300 +cob=(7) +cfi=(53) +cfn=(880) +calls=60 0 +0 6600 +0 1320 +cob=(7) +cfi=(53) +cfn=(1142) +calls=60 0 +0 4860 +0 300 +cob=(7) +cfi=(53) +cfn=(880) +calls=60 0 +0 6600 +0 1320 +cob=(7) +cfi=(53) +cfn=(1142) +calls=60 0 +0 4860 +0 300 +cob=(7) +cfi=(53) +cfn=(880) +calls=60 0 +0 6600 +0 1380 +cfn=(2994) +calls=60 0 +0 13260 +0 420 +cob=(7) +cfi=(53) +cfn=(1142) +calls=60 0 +0 4860 +0 300 +cob=(7) +cfi=(53) +cfn=(880) +calls=60 0 +0 6600 +0 1320 +cob=(7) +cfi=(53) +cfn=(1142) +calls=60 0 +0 4860 +0 13740 +cfn=(2862) +calls=60 0 +0 13980 +0 17160 +cob=(7) +cfi=(53) +cfn=(1142) +calls=300 0 +0 24300 +0 1140 +cob=(7) +cfi=(53) +cfn=(1142) +calls=60 0 +0 7072 +0 1020 +cob=(7) +cfi=(53) +cfn=(880) +calls=60 0 +0 6600 +0 1260 +cfn=(2992) +calls=60 0 +0 70446 +0 420 +cfn=(2992) +calls=60 0 +0 51498 +0 420 +cfn=(2992) +calls=60 0 +0 119132 +0 420 +cfn=(2992) +calls=60 0 +0 27303 +0 60 + +fn=(3000) BTS::Image::Expected::Buffer::factory(std::string const&, BTS::Triple const&, BTS::Triple const&, BTS::Diffusion::Model const&, unsigned int, unsigned int, double, BTS::Triple const&, bool, double) +0 19 +cob=(7) +cfi=(53) +cfn=(2138) +calls=1 0 +0 44 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1506 +0 14 +cob=(7) +cfi=(53) +cfn=(2138) +calls=1 0 +0 44 +0 5 +cob=(7) +cfi=(53) +cfn=(2138) +calls=1 0 +0 64 +0 4 +cob=(7) +cfi=(53) +cfn=(880) +calls=1 0 +0 383 +0 13 +cfn=(3006) +calls=1 0 +0 36826 +0 1 + +fn=(3064) BTS::Image::Expected::Quartic::Buffer::dims() const +0 2 + +fn=(3106) BTS::Fibre::Base::Reader::open(std::string const&) +0 12 +cob=(7) +cfi=(53) +cfn=(1260) +calls=1 0 +0 28 +0 35 +cfn=(3108) MR::DWI::Tractography::Reader::open(std::string const&, MR::DWI::Tractography::Properties&) +calls=1 0 +0 63571 +0 6 +cfn=(2618) +calls=1 0 +0 11 +0 10 +cfn=(2564) +calls=1 0 +0 1161 +0 33 +cfn=(3174) std::basic_string, std::allocator > std::operator+, std::allocator >(std::basic_string, std::allocator > const&, char const*) +calls=1 0 +0 400 +0 4 +cob=(7) +cfi=(53) +cfn=(1254) +calls=1 0 +0 20 +0 4 +cob=(4) +cfi=(94) +cfn=(1296) +calls=1 37 +0 10 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1738 +0 8 +cob=(7) +cfi=(53) +cfn=(1380) +calls=1 0 +0 15 +0 7 +cob=(7) +cfi=(53) +cfn=(1550) +calls=1 0 +0 1097 +0 7 +cob=(7) +cfi=(53) +cfn=(1630) +calls=1 0 +0 8 +0 4 +cfn=(3180) BTS::Fibre::Properties::Extended::read_header(std::basic_ifstream >&) +calls=1 0 +0 9832 +0 3 +cfn=(2366) +calls=1 0 +0 248 +0 2 +cfn=(3198) BTS::Fibre::Properties::Header::~Header() +calls=1 0 +0 137 +0 2 +cob=(7) +cfi=(53) +cfn=(1380) +calls=1 0 +0 100 +0 2 +cfn=(3200) MR::DWI::Tractography::Properties::~Properties() +calls=1 0 +0 820 +0 8 + +fn=(3108) +0 16 +cfn=(2618) +calls=1 0 +0 11 +0 15 +cfn=(3110) MR::DWI::Tractography::ROISet::clear() +calls=1 0 +0 21 +0 2 +cfn=(3110) +calls=1 0 +0 21 +0 2 +cfn=(3110) +calls=1 0 +0 21 +0 11 +cfn=(2618) +calls=1 0 +0 11 +0 15 +cob=(7) +cfi=(53) +cfn=(722) +calls=1 0 +0 97 +0 22 +cob=(7) +cfi=(53) +cfn=(728) +calls=1 0 +0 708 +0 7 +cob=(7) +cfi=(53) +cfn=(1526) +calls=1 0 +0 265 +0 3 +cob=(7) +cfi=(53) +cfn=(728) +calls=1 0 +0 708 +0 4 +cob=(11) +cfi=(60) +cfn=(2168) +calls=1 0 +0 3344 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1096 +0 29 +cob=(11) +cfi=(60) +cfn=(2202) +calls=1 0 +0 3546 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 992 +0 14 +cob=(11) +cfi=(60) +cfn=(2202) +calls=7 0 +0 21528 +0 65 +cob=(7) +cfi=(53) +cfn=(2220) +calls=7 0 +0 1770 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1516 +0 42 +cob=(7) +cfi=(53) +cfn=(1326) +calls=7 0 +0 84 +0 84 +cob=(4) +cfi=(124) +cfn=(2234) +calls=7 47 +0 84 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1724 +0 177 +cob=(4) +cfi=(124) +cfn=(2234) +calls=59 47 +0 708 +0 299 +cob=(7) +cfi=(53) +cfn=(2138) +calls=7 0 +0 350 +0 84 +cob=(7) +cfi=(53) +cfn=(1308) +calls=7 0 +0 574 +0 35 +cob=(7) +cfi=(53) +cfn=(2138) +calls=7 0 +0 310 +0 42 +cob=(7) +cfi=(53) +cfn=(2138) +calls=7 0 +0 319 +0 18 +cob=(7) +cfi=(53) +cfn=(1260) +calls=1 0 +0 28 +0 25 +cob=(7) +cfi=(53) +cfn=(2138) +calls=6 0 +0 318 +0 233 +cob=(7) +cfi=(53) +cfn=(1260) +calls=5 0 +0 140 +0 9 +cob=(11) +cfi=(60) +cfn=(2454) +calls=1 0 +0 2002 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 984 +0 26 +cob=(7) +cfi=(53) +cfn=(1254) +calls=5 0 +0 1052 +0 15 +cob=(7) +cfi=(53) +cfn=(1254) +calls=5 0 +0 75 +0 20 +cfn=(2392) +calls=5 0 +0 1581 +0 15 +cob=(7) +cfi=(53) +cfn=(1380) +calls=5 0 +0 35 +0 10 +cob=(7) +cfi=(53) +cfn=(1380) +calls=5 0 +0 75 +0 36 +cob=(7) +cfi=(53) +cfn=(722) +calls=1 0 +0 97 +0 22 +cob=(7) +cfi=(53) +cfn=(728) +calls=1 0 +0 708 +0 16 +cob=(7) +cfi=(53) +cfn=(492) +calls=1 0 +0 39 +0 9 +cob=(7) +cfi=(53) +cfn=(1752) +calls=1 0 +0 196 +0 6 +cob=(7) +cfi=(53) +cfn=(1758) +calls=1 0 +0 21 +0 3 +cob=(7) +cfi=(53) +cfn=(728) +calls=1 0 +0 708 +0 6 +cob=(7) +cfi=(53) +cfn=(2504) +calls=1 0 +0 557 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 2395 +0 6 +cob=(7) +cfi=(53) +cfn=(2272) +calls=1 0 +0 500 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1664 +0 3 +cob=(7) +cfi=(53) +cfn=(2138) +calls=1 0 +0 52 +0 5 +cob=(7) +cfi=(53) +cfn=(1260) +calls=1 0 +0 123 +0 5 +cob=(7) +cfi=(53) +cfn=(1550) +calls=1 0 +0 1274 +0 8 +cob=(7) +cfi=(53) +cfn=(1630) +calls=1 0 +0 8 +0 9 +cob=(7) +cfi=(53) +cfn=(3150) +calls=1 0 +0 4647 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1754 +0 13 +cob=(7) +cfi=(53) +cfn=(1380) +calls=1 0 +0 100 +0 5 +cob=(7) +cfi=(53) +cfn=(746) +calls=1 0 +0 12 +0 11 +cob=(7) +cfi=(53) +cfn=(1818) +calls=1 0 +0 58 +0 6 +cfn=(2552) +calls=1 0 +0 908 +0 18 +cob=(7) +cfi=(53) +cfn=(1308) +calls=1 0 +0 82 +0 44 + +fn=(3180) +0 11 +cfn=(3182) BTS::Fibre::Properties::Extended::read_preamble(std::basic_ifstream >&) +calls=1 0 +0 4258 +0 23 +cob=(7) +cfi=(53) +cfn=(1638) +calls=1 0 +0 557 +0 7 +cob=(7) +cfi=(53) +cfn=(722) +calls=1 0 +0 97 +0 25 +cob=(7) +cfi=(53) +cfn=(728) +calls=1 0 +0 708 +0 16 +cob=(7) +cfi=(53) +cfn=(492) +calls=1 0 +0 39 +0 9 +cob=(7) +cfi=(53) +cfn=(1752) +calls=1 0 +0 374 +0 6 +cob=(7) +cfi=(53) +cfn=(1758) +calls=1 0 +0 21 +0 3 +cob=(7) +cfi=(53) +cfn=(728) +calls=1 0 +0 708 +0 14 +cob=(7) +cfi=(53) +cfn=(1638) +calls=1 0 +0 605 +0 8 +cob=(7) +cfi=(53) +cfn=(1638) +calls=2 0 +0 1261 +0 14 +cob=(7) +cfi=(53) +cfn=(1380) +calls=1 0 +0 100 +0 10 +cob=(7) +cfi=(53) +cfn=(1380) +calls=1 0 +0 100 +0 5 +cob=(7) +cfi=(53) +cfn=(746) +calls=1 0 +0 12 +0 11 +cob=(7) +cfi=(53) +cfn=(1818) +calls=1 0 +0 58 +0 2 +cob=(7) +cfi=(53) +cfn=(1380) +calls=1 0 +0 100 +0 23 +cfn=(2358) +calls=2 0 +0 645 +0 2 + +fn=(3220) BTS::Fibre::Properties::Header::Header(BTS::Fibre::Properties::Header const&) +0 25 +cob=(7) +cfi=(53) +cfn=(880) +calls=1 0 +0 110 +0 22 +cob=(7) +cfi=(53) +cfn=(1254) +calls=2 0 +0 40 +0 20 + +fn=(3298) +0 1459182768 +cob=(7) +cfi=(53) +cfn=(1254) +calls=81061197 0 +0 1621223940 +0 405305985 +cfn=(3078) +calls=81061197 0 +0 20184566834 +0 243183591 +cob=(7) +cfi=(53) +cfn=(1380) +calls=81061197 0 +0 1215917955 +0 648493856 + +fn=(3300) BTS::Fibre::Set::~Set() +0 59337 +cfn=(3302) +calls=6593 0 +0 369208 +0 65930 +cfn=(2618) +calls=6593 0 +0 72523 +0 39558 +cfn=(3230) +calls=6593 0 +0 1137505 +0 26390 +cfn=(3302) +calls=2 0 +0 112 +0 32 +cfn=(3274) +calls=8 0 +0 6384 +0 32 +cob=(7) +cfi=(53) +cfn=(1142) +calls=2 0 +0 212 +0 6 +cfn=(2618) +calls=2 0 +0 1788 +0 12 +cfn=(3230) +calls=2 0 +0 430 +0 8 + +fn=(3314) non-virtual thunk to BTS::Image::Expected::Quartic::Buffer::num_encodings() const +0 82375696 +cfn=(3316) +calls=41187848 0 +0 247127088 + +fn=(3338) std::vector >::reserve(unsigned long) +0 152 +cob=(7) +cfi=(53) +cfn=(880) +calls=4 0 +0 131574383 +0 24 +cfn=(3340) BTS::Fibre::Tract::Section* std::__uninitialized_copy_a(BTS::Fibre::Tract::Section*, BTS::Fibre::Tract::Section*, BTS::Fibre::Tract::Section*, std::allocator&) +calls=4 0 +0 16 +0 76 + +fn=(3346) std::_Rb_tree, std::less, std::allocator > > > >, std::_Select1st, std::less, std::allocator > > > > >, std::less, std::allocator, std::less, std::allocator > > > > > >::_M_insert_(std::_Rb_tree_node_base const*, std::_Rb_tree_node_base const*, std::pair, std::less, std::allocator > > > > const&) +0 26 +cob=(7) +cfi=(53) +cfn=(880) +calls=2 0 +0 639 +0 38 +cob=(7) +cfi=(53) +cfn=(2402) +calls=2 0 +0 60 +0 22 + +fn=(3368) +0 99846 +cob=(9) +cfi=(58) +cfn=(1868) +calls=2 0 +0 638 +0 10 + +fn=(3382) BTS::Image::Expected::Buffer_tpl::get_neighbourhood(BTS::Triple) +0 996480 +cob=(6) +cfi=(138) /build/buildd/eglibc-2.11.1/math/../sysdeps/ieee754/dbl-64/s_floor.c +cfn=(3388) floor +calls=83040 44 +0 2999044 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1422 +0 415200 +cob=(6) +cfi=(138) +cfn=(3388) +calls=83040 44 +0 3022106 +0 498240 +cob=(6) +cfi=(138) +cfn=(3388) +calls=83040 44 +0 3021468 +0 747360 +cfn=(3390) +calls=83040 0 +0 8398253 +0 913950 +cfn=(3400) +calls=102 0 +0 5954077 +0 306 +cfn=(3390) +calls=102 0 +0 10524 +0 612 +cfn=(3398) +calls=102 0 +0 1122 +0 1122 +cfn=(3446) std::_Rb_tree, std::less, std::allocator >::_M_copy(std::_Rb_tree_node const*, std::_Rb_tree_node*) +calls=102 0 +0 198290 +0 3646 +cfn=(3398) +calls=102 0 +0 84014 +0 102 + +fn=(3392) +0 1827 +cob=(7) +cfi=(53) +cfn=(2812) +calls=76 0 +0 1272 +0 645 +cfn=(3396) std::_Rb_tree, std::allocator > >, std::_Select1st, std::allocator > > >, std::less, std::allocator, std::allocator > > > >::_M_insert_(std::_Rb_tree_node_base const*, std::_Rb_tree_node_base const*, std::pair, std::allocator > > const&) +calls=53 0 +0 11955 +0 899 +cfn=(3394) std::_Rb_tree, std::allocator > >, std::_Select1st, std::allocator > > >, std::less, std::allocator, std::allocator > > > >::_M_insert_unique(std::pair, std::allocator > > const&) +calls=1 0 +0 467 +0 763 +cfn=(3396) +calls=48 0 +0 11376 +0 48 + +fn=(3438) +0 10914 +cob=(7) +cfi=(53) +cfn=(880) +calls=102 0 +0 12082 +0 1428 +cob=(7) +cfi=(53) +cfn=(880) +calls=714 0 +0 88322 +0 8160 +cob=(7) +cfi=(53) +cfn=(2402) +calls=816 0 +0 41640 +0 13362 + +fn=(3446) +0 831420 +cob=(7) +cfi=(53) +cfn=(880) +calls=83142 0 +0 9155443 +0 1330272 +cfn=(3447) std::_Rb_tree, std::less, std::allocator >::_M_copy(std::_Rb_tree_node const*, std::_Rb_tree_node*)'2 +calls=83142 0 +0 33913001 +0 665136 +cob=(7) +cfi=(53) +cfn=(880) +calls=83142 0 +0 9156203 +0 214782 +cob=(7) +cfi=(53) +cfn=(880) +calls=107391 0 +0 11826603 +0 2901353 +cfn=(3447) +calls=106106 0 +0 21229613 +0 1450232 + +fn=(3447) +0 2981660 +cob=(7) +cfi=(53) +cfn=(880) +calls=298166 0 +0 32838335 +0 3988880 +cfn=(3447) +calls=102722 0 +0 18067905 +0 1341520 +cob=(7) +cfi=(53) +cfn=(880) +calls=86075 0 +0 9478254 +0 14440 +cob=(7) +cfi=(53) +cfn=(880) +calls=7220 0 +0 795368 +0 1237619 +cfn=(3447) +calls=6196 0 +0 881073 +0 2466538 + +fn=(3452) BTS::Image::Container::Voxel::Voxel(BTS::Image::Container::Voxel const&) +0 16425 + +fn=(3462) +0 9899 +cfn=(3466) +calls=1 0 +0 302 +0 15 +cfn=(3466) +calls=3 0 +0 906 +0 6989 +cob=(7) +cfi=(53) +cfn=(880) +calls=365 0 +0 273198 +0 2190 +cfn=(3464) +calls=365 0 +0 40008566 +0 4380 + +fn=(3466) +0 42570640 +cfn=(3468) std::vector, std::allocator > >::operator=(std::vector, std::allocator > > const&) +calls=1064266 0 +0 286326374 +0 10642660 +cfn=(3468) +calls=2128532 0 +0 572810668 +0 25542384 + +fn=(3518) BTS::Coord::Tensor_tpl* std::__uninitialized_copy_a<__gnu_cxx::__normal_iterator const*, std::vector, std::allocator > > >, BTS::Coord::Tensor_tpl*, BTS::Coord::Tensor_tpl >(__gnu_cxx::__normal_iterator const*, std::vector, std::allocator > > >, __gnu_cxx::__normal_iterator const*, std::vector, std::allocator > > >, BTS::Coord::Tensor_tpl*, std::allocator >&) +0 1870260 +cfn=(3472) BTS::Coord::Tensor_tpl::Tensor_tpl(BTS::Coord::Tensor_tpl const&) +calls=200385 0 +0 3261110391 +0 1536285 + +fn=(3602) std::vector > BTS::Fibre::Properties::Intrinsic_tpl::intrinsic_keys >() +0 62586 +cfn=(3296) T.2918 +calls=3294 0 +0 2078514 +0 9882 +cfn=(2618) +calls=3294 0 +0 36234 +0 19764 +cob=(7) +cfi=(53) +cfn=(2824) +calls=3294 0 +0 59292 +0 36234 +cfn=(2358) +calls=3294 0 +0 768478 +0 9882 +cfn=(3300) +calls=3294 0 +0 744444 +0 23058 + +fn=(3686) std::_Rb_tree, std::allocator > >, std::_Select1st, std::allocator > > >, std::less, std::allocator, std::allocator > > > >::_M_erase(std::_Rb_tree_node, std::allocator > > >*) +0 11 + +fn=(3690) BTS::Image::Observed::Buffer::~Buffer() +0 16 +cfn=(2618) +calls=1 0 +0 11 +0 6 +cfn=(2628) std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::_M_erase(std::_Rb_tree_node >*) +calls=1 0 +0 15 +0 4 + +fn=(1096) global constructors keyed to curvature.cpp +0 6 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 324 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 323 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 407 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 310 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 8 + +fn=(1104) global constructors keyed to base_intensity.cpp +0 5 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 324 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 323 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 + +fn=(1128) std::vector >::_M_insert_aux(__gnu_cxx::__normal_iterator > >, MR::Argument const&) +0 300 +cob=(7) +cfi=(53) +cfn=(880) +calls=15 0 +0 1735 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1299 +0 750 + +fn=(1174) global constructors keyed to log.cpp +0 6 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 324 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 323 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 323 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 5 + +fn=(1212) global constructors keyed to end_in_sphere.cpp +0 6 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 324 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 323 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 318 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 8 + +fn=(1218) global constructors keyed to KCtree.cpp +0 7 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 6 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 324 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 323 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 2 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 + +fn=(1632) +0 842 +cob=(7) +cfi=(53) +cfn=(1638) +calls=62 0 +0 40729 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 2531 +0 926 +cob=(7) +cfi=(53) +cfn=(1702) +calls=61 0 +0 3225 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1500 +0 305 +cob=(7) +cfi=(53) +cfn=(1708) +calls=61 0 +0 13781 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1434 +0 305 +cob=(7) +cfi=(53) +cfn=(1726) +calls=61 0 +0 2989 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1722 +0 488 +cob=(7) +cfi=(53) +cfn=(1732) +calls=61 0 +0 3111 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1690 +0 549 +cob=(7) +cfi=(53) +cfn=(1708) +calls=61 0 +0 13803 +0 183 +cob=(7) +cfi=(53) +cfn=(1260) +calls=61 0 +0 7503 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1506 +0 854 +cob=(7) +cfi=(53) +cfn=(880) +calls=61 0 +0 6853 +0 366 +cob=(7) +cfi=(53) +cfn=(880) +calls=61 0 +0 6837 +0 1333 +cob=(7) +cfi=(53) +cfn=(722) +calls=61 0 +0 5917 +0 1708 +cob=(7) +cfi=(53) +cfn=(728) +calls=61 0 +0 43188 +0 976 +cob=(7) +cfi=(53) +cfn=(492) +calls=61 0 +0 2379 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1459 +0 549 +cob=(7) +cfi=(53) +cfn=(1752) +calls=61 0 +0 12966 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1514 +0 366 +cob=(7) +cfi=(53) +cfn=(1758) +calls=61 0 +0 1281 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 2194 +0 183 +cob=(7) +cfi=(53) +cfn=(728) +calls=61 0 +0 43188 +0 732 +cob=(7) +cfi=(53) +cfn=(1764) +calls=61 0 +0 2806 +0 732 +cob=(7) +cfi=(53) +cfn=(1764) +calls=244 0 +0 411346 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1656 +0 2196 +cfn=(1788) std::vector >::_M_insert_aux(__gnu_cxx::__normal_iterator > >, double const&) +calls=183 0 +0 73905 +0 2247 +cob=(7) +cfi=(53) +cfn=(746) +calls=61 0 +0 732 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1483 +0 671 +cob=(7) +cfi=(53) +cfn=(1818) +calls=61 0 +0 5928 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1515 +0 3504 +cob=(7) +cfi=(53) +cfn=(1326) +calls=61 0 +0 732 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1538 +0 857 +cob=(7) +cfi=(53) +cfn=(1142) +calls=61 0 +0 4941 +0 122 +cob=(7) +cfi=(53) +cfn=(1142) +calls=61 0 +0 4941 +0 183 +cob=(7) +cfi=(53) +cfn=(1142) +calls=61 0 +0 4941 +0 127 +cob=(7) +cfi=(53) +cfn=(1142) +calls=1 0 +0 114 +0 42 +cfn=(1742) std::vector >, false>, std::allocator >, false> > >::_M_insert_aux(__gnu_cxx::__normal_iterator >, false>*, std::vector >, false>, std::allocator >, false> > > >, MR::RefPtr >, false> const&) +calls=7 0 +0 4123 +0 13 +cob=(9) +cfi=(58) +cfn=(1868) +calls=1 0 +0 2575 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 859 +0 372 +cob=(7) +cfi=(53) +cfn=(1308) +calls=61 0 +0 5002 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1682 +0 1159 +cob=(7) +cfi=(53) +cfn=(1308) +calls=61 0 +0 5002 +0 427 +cob=(7) +cfi=(53) +cfn=(1308) +calls=61 0 +0 5002 +0 549 + +fn=(2294) +0 90 +cob=(7) +cfi=(53) +cfn=(880) +calls=3 0 +0 404 +0 45 +cob=(4) +cfi=(113) +cfn=(1794) +calls=3 47 +0 146 +0 24 +cob=(4) +cfi=(113) +cfn=(1794) +calls=3 47 +0 72 +0 11 +cob=(7) +cfi=(53) +cfn=(1142) +calls=2 0 +0 162 +0 44 + +fn=(2432) +0 38 +cob=(7) +cfi=(53) +cfn=(880) +calls=1 0 +0 166 +0 11 +cfn=(2434) +calls=1 0 +0 221 +0 6 +cfn=(2436) +calls=1 0 +0 21 +0 8 +cfn=(2436) +calls=1 0 +0 21 +0 31 + +fn=(2564) +0 72 +cob=(7) +cfi=(53) +cfn=(880) +calls=6 0 +0 676 +0 42 +cob=(7) +cfi=(53) +cfn=(1254) +calls=6 0 +0 120 +0 18 +cob=(7) +cfi=(53) +cfn=(1254) +calls=6 0 +0 120 +0 66 +cfn=(2565) std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::_M_copy(std::_Rb_tree_node > const*, std::_Rb_tree_node >*)'2 +calls=6 0 +0 5249 +0 48 +cob=(7) +cfi=(53) +cfn=(880) +calls=6 0 +0 889 +0 2 +cob=(7) +cfi=(53) +cfn=(880) +calls=1 0 +0 166 +0 49 +cob=(7) +cfi=(53) +cfn=(1254) +calls=7 0 +0 140 +0 21 +cob=(7) +cfi=(53) +cfn=(1254) +calls=7 0 +0 140 +0 72 +cfn=(2565) +calls=4 0 +0 1144 +0 86 + +fn=(2565) +0 252 +cob=(7) +cfi=(53) +cfn=(880) +calls=21 0 +0 3481 +0 147 +cob=(7) +cfi=(53) +cfn=(1254) +calls=21 0 +0 420 +0 63 +cob=(7) +cfi=(53) +cfn=(1254) +calls=21 0 +0 420 +0 183 +cfn=(2565) +calls=9 0 +0 5072 +0 84 +cob=(7) +cfi=(53) +cfn=(880) +calls=3 0 +0 498 +0 4 +cob=(7) +cfi=(53) +cfn=(880) +calls=2 0 +0 332 +0 35 +cob=(7) +cfi=(53) +cfn=(1254) +calls=5 0 +0 100 +0 15 +cob=(7) +cfi=(53) +cfn=(1254) +calls=5 0 +0 100 +0 48 +cfn=(2565) +calls=2 0 +0 494 +0 211 + +fn=(2616) +0 40 +cob=(7) +cfi=(53) +cfn=(1380) +calls=8 0 +0 56 +0 32 +cob=(7) +cfi=(53) +cfn=(1380) +calls=8 0 +0 56 + +fn=(2632) MR::Image::Voxel::Voxel(MR::Image::Header const&) +0 24 +cob=(7) +cfi=(53) +cfn=(880) +calls=1 0 +0 126 +0 26 +cob=(11) +cfi=(60) +cfn=(2638) +calls=1 0 +0 57609 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1144 +0 24 + +fn=(2784) +0 283147 +cfn=(2786) +calls=27 0 +0 15532 +0 131840 +cfn=(2792) +calls=27 0 +0 2106 +0 108 +cfn=(2794) std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::_M_insert_unique_(std::_Rb_tree_const_iterator >, std::pair const&) +calls=27 0 +0 16891 +0 81 +cfn=(2800) BTS::Image::Observed::Voxel::~Voxel() +calls=27 0 +0 189 +0 54 +cfn=(2800) +calls=27 0 +0 189 +0 81 +cfn=(2802) +calls=27 0 +0 12723 +0 486 +cfn=(2800) +calls=27 0 +0 3510 +0 102 + +fn=(2790) BTS::Image::Observed::Buffer::num_encodings() const +0 108 + +fn=(2800) +0 513 +cob=(7) +cfi=(53) +cfn=(1142) +calls=27 0 +0 3321 +0 54 + +fn=(3010) +0 56 +cob=(7) +cfi=(53) +cfn=(880) +calls=2 0 +0 6271 +0 1612 +cob=(9) +cfi=(58) +cfn=(1868) +calls=122 0 +0 44541 +0 11166 + +fn=(3048) BTS::Prob::Likelihood::factory(std::string const&, BTS::Image::Observed::Buffer const&, BTS::Image::Expected::Buffer*, double, bool, double) +0 13 +cob=(7) +cfi=(53) +cfn=(2138) +calls=1 0 +0 59 +0 4 +cob=(7) +cfi=(53) +cfn=(880) +calls=1 0 +0 393 +0 8 +cfn=(3050) BTS::Prob::Likelihood::ImageDiff::ImageDiff(BTS::Image::Observed::Buffer const&, BTS::Image::Expected::Buffer*, double, bool, double) +calls=1 0 +0 89393 +0 10 + +fn=(3050) +0 17 +cfn=(3052) BTS::Image::Observed::Buffer::Buffer(BTS::Image::Observed::Buffer const&) +calls=1 0 +0 19378 +0 3 +cfn=(3056) BTS::Image::Expected::Quartic::Buffer::clone() const +calls=1 0 +0 30524 +0 17 +cfn=(3062) BTS::Image::Expected::Buffer::dims_match(BTS::Image::Observed::Buffer const&) +calls=1 0 +0 25 +0 5 +cfn=(3066) +calls=1 0 +0 39396 +0 3 +cfn=(3076) BTS::Image::Expected::Quartic::Buffer::zero() +calls=1 0 +0 17 +0 8 + +fn=(3068) +0 14 +cfn=(3070) BTS::Image::Observed::Voxel::b0() const +calls=1 0 +0 1433 +0 52 +cfn=(3070) +calls=26 0 +0 37258 +0 108 +cob=(7) +cfi=(53) +cfn=(2824) +calls=27 0 +0 417 +0 93 + +fn=(3070) +0 18468 +cfn=(3072) BTS::Image::Observed::Voxel::encoding(unsigned int) const +calls=1647 0 +0 13176 +0 7047 + +fn=(3080) std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::_M_insert_unique(std::pair const&) +0 12173565028 +cfn=(3082) std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::_M_insert_(std::_Rb_tree_node_base const*, std::_Rb_tree_node_base const*, std::pair const&) +calls=529285436 0 +0 105412270717 +0 2117141744 + +fn=(3086) +0 108812 + +fn=(3092) BTS::Fibre::Set::load(std::string const&) +0 19 +cob=(7) +cfi=(53) +cfn=(3098) +calls=1 0 +0 3056 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1962 +0 18 +cob=(7) +cfi=(53) +cfn=(3098) +calls=1 0 +0 1828 +0 4 +cfn=(3104) void BTS::Fibre::Set::load_tpl >(std::string const&, BTS::Fibre::Base::Reader&) +calls=1 0 +0 202935 +0 2 +cfn=(3276) BTS::Fibre::Base::Reader::~Reader() +calls=1 0 +0 7843 +0 14 +cob=(7) +cfi=(53) +cfn=(1708) +calls=1 0 +0 206 +0 8 +cob=(7) +cfi=(53) +cfn=(1380) +calls=1 0 +0 100 +0 7 + +fn=(3174) +0 6 +cob=(7) +cfi=(53) +cfn=(1254) +calls=1 0 +0 20 +0 2 +cob=(4) +cfi=(69) +cfn=(642) +calls=1 26 +0 16 +0 4 +cob=(7) +cfi=(53) +cfn=(1686) +calls=1 0 +0 347 +0 5 + +fn=(3230) +0 5814792346 +cfn=(3231) std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::_M_erase(std::_Rb_tree_node >*)'2 +calls=528617486 0 +0 5814792346 +0 126976071 +cfn=(3231) +calls=42325357 0 +0 465578927 +0 1712828529 +cob=(7) +cfi=(53) +cfn=(1380) +calls=570942843 0 +0 57069054090 +0 1712828529 +cob=(7) +cfi=(53) +cfn=(1142) +calls=570942843 0 +0 46246370283 +0 3256355630 + +fn=(3231) +0 6280371273 + +fn=(3272) BTS::Fibre::Properties::Extended::add_row(BTS::Fibre::Properties const&) +0 96 +cob=(7) +cfi=(53) +cfn=(1380) +calls=4 0 +0 28 +0 36 +cfn=(2374) +calls=4 0 +0 60 +0 52 + +fn=(3294) unsigned int BTS::Fibre::Properties::Intrinsic::num_intrinsic_keys >() +0 46186 +cfn=(3296) +calls=3299 0 +0 2082374 +0 9897 +cfn=(2618) +calls=3299 0 +0 36289 +0 23093 +cob=(7) +cfi=(53) +cfn=(2824) +calls=3299 0 +0 59382 +0 19794 +cfn=(3300) +calls=3299 0 +0 1025989 +0 19794 + +fn=(3304) +0 35688 +cfn=(3224) +calls=4461 0 +0 6630732 +0 35688 +cob=(7) +cfi=(53) +cfn=(2824) +calls=8922 0 +0 133830 +0 35688 +cfn=(3274) +calls=4461 0 +0 2462472 +0 26766 + +fn=(3356) +0 30 +cob=(7) +cfi=(53) +cfn=(880) +calls=2 0 +0 334 +0 60 +cob=(7) +cfi=(53) +cfn=(2402) +calls=2 0 +0 60 +0 26 + +fn=(3394) +0 14 +cfn=(3396) +calls=1 0 +0 441 +0 12 + +fn=(3396) +0 1182 +cob=(7) +cfi=(53) +cfn=(880) +calls=54 0 +0 6228 +0 96 +cob=(7) +cfi=(53) +cfn=(880) +calls=48 0 +0 5280 +0 2142 +cob=(7) +cfi=(53) +cfn=(2402) +calls=102 0 +0 7277 +0 1567 + +fn=(3408) BTS::Image::Expected::Quartic::Voxel::Voxel(BTS::Image::Expected::Quartic::Buffer&, BTS::Image::Coord const&) +0 1659 +cfn=(3410) +calls=237 0 +0 3575488 +0 1896 + +fn=(3416) BTS::Triple::invalidate() +0 1053636168 +cfn=(3418) +calls=81048936 0 +0 243146808 +0 162097872 +cfn=(3418) +calls=81048936 0 +0 243146808 +0 810489360 +cfn=(3418) +calls=81048936 0 +0 243146808 +0 162097872 +cfn=(3418) +calls=81048936 0 +0 243146808 +0 810489360 +cfn=(3418) +calls=81048936 0 +0 243146808 +0 162097872 +cfn=(3418) +calls=81048936 0 +0 243146808 +0 405244680 + +fn=(3422) +0 40527 +cfn=(3416) +calls=237 0 +0 14694 +0 22989 +cfn=(3416) +calls=237 0 +0 14694 +0 8769 + +fn=(3456) std::_Rb_tree >, std::_Select1st > >, std::less, std::allocator > > >::_M_insert_unique(std::pair > const&) +0 56 +cfn=(3458) +calls=4 0 +0 1288 +0 48 + +fn=(3472) +0 3629208 +cfn=(3224) +calls=329928 0 +0 476787236 +0 1319712 +cfn=(3224) +calls=329928 0 +0 477854547 +0 989784 +cfn=(3224) +calls=329928 0 +0 477931151 +0 31013232 +cfn=(3268) +calls=329928 0 +0 753519770 +0 1319712 +cfn=(3268) +calls=329928 0 +0 760359690 +0 989784 +cfn=(3268) +calls=329928 0 +0 760364852 +0 989784 +cfn=(3466) +calls=329928 0 +0 294513712 +0 2309496 +cfn=(3466) +calls=329928 0 +0 294634899 +0 2309496 +cfn=(3466) +calls=329928 0 +0 294682316 +0 1979568 +cfn=(3274) +calls=329928 0 +0 263282544 +0 659856 +cfn=(3274) +calls=329928 0 +0 263282544 +0 659856 +cfn=(3274) +calls=329928 0 +0 263282544 +0 2639424 + +fn=(3504) std::_Rb_tree >, std::_Select1st > >, std::less, std::allocator > > >::_M_insert_(std::_Rb_tree_node_base const*, std::_Rb_tree_node_base const*, std::pair > const&) +0 4968 +cob=(7) +cfi=(53) +cfn=(880) +calls=196 0 +0 34907 +0 338 +cob=(7) +cfi=(53) +cfn=(880) +calls=169 0 +0 30594 +0 14965 +cob=(7) +cfi=(53) +cfn=(2402) +calls=365 0 +0 26531 +0 6663 + +fn=(3530) BTS::Coord::Tensor_tpl::Tensor_tpl() +0 8023656960 +cfn=(3416) +calls=81047040 0 +0 5024916480 +0 162094080 + +fn=(3540) BTS::Fibre::Strand::~Strand() +0 5835386880 +cfn=(3230) +calls=486282240 0 +0 104550681600 +0 4376540160 +cob=(7) +cfi=(53) +cfn=(1142) +calls=486282240 0 +0 39388861440 + +fn=(3556) +0 1850277 +cfn=(3224) +calls=142329 0 +0 215495754 +0 1138632 +cob=(7) +cfi=(53) +cfn=(2824) +calls=284658 0 +0 4269870 +0 5977818 +cob=(7) +cfi=(53) +cfn=(1142) +calls=142329 0 +0 11528649 +0 853974 +cfn=(3230) +calls=142329 0 +0 59493522 +0 8112753 + +fn=(3564) +0 11529 + +fn=(3576) +0 2981436 +cob=(7) +cfi=(53) +cfn=(1254) +calls=146766 0 +0 2935320 +0 440298 +cfn=(3578) void std::__unguarded_linear_insert<__gnu_cxx::__normal_iterator > >, std::string>(__gnu_cxx::__normal_iterator > >, std::string) +calls=146766 0 +0 7631832 +0 293532 +cob=(7) +cfi=(53) +cfn=(1380) +calls=146766 0 +0 2201490 +0 440298 +cob=(7) +cfi=(53) +cfn=(1380) +calls=146766 0 +0 2201490 +0 733830 +cob=(7) +cfi=(53) +cfn=(1254) +calls=146766 0 +0 2935320 +0 440298 +cob=(7) +cfi=(53) +cfn=(2414) +calls=146766 0 +0 2495022 +0 1494012 + +fn=(3692) std::map, std::less, std::allocator > > >, std::less, std::allocator, std::less, std::allocator > > > > > >::~map() +0 9 +cfn=(3694) +calls=3 0 +0 857 +0 6 + +fn=(1070) global constructors keyed to end_out_sphere.cpp +0 6 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1579 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1778 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1498 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 407 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 324 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 323 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 37 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 5 + +fn=(1098) global constructors keyed to gaussian_intensity.cpp +0 6 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 324 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 323 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 308 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 8 + +fn=(1116) global constructors keyed to all_in_cube.cpp +0 6 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 324 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 323 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 14 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 324 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 407 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 323 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 8 + +fn=(1120) global constructors keyed to dummy.cpp +0 1 +cfn=(1122) +calls=1 0 +0 18033 + +fn=(1136) +0 63 +cob=(7) +cfi=(53) +cfn=(1142) +calls=15 0 +0 2857 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1307 +0 1 + +fn=(1178) global constructors keyed to KCutil.cpp +0 7 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 6 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 324 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 323 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 + +fn=(1188) global constructors keyed to KMlocal.cpp +0 7 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 6 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 324 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 323 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 + +fn=(1190) global constructors keyed to KMeans.cpp +0 5 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 324 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 323 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 + +fn=(1206) global constructors keyed to KMdata.cpp +0 7 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 6 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 324 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 323 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 + +fn=(1230) main +0 19 +cob=(11) +cfi=(60) +cfn=(1236) +calls=1 0 +0 41933 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1496 +0 5 +cob=(11) +cfi=(60) +cfn=(1366) +calls=1 0 +0 390 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1024 +0 3 +cfn=(1368) MyApp::execute() +calls=1 0 +0 1323498586263 +0 4 +cob=(11) +cfi=(60) +cfn=(3676) +calls=1 0 +0 31 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 792 +0 5 + +fn=(2366) +0 213 +cob=(7) +cfi=(53) +cfn=(880) +calls=3 0 +0 388 +0 18 +cfn=(2368) std::string* std::__uninitialized_copy_a<__gnu_cxx::__normal_iterator > >, std::string*, std::string>(__gnu_cxx::__normal_iterator > >, __gnu_cxx::__normal_iterator > >, std::string*, std::allocator&) +calls=3 0 +0 323 +0 30 + +fn=(2408) +0 80 +cob=(7) +cfi=(53) +cfn=(1380) +calls=16 0 +0 112 +0 64 +cob=(7) +cfi=(53) +cfn=(1380) +calls=16 0 +0 240 + +fn=(2804) double MR::Image::(anonymous namespace)::__getLE(void const*, unsigned long) +0 4941 + +fn=(2806) void MR::DataSet::Loop::next_impl >(unsigned long, MR::Image::Voxel&) +0 25297 + +fn=(2856) +0 20 +cfn=(2858) +calls=1 0 +0 2646 +0 14 +cfn=(2860) BTS::Diffusion::Model::tensor_m0_SH(double, double, double) +calls=1 0 +0 109329 +0 420 +cfn=(2860) +calls=60 0 +0 6211320 +0 2806 +cob=(9) +cfi=(58) +cfn=(2626) +calls=61 0 +0 10065 +0 369 +cfn=(2972) +calls=1 0 +0 705406 +0 4 +cob=(9) +cfi=(58) +cfn=(2626) +calls=1 0 +0 226 +0 8 + +fn=(3062) +0 4 +cfn=(3064) +calls=1 0 +0 2 +0 19 + +fn=(3084) BTS::Fibre::Tract::Set::load(std::string const&, unsigned int) +0 17 +cfn=(2618) +calls=1 0 +0 11 +0 23 +cfn=(3086) +calls=1 0 +0 11 +0 10 +cfn=(3088) BTS::File::has_or_txt_extension(std::string const&, std::string const&) +calls=1 0 +0 786 +0 13 +cfn=(3092) +calls=1 0 +0 218002 +0 1 + +fn=(3104) +0 20 +cfn=(2618) +calls=1 0 +0 11 +0 23 +cfn=(3086) +calls=1 0 +0 11 +0 9 +cfn=(3106) +calls=1 0 +0 79343 +0 12 +cfn=(2564) +calls=1 0 +0 955 +0 34 +cfn=(2618) +calls=1 0 +0 11 +0 12 +cfn=(2564) +calls=1 0 +0 1392 +0 31 +cfn=(2618) +calls=1 0 +0 690 +0 5 +cfn=(3204) BTS::Fibre::Properties::Intrinsic::set_intrinsic_properties(BTS::Fibre::Properties&) +calls=1 0 +0 7889 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 57 +0 6 +cfn=(3220) +calls=1 0 +0 217 +0 2 +cfn=(3222) void BTS::Fibre::Properties::Intrinsic::remove_intrinsic_keys(BTS::Fibre::Properties::Header&) +calls=1 0 +0 2343 +0 29 +cob=(7) +cfi=(53) +cfn=(880) +calls=1 0 +0 168 +0 11 +cfn=(2368) +calls=1 0 +0 81 +0 3 +cfn=(3222) +calls=1 0 +0 2227 +0 7 +cfn=(3232) +calls=1 0 +0 33 +0 2 +cfn=(3198) +calls=1 0 +0 96 +0 2 +cfn=(2374) +calls=1 0 +0 15 +0 2 +cfn=(3198) +calls=1 0 +0 96 +0 2 +cob=(7) +cfi=(53) +cfn=(1380) +calls=1 0 +0 7 +0 4 +cfn=(3224) +calls=1 0 +0 1431 +0 19 +cfn=(3234) +calls=1 0 +0 23640 +0 16 +cfn=(3234) +calls=4 0 +0 62679 +0 78 +cfn=(3268) +calls=1 0 +0 1932 +0 6 +cfn=(3272) +calls=1 0 +0 68 +0 9 +cfn=(3272) +calls=3 0 +0 204 +0 12 +cfn=(2618) +calls=4 0 +0 44 +0 20 +cfn=(3266) std::vector >::_M_insert_aux(__gnu_cxx::__normal_iterator > >, BTS::Fibre::Tract const&) +calls=3 0 +0 16350 +0 12 +cfn=(2618) +calls=1 0 +0 11 +0 2 +cfn=(3274) +calls=1 0 +0 528 +0 12 + +fn=(3200) +0 7 +cfn=(2618) +calls=1 0 +0 11 +0 2 +cfn=(2374) +calls=1 0 +0 15 +0 2 +cfn=(3202) +calls=1 0 +0 20 +0 2 +cfn=(3202) +calls=1 0 +0 20 +0 2 +cfn=(3202) +calls=1 0 +0 20 +0 2 +cfn=(3202) +calls=1 0 +0 20 +0 3 +cfn=(2618) +calls=1 0 +0 690 +0 4 + +fn=(3206) double BTS::to(std::string const&) +0 99 +cob=(7) +cfi=(53) +cfn=(722) +calls=9 0 +0 873 +0 198 +cob=(7) +cfi=(53) +cfn=(728) +calls=9 0 +0 6372 +0 144 +cob=(7) +cfi=(53) +cfn=(492) +calls=9 0 +0 351 +0 81 +cob=(7) +cfi=(53) +cfn=(1752) +calls=9 0 +0 1646 +0 54 +cob=(7) +cfi=(53) +cfn=(1758) +calls=9 0 +0 189 +0 27 +cob=(7) +cfi=(53) +cfn=(728) +calls=9 0 +0 6372 +0 27 +cob=(7) +cfi=(53) +cfn=(1764) +calls=9 0 +0 12328 +0 90 +cob=(7) +cfi=(53) +cfn=(1380) +calls=9 0 +0 900 +0 45 +cob=(7) +cfi=(53) +cfn=(746) +calls=9 0 +0 108 +0 81 +cob=(7) +cfi=(53) +cfn=(1818) +calls=9 0 +0 522 +0 81 + +fn=(3276) +0 13 +cob=(7) +cfi=(53) +cfn=(1880) +calls=1 0 +0 640 +0 5 +cob=(7) +cfi=(53) +cfn=(1880) +calls=1 0 +0 1411 +0 4 +cob=(7) +cfi=(53) +cfn=(3282) +calls=1 0 +0 2463 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1962 +0 2 +cfn=(3198) +calls=1 0 +0 307 +0 3 +cfn=(2618) +calls=1 0 +0 860 +0 2 +cob=(7) +cfi=(53) +cfn=(1380) +calls=1 0 +0 15 +0 7 +cob=(7) +cfi=(53) +cfn=(3282) +calls=1 0 +0 149 + +fn=(3312) void BTS::Image::Expected::Buffer_tpl::expected_image(BTS::Fibre::Tract::Set const&, BTS::Image::Container::Buffer::Set&, BTS::Image::Container::Buffer::Set&) +0 113 +cfn=(3334) void BTS::Image::Expected::Buffer_tpl::part_image(BTS::Fibre::Tract const&, BTS::Image::Container::Buffer&, BTS::Image::Container::Buffer&) +calls=4 0 +0 1318538253951 +0 80 +cfn=(3314) +calls=4 0 +0 32 +0 114 +cfn=(3324) +calls=1 0 +0 19 +0 15 +cfn=(3324) +calls=3 0 +0 57 +0 16 +cfn=(3314) +calls=4 0 +0 32 +0 114 +cfn=(3332) std::_Rb_tree >, std::_Select1st > >, std::less, std::allocator > > >::_M_erase(std::_Rb_tree_node > >*) +calls=1 0 +0 19 +0 15 +cfn=(3332) +calls=3 0 +0 57 +0 40 +cfn=(3318) +calls=3 0 +0 44642890 +0 24 +cfn=(3326) std::vector, std::allocator > >::_M_insert_aux(__gnu_cxx::__normal_iterator*, std::vector, std::allocator > > >, BTS::Image::Container::Buffer const&) +calls=3 0 +0 2469486810 +0 12 + +fn=(3324) +0 98 +cfn=(3325) std::_Rb_tree >, std::_Select1st > >, std::less, std::allocator > > >::_M_erase(std::_Rb_tree_node > >*)'2 +calls=3 0 +0 4040567 +0 84 +cfn=(3325) +calls=21 0 +0 5716237 +0 4560 +cfn=(3274) +calls=1464 0 +0 1168272 +0 4488 +cob=(7) +cfi=(53) +cfn=(1142) +calls=24 0 +0 2605 +0 72 +cob=(7) +cfi=(53) +cfn=(1142) +calls=24 0 +0 1944 +0 104 + +fn=(3325) +0 3226 +cfn=(3325) +calls=112 0 +0 9709203 +0 344 +cfn=(3325) +calls=86 0 +0 3549467 +0 37620 +cfn=(3274) +calls=12078 0 +0 9638244 +0 37026 +cob=(7) +cfi=(53) +cfn=(1142) +calls=198 0 +0 21540 +0 594 +cob=(7) +cfi=(53) +cfn=(1142) +calls=198 0 +0 16038 +0 2172 + +fn=(3326) +0 71 +cob=(7) +cfi=(53) +cfn=(880) +calls=3 0 +0 16520 +0 27 +cfn=(3328) BTS::Image::Container::Buffer::Buffer(BTS::Image::Container::Buffer const&) +calls=3 0 +0 96 +0 18 +cfn=(3330) BTS::Image::Container::Buffer* std::__uninitialized_move_a*, BTS::Image::Container::Buffer*, std::allocator > >(BTS::Image::Container::Buffer*, BTS::Image::Container::Buffer*, BTS::Image::Container::Buffer*, std::allocator >&) +calls=3 0 +0 2141456979 +0 18 +cfn=(3330) +calls=3 0 +0 51 +0 32 +cfn=(3332) +calls=2 0 +0 206855230 +0 4 +cfn=(3332) +calls=1 0 +0 121157474 +0 19 +cob=(7) +cfi=(53) +cfn=(1142) +calls=2 0 +0 187 +0 84 + +fn=(3332) +0 98 +cfn=(3333) std::_Rb_tree >, std::_Select1st > >, std::less, std::allocator > > >::_M_erase(std::_Rb_tree_node > >*)'2 +calls=3 0 +0 121158107 +0 84 +cfn=(3333) +calls=21 0 +0 171394171 +0 4560 +cfn=(3512) +calls=1464 0 +0 35446472 +0 4488 +cob=(7) +cfi=(53) +cfn=(1142) +calls=24 0 +0 2680 +0 72 +cob=(7) +cfi=(53) +cfn=(1142) +calls=24 0 +0 1944 +0 104 + +fn=(3333) +0 3226 +cfn=(3333) +calls=112 0 +0 291076482 +0 344 +cfn=(3333) +calls=86 0 +0 106384178 +0 37620 +cfn=(3512) +calls=12078 0 +0 292433170 +0 37026 +cob=(7) +cfi=(53) +cfn=(1142) +calls=198 0 +0 22088 +0 594 +cob=(7) +cfi=(53) +cfn=(1142) +calls=198 0 +0 16038 +0 2172 + +fn=(3336) BTS::Fibre::Tract::sections(unsigned int, unsigned int, BTS::Triple const&, BTS::Triple const&) const +0 116 +cfn=(3338) +calls=4 0 +0 131574651 +0 128 +cfn=(3342) std::_Rb_tree, std::less, std::allocator > > > >, std::_Select1st, std::less, std::allocator > > > > >, std::less, std::allocator, std::less, std::allocator > > > > > >::_M_insert_unique_(std::_Rb_tree_const_iterator, std::less, std::allocator > > > > >, std::pair, std::less, std::allocator > > > > const&) +calls=1 0 +0 380 +0 5 +cfn=(3348) +calls=1 0 +0 11 +0 3 +cfn=(3348) +calls=1 0 +0 11 +0 75 +cfn=(3350) MR::Math::Matrix::Matrix(MR::Math::Matrix const&) +calls=1 0 +0 31 +0 4 +cfn=(3352) std::_Rb_tree >, std::_Select1st > >, std::less, std::allocator > > >::_M_insert_unique_(std::_Rb_tree_const_iterator > >, std::pair > const&) +calls=1 0 +0 304 +0 33 +cfn=(3358) BTS::Fibre::Strand::create_position_matrix(unsigned int, unsigned int, bool) +calls=1 0 +0 9271 +0 3 +cfn=(3368) +calls=1 0 +0 1447 +0 5 +cob=(9) +cfi=(58) +cfn=(2626) +calls=1 0 +0 196 +0 116 +cfn=(3342) +calls=1 0 +0 501 +0 4 +cfn=(3348) +calls=1 0 +0 11 +0 3 +cfn=(3348) +calls=1 0 +0 11 +0 82 +cfn=(3350) +calls=1 0 +0 31 +0 4 +cfn=(3352) +calls=1 0 +0 302 +0 49969737 +cfn=(3370) +calls=1 0 +0 9751 +0 3 +cfn=(3368) +calls=1 0 +0 1445 +0 5 +cob=(9) +cfi=(58) +cfn=(2626) +calls=1 0 +0 196 +0 37 + +fn=(3340) +0 16 + +fn=(3360) +0 224750 +cob=(9) +cfi=(58) +cfn=(1868) +calls=7750 0 +0 22250210 +0 38750 + +fn=(3406) BTS::Image::Expected::Quartic::Buffer::new_voxel(BTS::Image::Coord const&) +0 711 +cfn=(3408) +calls=237 0 +0 3579043 +0 711 + +fn=(3474) T.6704 +0 5110 +cob=(7) +cfi=(53) +cfn=(880) +calls=365 0 +0 40150 +0 26645 +cob=(7) +cfi=(53) +cfn=(880) +calls=1095 0 +0 187028 +0 29565 +cfn=(3472) +calls=3285 0 +0 49983949 +0 29200 + +fn=(3512) +0 143228 +cfn=(3494) +calls=35807 0 +0 365787299 + +fn=(3522) BTS::Image::Expected::Quartic::Voxel::interpolate(BTS::Triple const&, BTS::Triple&, BTS::Coord::Tensor&) +0 95662080 + +fn=(3548) std::_Rb_tree >, std::_Select1st > >, std::less, std::allocator > > >::_M_copy(std::_Rb_tree_node > > const*, std::_Rb_tree_node > >*) +0 36 +cob=(7) +cfi=(53) +cfn=(880) +calls=3 0 +0 460 +0 81 +cob=(7) +cfi=(53) +cfn=(880) +calls=3 0 +0 24430 +0 954 +cfn=(3268) +calls=183 0 +0 446664 +0 978 +cfn=(3549) std::_Rb_tree >, std::_Select1st > >, std::less, std::allocator > > >::_M_copy(std::_Rb_tree_node > > const*, std::_Rb_tree_node > >*)'2 +calls=3 0 +0 12454817 +0 30 +cob=(7) +cfi=(53) +cfn=(880) +calls=3 0 +0 531 +0 36 +cob=(7) +cfi=(53) +cfn=(880) +calls=18 0 +0 3186 +0 651 +cob=(7) +cfi=(53) +cfn=(880) +calls=21 0 +0 6797 +0 6657 +cfn=(3268) +calls=1281 0 +0 3165680 +0 6763 +cfn=(3549) +calls=16 0 +0 17578334 +0 127 + +fn=(3549) +0 1344 +cob=(7) +cfi=(53) +cfn=(880) +calls=112 0 +0 19788 +0 3024 +cob=(7) +cfi=(53) +cfn=(880) +calls=112 0 +0 36723 +0 35616 +cfn=(3268) +calls=6832 0 +0 16866786 +0 36280 +cfn=(3549) +calls=54 0 +0 29872880 +0 699 +cob=(7) +cfi=(53) +cfn=(880) +calls=51 0 +0 8919 +0 70 +cob=(7) +cfi=(53) +cfn=(880) +calls=35 0 +0 6231 +0 2666 +cob=(7) +cfi=(53) +cfn=(880) +calls=86 0 +0 28642 +0 27262 +cfn=(3268) +calls=5246 0 +0 12930120 +0 27590 +cfn=(3549) +calls=39 0 +0 10889046 +0 1391 + +fn=(3558) +0 180 +cob=(7) +cfi=(53) +cfn=(880) +calls=6 0 +0 692 +0 90 +cob=(4) +cfi=(113) +cfn=(1794) +calls=6 47 +0 292 +0 48 +cob=(4) +cfi=(113) +cfn=(1794) +calls=6 47 +0 144 +0 22 +cob=(7) +cfi=(53) +cfn=(1142) +calls=4 0 +0 324 +0 88 + +fn=(3562) +0 11529 +cfn=(3402) +calls=1647 0 +0 254307 +0 3294 + +fn=(3578) +0 1907958 +cob=(7) +cfi=(53) +cfn=(2414) +calls=146766 0 +0 2495022 +0 1614426 +cob=(7) +cfi=(53) +cfn=(1260) +calls=146766 0 +0 1614426 + +fn=(3592) void BTS::Fibre::Unzipper::unzip_intrinsic(BTS::Fibre::BasicStrand const&, MR::Math::Vector&, unsigned int&) +0 2561634 +cfn=(2374) +calls=426939 0 +0 6404085 +0 853878 + +fn=(3596) +0 32940 +cfn=(3294) +calls=3294 0 +0 3317058 +0 52704 +cfn=(3556) +calls=3294 0 +0 6879824 +0 59292 +cfn=(3556) +calls=9882 0 +0 20639472 +0 115290 +cob=(9) +cfi=(58) +cfn=(1868) +calls=3294 0 +0 1058960 +0 42822 +cfn=(3598) void BTS::Fibre::Unzipper::unzip_element >(BTS::Fibre::Set const&, MR::Math::Vector&, unsigned int&) +calls=3294 0 +0 54276092 +0 26352 + +fn=(3684) BTS::Image::Expected::Buffer_tpl::~Buffer_tpl() +0 10 +cfn=(3686) +calls=1 0 +0 11 +0 13 +cfn=(2618) +calls=1 0 +0 11 +0 6 +cfn=(3688) std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::_M_erase(std::_Rb_tree_node >*) +calls=1 0 +0 11 +0 4 + +fn=(3480) +0 1538342 +cob=(7) +cfi=(53) +cfn=(2414) +calls=59167 0 +0 1005839 +0 1301674 +cfn=(3482) +calls=59167 0 +0 16832336 +0 295835 +cfn=(3484) +calls=59167 0 +0 15107047 +0 59167 + +fn=(1118) global constructors keyed to midpoint_in_sphere.cpp +0 6 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 324 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 323 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 318 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 8 + +fn=(1158) global constructors keyed to voxel.cpp +0 5 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 407 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 324 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 323 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 9 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 324 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 323 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 12 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 324 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 323 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 9 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 324 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 323 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 12 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 324 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 323 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 12 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 407 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 324 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 323 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 7 + +fn=(1160) global constructors keyed to base_width.cpp +0 6 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 324 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 323 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 8 + +fn=(1166) global constructors keyed to spread.cpp +0 6 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 324 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 323 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 314 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 8 + +fn=(1388) std::vector >::~vector() +0 375 + +fn=(3020) +0 10 +cob=(4) +cfi=(135) +cfn=(3028) 0x000000000012aa40 +calls=2 81 +0 106 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1699 + +fn=(3056) +0 6 +cob=(7) +cfi=(53) +cfn=(880) +calls=1 0 +0 187 +0 4 +cfn=(3058) BTS::Image::Expected::Quartic::Buffer::Buffer(BTS::Image::Expected::Quartic::Buffer const&) +calls=1 0 +0 30322 +0 5 + +fn=(3058) +0 11 +cfn=(3060) +calls=1 0 +0 30242 +0 7 +cfn=(3020) +calls=1 0 +0 58 +0 4 + +fn=(3074) BTS::Image::Observed::Buffer::encoding(unsigned int) const +0 6588 + +fn=(3078) +0 7498878769 +cfn=(3082) +calls=42993307 0 +0 8745362650 +0 6123092945 +cfn=(3080) +calls=529285436 0 +0 119702977489 +0 529285436 + +fn=(3110) +0 63 + +fn=(3182) +0 37 +cob=(7) +cfi=(53) +cfn=(3188) +calls=1 0 +0 978 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1434 +0 3 +cob=(4) +cfi=(97) /build/buildd/eglibc-2.11.1/string/../sysdeps/x86_64/multiarch/../strcmp.S +cfn=(3196) __strcmp_ssse3 +calls=1 90 +0 92 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1701 +0 13 + +fn=(3198) +0 38 +cob=(7) +cfi=(53) +cfn=(1380) +calls=2 0 +0 115 +0 4 +cob=(7) +cfi=(53) +cfn=(1380) +calls=2 0 +0 115 +0 40 +cob=(7) +cfi=(53) +cfn=(1142) +calls=4 0 +0 324 + +fn=(3238) BTS::Fibre::Base::Reader::read_triple() +0 1643 +cob=(7) +cfi=(53) +cfn=(3244) +calls=53 0 +0 10152 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1434 +0 53 + +fn=(3256) std::vector, std::allocator > >::_M_insert_aux(__gnu_cxx::__normal_iterator*, std::vector, std::allocator > > >, BTS::Triple const&) +0 10698210072 +cob=(7) +cfi=(53) +cfn=(880) +calls=486282276 0 +0 53491123548 +0 22693172880 +cob=(7) +cfi=(53) +cfn=(1142) +calls=324188184 0 +0 26259242904 +0 10049833704 + +fn=(3260) +0 272 +cob=(7) +cfi=(53) +cfn=(1254) +calls=8 0 +0 160 +0 32 +cob=(7) +cfi=(53) +cfn=(1254) +calls=8 0 +0 120 +0 32 +cfn=(2392) +calls=8 0 +0 2274 +0 24 +cob=(7) +cfi=(53) +cfn=(1380) +calls=8 0 +0 56 +0 16 +cob=(7) +cfi=(53) +cfn=(1380) +calls=8 0 +0 120 +0 16 +cob=(7) +cfi=(53) +cfn=(1380) +calls=8 0 +0 56 +0 72 + +fn=(3266) +0 72 +cob=(7) +cfi=(53) +cfn=(880) +calls=3 0 +0 430 +0 33 +cfn=(3268) +calls=3 0 +0 6086 +0 18 +cfn=(3270) BTS::Fibre::Tract* std::__uninitialized_move_a >(BTS::Fibre::Tract*, BTS::Fibre::Tract*, BTS::Fibre::Tract*, std::allocator&) +calls=3 0 +0 6929 +0 18 +cfn=(3270) +calls=3 0 +0 51 +0 28 +cfn=(3274) +calls=2 0 +0 1596 +0 4 +cfn=(3274) +calls=1 0 +0 798 +0 16 +cob=(7) +cfi=(53) +cfn=(1142) +calls=2 0 +0 193 +0 78 + +fn=(3344) std::_Rb_tree, std::less, std::allocator > > > >, std::_Select1st, std::less, std::allocator > > > > >, std::less, std::allocator, std::less, std::allocator > > > > > >::_M_insert_unique(std::pair, std::less, std::allocator > > > > const&) +0 50 +cfn=(3346) +calls=2 0 +0 785 +0 4 + +fn=(3348) +0 50 +cfn=(3349) std::_Rb_tree >, std::_Select1st > >, std::less, std::allocator > > >::_M_erase(std::_Rb_tree_node > >*)'2 +calls=2 0 +0 22 +0 10 +cob=(9) +cfi=(58) +cfn=(2626) +calls=2 0 +0 380 +0 6 +cob=(7) +cfi=(53) +cfn=(1142) +calls=2 0 +0 162 +0 28 + +fn=(3349) +0 22 + +fn=(3350) +0 62 + +fn=(3412) +0 4503 +cob=(7) +cfi=(53) +cfn=(880) +calls=237 0 +0 111237 +0 65175 + +fn=(3414) +0 75366 +cfn=(3416) +calls=711 0 +0 44082 +0 68967 +cfn=(3416) +calls=711 0 +0 44082 +0 24174 + +fn=(3468) +0 134097924 +cob=(7) +cfi=(53) +cfn=(880) +calls=3192786 0 +0 574978176 +0 150060942 + +fn=(3510) BTS::Fibre::Tract::Tensor* std::__uninitialized_copy_a<__gnu_cxx::__normal_iterator > >, BTS::Fibre::Tract::Tensor*, BTS::Fibre::Tract::Tensor>(__gnu_cxx::__normal_iterator > >, __gnu_cxx::__normal_iterator > >, BTS::Fibre::Tract::Tensor*, std::allocator&) +0 116070 +cfn=(3492) BTS::Fibre::Tract::Tensor::Tensor(BTS::Fibre::Tract::Tensor const&) +calls=22265 0 +0 120166928 +0 114245 + +fn=(3520) BTS::Image::Expected::Quartic::Voxel::interpolate(BTS::Fibre::Strand::Section const&, BTS::Fibre::Strand::Section&, BTS::Fibre::Strand::Section::Tensor&) +0 39859200 +cfn=(3522) +calls=664320 0 +0 95662080 +0 3321600 +cfn=(3524) +calls=664320 0 +0 41187840 +0 7971840 +cfn=(3526) +calls=664320 0 +0 1992960 +0 1328640 +cfn=(3526) +calls=664320 0 +0 1992960 +0 15943680 +cfn=(3528) +calls=664320 0 +0 47166720 +0 1328640 +cfn=(3528) +calls=664320 0 +0 47166720 +0 7307520 +cfn=(3526) +calls=664320 0 +0 1992960 +0 1328640 +cfn=(3526) +calls=664320 0 +0 1992960 +0 68424960 + +fn=(3534) BTS::Fibre::Tract::add_section_gradient(BTS::Fibre::Tract::Section const&, BTS::Fibre::Tract::Section const&) +0 6726904320 +cfn=(3256) +calls=243141120 0 +0 61595794553 +0 2917693440 +cob=(7) +cfi=(53) +cfn=(880) +calls=81047040 0 +0 8915174544 +0 6321669120 +cob=(7) +cfi=(53) +cfn=(934) +calls=81047040 0 +0 18073497212 +0 1296752640 +cob=(7) +cfi=(53) +cfn=(1380) +calls=81047040 0 +0 1215705600 +0 567329280 +cob=(7) +cfi=(53) +cfn=(1142) +calls=81047040 0 +0 6564810240 +0 243141120 +cfn=(3536) BTS::Fibre::BasicStrand::operator+=(BTS::Fibre::BasicStrand const&) +calls=81047040 0 +0 7051092480 +0 486282240 +cfn=(3538) +calls=81047040 0 +0 62244192136 +0 4943869440 +cfn=(3536) +calls=81047040 0 +0 7051092480 +0 162094080 +cfn=(3540) +calls=81047040 0 +0 25691911680 +0 486282240 +cfn=(3538) +calls=81047040 0 +0 62244156575 +0 4943869440 +cfn=(3536) +calls=81047040 0 +0 7051092480 +0 162094080 +cfn=(3540) +calls=81047040 0 +0 25691911680 +0 6564810240 +cfn=(3256) +calls=243141120 0 +0 61595779319 +0 2917693440 +cob=(7) +cfi=(53) +cfn=(880) +calls=81047040 0 +0 8915174400 +0 6159575040 +cob=(7) +cfi=(53) +cfn=(934) +calls=81047040 0 +0 18073489920 +0 243141120 +cfn=(3298) +calls=81047040 0 +0 25772987055 +0 324188160 +cob=(7) +cfi=(53) +cfn=(1380) +calls=81047040 0 +0 1215705600 +0 567329280 +cob=(7) +cfi=(53) +cfn=(1142) +calls=81047040 0 +0 6564810240 +0 243141120 +cfn=(3536) +calls=81047040 0 +0 7051092480 +0 486282240 +cfn=(3538) +calls=81047040 0 +0 62244197902 +0 4943869440 +cfn=(3536) +calls=81047040 0 +0 7051092480 +0 162094080 +cfn=(3540) +calls=81047040 0 +0 25691911680 +0 486282240 +cfn=(3538) +calls=81047040 0 +0 62244156739 +0 4943869440 +cfn=(3536) +calls=81047040 0 +0 7051092480 +0 162094080 +cfn=(3540) +calls=81047040 0 +0 25691911680 +0 972564480 +cfn=(3540) +calls=81047040 0 +0 25691911680 +0 162094080 +cfn=(3540) +calls=81047040 0 +0 25691911680 +0 2836646400 +cob=(7) +cfi=(53) +cfn=(1254) +calls=81047040 0 +0 1620940800 +0 486282240 +cfn=(3078) +calls=81047040 0 +0 20180745258 +0 243141120 +cob=(7) +cfi=(53) +cfn=(1380) +calls=81047040 0 +0 1215705600 +0 81047040 + +fn=(3550) std::_Rb_tree >, std::_Select1st > >, std::less, std::allocator > > >::_M_copy(std::_Rb_tree_node > > const*, std::_Rb_tree_node > >*) +0 36 +cob=(7) +cfi=(53) +cfn=(880) +calls=3 0 +0 415 +0 81 +cob=(7) +cfi=(53) +cfn=(880) +calls=3 0 +0 4649910 +0 954 +cfn=(3492) +calls=183 0 +0 28123350 +0 975 +cfn=(3551) std::_Rb_tree >, std::_Select1st > >, std::less, std::allocator > > >::_M_copy(std::_Rb_tree_node > > const*, std::_Rb_tree_node > >*)'2 +calls=3 0 +0 787726194 +0 30 +cob=(7) +cfi=(53) +cfn=(880) +calls=3 0 +0 585 +0 36 +cob=(7) +cfi=(53) +cfn=(880) +calls=18 0 +0 3510 +0 651 +cob=(7) +cfi=(53) +cfn=(880) +calls=21 0 +0 26775 +0 6657 +cfn=(3492) +calls=1281 0 +0 202427820 +0 6763 +cfn=(3551) +calls=16 0 +0 1118481753 +0 127 + +fn=(3551) +0 1344 +cob=(7) +cfi=(53) +cfn=(880) +calls=112 0 +0 21365 +0 3024 +cob=(7) +cfi=(53) +cfn=(880) +calls=112 0 +0 146228 +0 35616 +cfn=(3492) +calls=6832 0 +0 1076803581 +0 36168 +cfn=(3551) +calls=54 0 +0 1893246970 +0 699 +cob=(7) +cfi=(53) +cfn=(880) +calls=51 0 +0 9918 +0 70 +cob=(7) +cfi=(53) +cfn=(880) +calls=35 0 +0 6825 +0 2666 +cob=(7) +cfi=(53) +cfn=(880) +calls=86 0 +0 109947 +0 27262 +cfn=(3492) +calls=5246 0 +0 828974253 +0 27590 +cfn=(3551) +calls=39 0 +0 694216984 +0 1391 + +fn=(3594) +0 961848 +cfn=(3582) +calls=120231 0 +0 747004841 +0 23324814 +cob=(9) +cfi=(58) +cfn=(2626) +calls=120231 0 +0 22843890 +0 480924 + +fn=(3598) +0 39528 +cfn=(3600) void BTS::Fibre::Unzipper::unzip_intrinsic >(BTS::Fibre::Set const&, MR::Math::Vector&, unsigned int&) +calls=3294 0 +0 5264788 +0 52704 +cfn=(3588) void BTS::Fibre::Unzipper::unzip_intrinsic(BTS::Fibre::Tract const&, MR::Math::Vector&, unsigned int&) +calls=3294 0 +0 11065156 +0 79056 +cfn=(3588) +calls=9882 0 +0 33189612 +0 210816 +cfn=(3592) +calls=13176 0 +0 303048 +0 210816 +cfn=(3592) +calls=26352 0 +0 606096 +0 3254472 + +fn=(3688) +0 11 + +fn=(3696) __tcf_0 +0 101 +cob=(7) +cfi=(53) +cfn=(1142) +calls=15 0 +0 1215 +0 44 + +fn=(3750) MR::Math::Matrix::~Matrix() +0 4 + +fn=(1060) +0 6 + +fn=(1108) global constructors keyed to triple.cpp +0 4 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 51 + +fn=(1126) +0 165 +cfn=(1128) +calls=15 0 +0 4084 +0 30 + +fn=(1134) +0 377 +cob=(7) +cfi=(53) +cfn=(880) +calls=15 0 +0 2925 +0 867 + +fn=(1154) global constructors keyed to tract.cpp +0 5 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 324 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 323 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 13 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 324 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 323 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 12 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 5 + +fn=(1162) global constructors keyed to strand.cpp +0 5 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 324 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 323 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 13 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 324 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 323 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 318 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 314 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 304 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 11 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 10 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 10 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 5 + +fn=(1172) global constructors keyed to width.cpp +0 6 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 407 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 324 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 323 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 308 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 5 + +fn=(1184) global constructors keyed to track.cpp +0 6 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 324 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 323 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 308 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 314 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 304 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 12 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 315 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 5 + +fn=(1186) global constructors keyed to walker.cpp +0 3 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 + +fn=(1204) global constructors keyed to dummy_intrinsic_properties.cpp +0 3 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 + +fn=(1350) +0 36 +cob=(7) +cfi=(53) +cfn=(1254) +calls=6 0 +0 120 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1426 +0 18 +cob=(7) +cfi=(53) +cfn=(1360) +calls=6 0 +0 2320 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1548 +0 30 + +fn=(1788) +0 5490 +cob=(7) +cfi=(53) +cfn=(880) +calls=183 0 +0 35180 +0 2745 +cob=(4) +cfi=(113) +cfn=(1794) +calls=183 47 +0 9699 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1698 +0 1464 +cob=(4) +cfi=(113) +cfn=(1794) +calls=183 47 +0 4392 +0 671 +cob=(7) +cfi=(53) +cfn=(1142) +calls=122 0 +0 9882 +0 2684 + +fn=(1950) BTS::Image::Observed::Buffer::load(std::string const&, BTS::Diffusion::Encoding::Set const&) +0 13 +cob=(11) +cfi=(60) +cfn=(1956) +calls=1 0 +0 1861032 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1072 +0 15 +cfn=(2620) +calls=1 0 +0 5932 +0 4 +cfn=(1946) +calls=1 0 +0 7105 +0 4 +cob=(9) +cfi=(58) +cfn=(2626) +calls=1 0 +0 198 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 877 +0 22 +cfn=(2620) +calls=1 0 +0 468 +0 24 +cfn=(2628) +calls=1 0 +0 15 +0 29 +cfn=(2630) std::vector >::operator=(std::vector > const&) +calls=1 0 +0 1246 +0 4 +cfn=(2632) +calls=1 0 +0 58953 +0 15 +cob=(4) +cfi=(126) /build/buildd/eglibc-2.11.1/time/../sysdeps/unix/sysv/linux/x86_64/gettimeofday.S +cfn=(2780) gettimeofday +calls=1 29 +0 12 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1795 +0 21494 +cfn=(2784) +calls=1647 0 +0 260249 +0 23058 +cfn=(2804) +calls=1647 0 +0 4941 +0 44469 +cfn=(2806) +calls=549 0 +0 25297 +0 8241 +cfn=(2392) +calls=1 0 +0 289 +0 60 +cfn=(2392) +calls=15 0 +0 6537 +0 32 +cob=(7) +cfi=(53) +cfn=(2824) +calls=16 0 +0 1491 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1971 +0 50 +cfn=(2832) MR::ProgressBar::~ProgressBar() +calls=1 0 +0 16 +0 4 +cob=(7) +cfi=(53) +cfn=(1142) +calls=1 0 +0 81 +0 4 +cob=(9) +cfi=(58) +cfn=(2626) +calls=1 0 +0 165 +0 4 +cob=(7) +cfi=(53) +cfn=(1142) +calls=1 0 +0 114 +0 2 +cfn=(2610) +calls=1 0 +0 8973 +0 7694 + +fn=(2392) +0 520 +cob=(7) +cfi=(53) +cfn=(2812) +calls=1 0 +0 11 +0 398 +cfn=(2394) std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::_M_insert_unique(std::pair const&) +calls=7 0 +0 3987 +0 155 +cob=(7) +cfi=(53) +cfn=(2414) +calls=37 0 +0 723 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1532 +0 259 +cfn=(2396) +calls=37 0 +0 13413 +0 42 +cfn=(2396) +calls=1 0 +0 254 +0 1 + +fn=(2618) +0 127179 +cfn=(2619) std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::_M_erase(std::_Rb_tree_node >*)'2 +calls=13 0 +0 9036 +0 36 +cfn=(2619) +calls=12 0 +0 1118 +0 75 +cob=(7) +cfi=(53) +cfn=(1380) +calls=25 0 +0 1225 +0 50 +cob=(7) +cfi=(53) +cfn=(1380) +calls=25 0 +0 885 +0 75 +cob=(7) +cfi=(53) +cfn=(1142) +calls=25 0 +0 2025 +0 72694 + +fn=(2619) +0 709 +cfn=(2619) +calls=39 0 +0 10073 +0 45 +cfn=(2619) +calls=15 0 +0 1321 +0 162 +cob=(7) +cfi=(53) +cfn=(1380) +calls=54 0 +0 2085 +0 108 +cob=(7) +cfi=(53) +cfn=(1380) +calls=54 0 +0 2085 +0 162 +cob=(7) +cfi=(53) +cfn=(1142) +calls=54 0 +0 4374 +0 424 + +fn=(2796) std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::_M_insert_unique(std::pair const&) +0 14 +cfn=(2798) std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::_M_insert_(std::_Rb_tree_node_base const*, std::_Rb_tree_node_base const*, std::pair const&) +calls=1 0 +0 247 +0 12 + +fn=(2864) MR::Math::Vector& MR::Math::SH::FA2SH(MR::Math::Vector&, double, double, double, int, int) +0 2623 +cfn=(2862) +calls=61 0 +0 26824 +0 549 +cfn=(2858) +calls=61 0 +0 39845 +0 2318 +cob=(6) +cfi=(127) /build/buildd/eglibc-2.11.1/math/../sysdeps/x86_64/fpu/s_sincos.S +cfn=(2870) sincos +calls=61 34 +0 549 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1430 +0 42273 +cob=(6) +cfi=(127) +cfn=(2870) +calls=6039 34 +0 54351 +0 97600 +cob=(6) +cfi=(128) /build/buildd/eglibc-2.11.1/math/../sysdeps/ieee754/dbl-64/w_exp.c +cfn=(2876) exp +calls=6100 38 +0 700400 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1390 +0 1439844 +cfn=(2858) +calls=61 0 +0 23241 +0 549 +cfn=(2858) +calls=61 0 +0 19764 +0 305 +cfn=(2858) +calls=61 0 +0 23241 +0 276025 +cob=(9) +cfi=(58) +cfn=(2886) gsl_blas_dgemm +calls=61 0 +0 1273115 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 843 +0 122 +cob=(9) +cfi=(58) +cfn=(2898) gsl_linalg_cholesky_decomp +calls=61 0 +0 118003 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1027 +0 122 +cob=(9) +cfi=(58) +cfn=(2924) gsl_linalg_cholesky_invert +calls=61 0 +0 216316 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1027 +0 488 +cob=(9) +cfi=(58) +cfn=(2950) gsl_blas_dsymm +calls=61 0 +0 1617799 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 843 +0 244 +cob=(9) +cfi=(58) +cfn=(2626) +calls=61 0 +0 11285 +0 244 +cob=(9) +cfi=(58) +cfn=(2626) +calls=61 0 +0 11956 +0 183 +cfn=(2958) MR::Math::Vector::allocate(unsigned long) +calls=61 0 +0 854 +0 427 +cob=(9) +cfi=(58) +cfn=(2964) gsl_blas_dgemv +calls=61 0 +0 259120 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 835 +0 244 +cob=(9) +cfi=(58) +cfn=(2626) +calls=61 0 +0 11285 +0 244 +cob=(9) +cfi=(58) +cfn=(2626) +calls=61 0 +0 11285 +0 244 +cob=(9) +cfi=(58) +cfn=(2626) +calls=61 0 +0 12749 +0 1098 + +fn=(3076) +0 17 + +fn=(3082) +0 8011902402 +cob=(7) +cfi=(53) +cfn=(880) +calls=572278743 0 +0 63138838626 +0 3433672458 +cob=(7) +cfi=(53) +cfn=(1254) +calls=572278743 0 +0 11445574860 +0 4005951201 +cob=(7) +cfi=(53) +cfn=(2402) +calls=572278743 0 +0 17383328825 +0 6738364995 + +fn=(3222) +0 24 +cfn=(3224) +calls=2 0 +0 2978 +0 30 +cfn=(3228) +calls=2 0 +0 70 +0 12 +cfn=(3228) +calls=2 0 +0 78 +0 46 +cob=(7) +cfi=(53) +cfn=(1260) +calls=2 0 +0 72 +0 14 +cob=(7) +cfi=(53) +cfn=(1380) +calls=2 0 +0 30 +0 6 +cob=(7) +cfi=(53) +cfn=(1380) +calls=2 0 +0 30 +0 8 +cob=(7) +cfi=(53) +cfn=(2824) +calls=4 0 +0 60 +0 84 +cob=(7) +cfi=(53) +cfn=(1142) +calls=2 0 +0 162 +0 14 +cfn=(3230) +calls=2 0 +0 836 +0 16 + +fn=(3236) +0 172 +cob=(7) +cfi=(53) +cfn=(1142) +calls=12 0 +0 972 +0 90 +cfn=(3238) +calls=5 0 +0 3874 +0 685 +cfn=(3238) +calls=36 0 +0 7056 +0 1212 +cfn=(3256) +calls=36 0 +0 9236 +0 401 +cob=(7) +cfi=(53) +cfn=(880) +calls=12 0 +0 1378 +0 804 +cfn=(3238) +calls=12 0 +0 2352 +0 156 +cob=(7) +cfi=(53) +cfn=(1142) +calls=12 0 +0 972 +0 20 + +fn=(3292) BTS::Fibre::Set::Set(BTS::Fibre::Set const&) +0 32 +cfn=(2564) +calls=1 0 +0 759 +0 56 +cob=(7) +cfi=(53) +cfn=(880) +calls=1 0 +0 658 +0 37 +cfn=(3268) +calls=4 0 +0 9791 +0 132 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 250 +0 12 +cob=(7) +cfi=(53) +cfn=(1254) +calls=1 0 +0 20 +0 6 +cfn=(3078) +calls=1 0 +0 307 +0 3 +cob=(7) +cfi=(53) +cfn=(1380) +calls=1 0 +0 15 +0 23 + +fn=(3296) +0 342836 +cob=(7) +cfi=(53) +cfn=(934) +calls=6593 0 +0 1542836 +0 19779 +cfn=(3298) +calls=6593 0 +0 2097205 +0 26372 +cob=(7) +cfi=(53) +cfn=(1380) +calls=6593 0 +0 98895 +0 32965 + +fn=(3322) +0 124 +cfn=(3548) +calls=3 0 +0 33697212 +0 284 + +fn=(3352) +0 40 +cfn=(3354) +calls=2 0 +0 564 +0 2 + +fn=(3358) +0 20 +cfn=(3360) +calls=1 0 +0 312 +0 271 +cob=(6) +cfi=(137) +cfn=(3366) cos +calls=2 348 +0 152 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1382 +0 232 +cob=(6) +cfi=(137) +cfn=(3366) +calls=58 348 +0 6225 +0 677 + +fn=(3378) BTS::Diffusion::Response::weighting(BTS::Triple const&, BTS::Triple&, BTS::Coord::Tensor&) +0 1156498080 +cfn=(3380) +calls=14947200 0 +0 582940800 +0 209260800 +cfn=(3380) +calls=4982400 0 +0 194313600 +0 737395200 +cfn=(3380) +calls=19929600 0 +0 777254400 +0 79718400 +cfn=(3380) +calls=19929600 0 +0 777254400 +0 856972800 +cfn=(3380) +calls=19929600 0 +0 777254400 +0 1879112160 + +fn=(3398) +0 916704 +cfn=(3399) std::_Rb_tree, std::less, std::allocator >::_M_erase(std::_Rb_tree_node*)'2 +calls=83142 0 +0 25457931 +0 571599 +cfn=(3399) +calls=190533 0 +0 17388221 +0 821025 +cob=(7) +cfi=(53) +cfn=(1142) +calls=273675 0 +0 22167675 +0 1154817 + +fn=(3399) +0 5848616 +cfn=(3399) +calls=298166 0 +0 16254654 +0 279885 +cfn=(3399) +calls=93295 0 +0 1658237 +0 1174383 +cob=(7) +cfi=(53) +cfn=(1142) +calls=391461 0 +0 31708341 +0 3834927 + +fn=(3428) +0 14 +cfn=(3430) +calls=1 0 +0 815 +0 12 + +fn=(3430) +0 2886 +cob=(7) +cfi=(53) +cfn=(880) +calls=93 0 +0 42535 +0 288 +cob=(7) +cfi=(53) +cfn=(880) +calls=144 0 +0 58465 +0 2370 +cfn=(3424) +calls=237 0 +0 123714 +0 2370 +cob=(7) +cfi=(53) +cfn=(2402) +calls=237 0 +0 18923 +0 4304 + +fn=(3450) BTS::Image::Container::Buffer::new_voxel(BTS::Image::Coord const&) +0 5110 +cfn=(3224) +calls=365 0 +0 533851 +0 3650 +cob=(7) +cfi=(53) +cfn=(880) +calls=365 0 +0 6562624 +0 114245 +cfn=(3268) +calls=22265 0 +0 40727184 +0 90520 +cfn=(3274) +calls=365 0 +0 201480 +0 4745 + +fn=(3488) +0 1460 +cfn=(3490) BTS::Image::Voxel::Voxel(unsigned int) +calls=365 0 +0 126120081 +0 2555 + +fn=(3502) std::_Rb_tree >, std::_Select1st > >, std::less, std::allocator > > >::_M_insert_unique(std::pair > const&) +0 56 +cfn=(3504) +calls=4 0 +0 1099 +0 48 + +fn=(3526) +0 31887360 + +fn=(3560) +0 156 + +fn=(3570) +0 1907958 +cfn=(3224) +calls=146766 0 +0 217661542 +0 1174128 +cob=(7) +cfi=(53) +cfn=(2824) +calls=293532 0 +0 4402980 +0 3228852 +cfn=(2358) +calls=293532 0 +0 90254502 +0 5577108 +cob=(7) +cfi=(53) +cfn=(1142) +calls=146766 0 +0 11888046 +0 880596 +cfn=(3230) +calls=146766 0 +0 36397968 +0 1174128 + +fn=(3588) +0 1707756 +cfn=(3570) +calls=142313 0 +0 362493537 +0 2277008 +cfn=(3572) +calls=142313 0 +0 2988573 +0 426939 +cfn=(3574) +calls=142313 0 +0 28462600 +0 1992382 +cfn=(3590) +calls=142313 0 +0 18358377 +0 1423130 +cfn=(3590) +calls=142313 0 +0 17931438 +0 1707756 +cfn=(2374) +calls=142313 0 +0 43690091 +0 1138504 + +fn=(3600) +0 39528 +cfn=(3602) +calls=3294 0 +0 3848368 +0 52704 +cfn=(3572) +calls=3294 0 +0 69174 +0 9882 +cfn=(3574) +calls=3294 0 +0 121878 +0 46116 +cfn=(3590) +calls=3294 0 +0 362340 +0 23058 +cfn=(2374) +calls=3294 0 +0 665388 +0 26352 + +fn=(1054) +0 6 + +fn=(1066) +0 11 +cfn=(1070) +calls=1 0 +0 8529 +0 150 +cfn=(1162) +calls=1 0 +0 2841 +cfn=(1116) +calls=1 0 +0 3233 +cfn=(1218) +calls=1 0 +0 2459 +cfn=(1158) +calls=1 0 +0 3183 +cfn=(1216) global constructors keyed to KMcenters.cpp +calls=1 0 +0 2367 +cfn=(1112) +calls=1 0 +0 3631 +cfn=(1092) +calls=1 0 +0 3229 +cfn=(1200) +calls=1 0 +0 94 +cfn=(1106) global constructors keyed to buffer.cpp +calls=1 0 +0 3572 +cfn=(1154) +calls=1 0 +0 2841 +cfn=(1214) +calls=1 0 +0 94 +cfn=(1212) +calls=1 0 +0 3232 +cfn=(1100) global constructors keyed to momentum.cpp +calls=1 0 +0 2838 +cfn=(1210) +calls=1 0 +0 3590 +cfn=(1112) +calls=1 0 +0 2838 +cfn=(1208) +calls=1 0 +0 3233 +cfn=(1206) +calls=1 0 +0 2367 +cfn=(1106) +calls=1 0 +0 3573 +cfn=(1204) +calls=1 0 +0 94 +cfn=(1202) +calls=1 0 +0 2367 +cfn=(1200) +calls=1 0 +0 2838 +cfn=(1106) +calls=1 0 +0 2838 +cfn=(1198) +calls=1 0 +0 3183 +cfn=(1196) global constructors keyed to extended.cpp +calls=1 0 +0 521 +cfn=(1194) +calls=1 0 +0 2367 +cfn=(1106) +calls=1 0 +0 3222 +cfn=(1180) global constructors keyed to tensor.cpp +calls=1 0 +0 2838 +cfn=(1192) global constructors keyed to KM_ANN.cpp +calls=1 0 +0 2712 +cfn=(1158) +calls=1 0 +0 2841 +cfn=(1190) +calls=1 0 +0 2459 +cfn=(1180) +calls=1 0 +0 477 +cfn=(1188) +calls=1 0 +0 2367 +cfn=(1186) +calls=1 0 +0 94 +cfn=(1106) +calls=1 0 +0 3563 +cfn=(1184) +calls=1 0 +0 4372 +cfn=(1158) +calls=1 0 +0 2838 +cfn=(1182) +calls=1 0 +0 2367 +cfn=(1180) +calls=1 0 +0 822 +cfn=(1178) +calls=1 0 +0 2367 +cfn=(1176) global constructors keyed to state.cpp +calls=1 0 +0 480 +cfn=(1158) +calls=1 0 +0 2841 +cfn=(1174) +calls=1 0 +0 3234 +cfn=(1172) +calls=1 0 +0 3564 +cfn=(1170) +calls=1 0 +0 2838 +cfn=(1158) +calls=1 0 +0 2841 +cfn=(1112) +calls=1 0 +0 3638 +cfn=(1168) global constructors keyed to likelihood.cpp +calls=1 0 +0 3398 +cfn=(1166) +calls=1 0 +0 3228 +cfn=(1156) +calls=1 0 +0 3237 +cfn=(1164) +calls=1 0 +0 3183 +cfn=(1162) +calls=1 0 +0 4586 +cfn=(1160) +calls=1 0 +0 3223 +cfn=(1158) +calls=1 0 +0 3186 +cfn=(1156) +calls=1 0 +0 3231 +cfn=(1100) +calls=1 0 +0 2838 +cfn=(1154) +calls=1 0 +0 3227 +cfn=(1152) +calls=1 0 +0 3362 +cfn=(1120) +calls=1 0 +0 18034 +cfn=(1094) +calls=1 0 +0 477 +cfn=(1118) +calls=1 0 +0 3232 +cfn=(1116) +calls=1 0 +0 3578 +cfn=(1114) +calls=1 0 +0 94 +cfn=(1112) +calls=1 0 +0 3242 +cfn=(1110) +calls=1 0 +0 3223 +cfn=(1108) +calls=1 0 +0 526 +cfn=(1106) +calls=1 0 +0 3578 +cfn=(1104) +calls=1 0 +0 2838 +cfn=(1102) +calls=1 0 +0 3227 +cfn=(1100) +calls=1 0 +0 94 +cfn=(1098) +calls=1 0 +0 3222 +cfn=(1096) +calls=1 0 +0 3569 +cfn=(1094) +calls=1 0 +0 94 +cfn=(1092) +calls=1 0 +0 3227 +cfn=(1090) global constructors keyed to properties.cpp +calls=1 0 +0 94 +cfn=(1088) +calls=1 0 +0 2845 +0 232 + +fn=(1090) +0 3 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 + +fn=(1100) +0 5 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 324 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 323 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 9 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 324 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 323 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 7 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 + +fn=(1168) +0 5 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 324 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 323 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 407 +0 38 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 49 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 7 + +fn=(1176) +0 5 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 + +fn=(1386) std::vector >::operator=(std::vector > const&) +0 1128 + +fn=(2368) +0 112 +cob=(7) +cfi=(53) +cfn=(1254) +calls=12 0 +0 200 +0 92 + +fn=(2484) +0 2879 +cob=(9) +cfi=(58) +cfn=(2478) +calls=2 0 +0 510 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 947 +0 10 + +fn=(2630) +0 31 +cob=(7) +cfi=(53) +cfn=(880) +calls=1 0 +0 343 +0 872 + +fn=(2788) +0 297 +cfn=(2790) +calls=27 0 +0 108 +0 324 +cob=(7) +cfi=(53) +cfn=(880) +calls=27 0 +0 7216 +0 7425 + +fn=(2798) +0 345 +cob=(7) +cfi=(53) +cfn=(880) +calls=7 0 +0 2148 +0 40 +cob=(7) +cfi=(53) +cfn=(880) +calls=20 0 +0 5721 +0 864 +cob=(4) +cfi=(113) +cfn=(1794) +calls=27 47 +0 648 +0 621 +cob=(7) +cfi=(53) +cfn=(2402) +calls=27 0 +0 1217 +0 576 + +fn=(2976) BTS::Diffusion::Response* std::__uninitialized_copy_a(BTS::Diffusion::Response*, BTS::Diffusion::Response*, BTS::Diffusion::Response*, std::allocator&) +0 1131 +cfn=(2862) +calls=63 0 +0 24098 +0 5412 + +fn=(3052) +0 23 +cfn=(3054) std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::_M_copy(std::_Rb_tree_node > const*, std::_Rb_tree_node >*) +calls=1 0 +0 18214 +0 88 +cob=(7) +cfi=(53) +cfn=(880) +calls=1 0 +0 179 +0 874 + +fn=(3054) +0 12 +cob=(7) +cfi=(53) +cfn=(880) +calls=1 0 +0 195 +0 26 +cob=(7) +cfi=(53) +cfn=(880) +calls=1 0 +0 180 +0 13 +cob=(4) +cfi=(113) +cfn=(1794) +calls=1 47 +0 215 +0 27 +cfn=(3055) std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::_M_copy(std::_Rb_tree_node > const*, std::_Rb_tree_node >*)'2 +calls=1 0 +0 11480 +0 8 +cob=(7) +cfi=(53) +cfn=(880) +calls=1 0 +0 195 +0 4 +cob=(7) +cfi=(53) +cfn=(880) +calls=2 0 +0 390 +0 78 +cob=(7) +cfi=(53) +cfn=(880) +calls=3 0 +0 540 +0 39 +cob=(4) +cfi=(113) +cfn=(1794) +calls=3 47 +0 645 +0 86 +cfn=(3055) +calls=2 0 +0 4058 +0 23 + +fn=(3055) +0 204 +cob=(7) +cfi=(53) +cfn=(880) +calls=17 0 +0 3315 +0 442 +cob=(7) +cfi=(53) +cfn=(880) +calls=17 0 +0 3060 +0 221 +cob=(4) +cfi=(113) +cfn=(1794) +calls=17 47 +0 3655 +0 423 +cfn=(3055) +calls=8 0 +0 14888 +0 79 +cob=(7) +cfi=(53) +cfn=(880) +calls=5 0 +0 975 +0 2 +cob=(7) +cfi=(53) +cfn=(880) +calls=1 0 +0 195 +0 156 +cob=(7) +cfi=(53) +cfn=(880) +calls=6 0 +0 1080 +0 78 +cob=(4) +cfi=(113) +cfn=(1794) +calls=6 47 +0 1290 +0 180 +cfn=(3055) +calls=6 0 +0 6762 +0 183 + +fn=(3090) BTS::File::has_extension(std::string const&, std::string const&) +0 22 +cob=(7) +cfi=(53) +cfn=(1708) +calls=1 0 +0 206 +0 9 +cob=(7) +cfi=(53) +cfn=(1380) +calls=1 0 +0 100 +0 9 + +fn=(3208) std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::erase(std::string const&) +0 820 +cfn=(2618) +calls=4 0 +0 928 +0 219 +cob=(7) +cfi=(53) +cfn=(2830) +calls=5 0 +0 50 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1971 +0 20 +cob=(7) +cfi=(53) +cfn=(3218) +calls=5 0 +0 259 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 2171 +0 15 +cob=(7) +cfi=(53) +cfn=(1380) +calls=5 0 +0 415 +0 10 +cob=(7) +cfi=(53) +cfn=(1380) +calls=5 0 +0 75 +0 10 +cob=(7) +cfi=(53) +cfn=(1142) +calls=5 0 +0 405 +0 111 + +fn=(3224) +0 41189760 +cob=(7) +cfi=(53) +cfn=(880) +calls=1287180 0 +0 144025430 +0 142876980 +cfn=(3226) +calls=1287180 0 +0 1540279829 +0 10297440 + +fn=(3226) +0 601876408 +cob=(7) +cfi=(53) +cfn=(934) +calls=42991172 0 +0 9669743026 +0 515894064 +cob=(7) +cfi=(53) +cfn=(1380) +calls=42991172 0 +0 644867580 +0 257947032 +cob=(7) +cfi=(53) +cfn=(934) +calls=42991172 0 +0 9713540435 +0 429911720 +cob=(7) +cfi=(53) +cfn=(2414) +calls=42991172 0 +0 730849924 +0 343929376 +cob=(7) +cfi=(53) +cfn=(2414) +calls=42991172 0 +0 730849924 +0 257947032 +cob=(7) +cfi=(53) +cfn=(1380) +calls=42991172 0 +0 644867580 +0 558885236 +cob=(7) +cfi=(53) +cfn=(1254) +calls=42991172 0 +0 859823440 +0 214955860 +cfn=(3078) +calls=42991172 0 +0 10788842090 +0 128973516 +cob=(7) +cfi=(53) +cfn=(1380) +calls=42991172 0 +0 644867580 +0 214955860 +cob=(7) +cfi=(53) +cfn=(1254) +calls=42991172 0 +0 859823440 +0 214955860 +cfn=(3078) +calls=42991172 0 +0 10722422507 +0 128973516 +cob=(7) +cfi=(53) +cfn=(1380) +calls=42991172 0 +0 644867580 +0 128973516 + +fn=(3306) BTS::Prob::Likelihood::ImageDiff::log_prob(BTS::Fibre::Tract::Set const&, BTS::Fibre::Tract::Set&, BTS::Fibre::Tract::Set::Tensor&) +0 1 +cfn=(3308) +calls=1 0 +0 1323487772479 + +fn=(3310) +0 4 +cfn=(3312) +calls=1 0 +0 1321052384410 +0 3 + +fn=(3334) +0 72 +cfn=(3336) +calls=4 0 +0 181568913 +0 25825492 +cfn=(3378) +calls=5065440 0 +0 8027975040 +0 26572800 +cfn=(3382) +calls=83040 0 +0 27267338 +0 1245600 +cfn=(3446) +calls=83040 0 +0 92475768 +0 1865012 +cfn=(3546) +calls=83040 0 +0 1245600 +0 166096 +cob=(7) +cfi=(53) +cfn=(1142) +calls=4 0 +0 58078 +0 57999947 +cfn=(3448) +calls=365 0 +0 101267326 +0 7300 +cfn=(3268) +calls=365 0 +0 705465 +0 191260 +cfn=(3466) +calls=22265 0 +0 18718092 +0 270465 +cfn=(3274) +calls=365 0 +0 291270 +0 1992960 +cfn=(3448) +calls=664320 0 +0 80417440 +0 51295711 +cfn=(3268) +calls=365 0 +0 705180 +0 1460 +cfn=(3268) +calls=365 0 +0 781538 +0 1825 +cfn=(3470) BTS::Fibre::BasicStrand::Tensor_tpl::Tensor_tpl(int, BTS::Fibre::Tract const&) +calls=365 0 +0 24483229 +0 1825 +cfn=(3474) +calls=365 0 +0 50301647 +0 730 +cfn=(3476) +calls=365 0 +0 2685004 +0 730 +cfn=(3478) +calls=365 0 +0 429605 +0 2190 +cfn=(3486) +calls=365 0 +0 285463167 +0 260245 +cfn=(3514) std::vector, std::allocator > >::operator=(std::vector, std::allocator > > const&) +calls=22265 0 +0 3282116979 +0 66795 +cfn=(3466) +calls=22265 0 +0 14939815 +0 155855 +cfn=(3466) +calls=22265 0 +0 14939815 +0 293825 +cfn=(3494) +calls=365 0 +0 8847833 +0 1460 +cfn=(3494) +calls=365 0 +0 8837664 +0 1992960 +cfn=(3486) +calls=664320 0 +0 80417440 +0 7307520 +cfn=(3520) +calls=664320 0 +0 385969920 +0 9300480 +cfn=(3314) +calls=664320 0 +0 5314560 +0 162094080 +cfn=(3314) +calls=40523520 0 +0 324188160 +0 2311169280 +cfn=(3530) +calls=40523520 0 +0 6605333760 +0 121570560 +cfn=(3530) +calls=40523520 0 +0 6605333760 +0 3768687360 +cfn=(3532) +calls=40523520 0 +0 15804172800 +0 932040960 +cfn=(3534) +calls=40523520 0 +0 374599589215 +0 4700728320 +cob=(7) +cfi=(53) +cfn=(880) +calls=40523520 0 +0 4457587200 +0 1337276160 +cob=(7) +cfi=(53) +cfn=(880) +calls=40523520 0 +0 4457587200 +0 2593505280 +cob=(7) +cfi=(53) +cfn=(880) +calls=121570560 0 +0 13372761600 +0 6321669120 +cob=(7) +cfi=(53) +cfn=(1142) +calls=40523520 0 +0 3282405120 +0 81047040 +cfn=(3226) +calls=40523520 0 +0 47412544963 +0 162094080 +cfn=(3534) +calls=40523520 0 +0 374599586158 +0 567329280 +cfn=(3536) +calls=40523520 0 +0 3525546240 +0 405235200 +cfn=(3536) +calls=81047040 0 +0 7051092480 +0 381245276160 +cfn=(3274) +calls=40523520 0 +0 32337768960 +0 243141120 +cfn=(3434) +calls=40523520 0 +0 607852800 +0 162094080 +cfn=(3434) +calls=40523520 0 +0 607852800 +0 162094080 +cfn=(3434) +calls=40523520 0 +0 607852800 +0 162094080 +cfn=(3434) +calls=40523520 0 +0 607852800 +0 162094080 +cfn=(3434) +calls=40523520 0 +0 607852800 +0 162094080 +cfn=(3434) +calls=40523520 0 +0 607852800 +0 121570560 +cfn=(3434) +calls=40523520 0 +0 607852800 +0 892846080 +cob=(7) +cfi=(53) +cfn=(2824) +calls=664320 0 +0 9628322 +0 1330100 +cfn=(3492) +calls=365 0 +0 50871544 +0 27523043 +cfn=(3398) +calls=83040 0 +0 68390592 +0 27247753 + +fn=(3342) +0 40 +cfn=(3344) +calls=2 0 +0 839 +0 2 + +fn=(3404) +0 474 +cfn=(3406) +calls=237 0 +0 3580465 + +fn=(3436) +0 2607 +cfn=(2802) +calls=237 0 +0 138118 +0 353841 +cfn=(3420) +calls=1659 0 +0 850431 +0 5214 + +fn=(3498) +0 16425 + +fn=(3508) +0 16790 +cob=(7) +cfi=(53) +cfn=(880) +calls=365 0 +0 434702 +0 2190 +cfn=(3510) +calls=365 0 +0 120397243 +0 5110 + +fn=(3516) std::vector, std::allocator > >::operator=(std::vector, std::allocator > > const&) +0 3072570 +cob=(7) +cfi=(53) +cfn=(880) +calls=66795 0 +0 11410373 +0 400770 +cfn=(3518) +calls=66795 0 +0 3264516936 +0 801540 + +fn=(3536) +0 52883193600 + +fn=(3554) +0 24 +cfn=(3294) +calls=3 0 +0 3610 +0 48 +cfn=(3556) +calls=3 0 +0 6925 +0 54 +cfn=(3556) +calls=9 0 +0 18774 +0 117 + +fn=(3572) +0 3151260 + +fn=(3606) +0 191052 + +fn=(3682) BTS::Image::Expected::Trilinear::Buffer::~Buffer() +0 7 +cfn=(3684) +calls=1 0 +0 66 + +fn=(1106) +0 6 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 407 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 324 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 323 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 313 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 14 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 324 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 407 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 323 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 13 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 10 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 324 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 323 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 10 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 324 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 323 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 308 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 14 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 324 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 407 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 323 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 304 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 14 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 407 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 324 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 323 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 8 + +fn=(1180) +0 5 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 324 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 323 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 8 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 7 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 407 +0 3 + +fn=(1192) +0 7 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 6 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 324 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 407 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 323 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 + +fn=(1196) +0 5 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 350 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 + +fn=(1216) +0 7 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 6 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 324 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 323 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 + +fn=(1368) +0 11 +cob=(4) +cfi=(90) +cfn=(1272) +calls=1 32 +0 8 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1642 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 234 +0 5 +cfn=(1374) MR::App::get_options(std::string const&) +calls=1 0 +0 28 +0 2 +cob=(7) +cfi=(53) +cfn=(1380) +calls=1 0 +0 1177 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1414 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 233 +0 5 +cfn=(1374) +calls=1 0 +0 28 +0 3 +cfn=(1386) +calls=1 0 +0 47 +0 2 +cfn=(1388) +calls=1 0 +0 15 +0 2 +cob=(7) +cfi=(53) +cfn=(1380) +calls=1 0 +0 100 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 230 +0 5 +cfn=(1374) +calls=1 0 +0 28 +0 3 +cfn=(1386) +calls=1 0 +0 47 +0 2 +cfn=(1388) +calls=1 0 +0 15 +0 2 +cob=(7) +cfi=(53) +cfn=(1380) +calls=1 0 +0 100 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 235 +0 5 +cfn=(1374) +calls=1 0 +0 28 +0 3 +cfn=(1386) +calls=1 0 +0 47 +0 2 +cfn=(1388) +calls=1 0 +0 15 +0 2 +cob=(7) +cfi=(53) +cfn=(1380) +calls=1 0 +0 100 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 225 +0 5 +cfn=(1374) +calls=1 0 +0 28 +0 3 +cfn=(1386) +calls=1 0 +0 47 +0 2 +cfn=(1388) +calls=1 0 +0 15 +0 2 +cob=(7) +cfi=(53) +cfn=(1380) +calls=1 0 +0 100 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 219 +0 5 +cfn=(1374) +calls=1 0 +0 28 +0 3 +cfn=(1386) +calls=1 0 +0 47 +0 2 +cfn=(1388) +calls=1 0 +0 15 +0 2 +cob=(7) +cfi=(53) +cfn=(1380) +calls=1 0 +0 100 +0 10 +cob=(7) +cfi=(53) +cfn=(1394) +calls=1 0 +0 5148 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 2456 +0 3 +cob=(7) +cfi=(53) +cfn=(1436) +calls=1 0 +0 4864 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1648 +0 12 +cob=(7) +cfi=(53) +cfn=(1474) +calls=1 0 +0 1910 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1412 +0 2 +cob=(7) +cfi=(53) +cfn=(1498) +calls=1 0 +0 1762 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1444 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 224 +0 5 +cfn=(1374) +calls=1 0 +0 28 +0 3 +cfn=(1386) +calls=1 0 +0 47 +0 2 +cfn=(1388) +calls=1 0 +0 15 +0 2 +cob=(7) +cfi=(53) +cfn=(1380) +calls=1 0 +0 100 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 238 +0 5 +cfn=(1374) +calls=1 0 +0 28 +0 3 +cfn=(1386) +calls=1 0 +0 47 +0 2 +cfn=(1388) +calls=1 0 +0 15 +0 2 +cob=(7) +cfi=(53) +cfn=(1380) +calls=1 0 +0 100 +0 11 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 271 +0 14 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 238 +0 5 +cfn=(1374) +calls=1 0 +0 28 +0 3 +cfn=(1386) +calls=1 0 +0 47 +0 2 +cfn=(1388) +calls=1 0 +0 15 +0 2 +cob=(7) +cfi=(53) +cfn=(1380) +calls=1 0 +0 100 +0 11 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 249 +0 5 +cfn=(1374) +calls=1 0 +0 28 +0 3 +cfn=(1386) +calls=1 0 +0 47 +0 2 +cfn=(1388) +calls=1 0 +0 15 +0 2 +cob=(7) +cfi=(53) +cfn=(1380) +calls=1 0 +0 100 +0 11 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 234 +0 5 +cfn=(1374) +calls=1 0 +0 28 +0 3 +cfn=(1386) +calls=1 0 +0 47 +0 2 +cfn=(1388) +calls=1 0 +0 15 +0 2 +cob=(7) +cfi=(53) +cfn=(1380) +calls=1 0 +0 100 +0 12 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 225 +0 5 +cfn=(1374) +calls=1 0 +0 28 +0 3 +cfn=(1386) +calls=1 0 +0 47 +0 2 +cfn=(1388) +calls=1 0 +0 15 +0 2 +cob=(7) +cfi=(53) +cfn=(1380) +calls=1 0 +0 100 +0 10 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 228 +0 5 +cfn=(1374) +calls=1 0 +0 28 +0 3 +cfn=(1386) +calls=1 0 +0 47 +0 2 +cfn=(1388) +calls=1 0 +0 15 +0 2 +cob=(7) +cfi=(53) +cfn=(1380) +calls=1 0 +0 100 +0 25 +cfn=(1512) +calls=1 0 +0 829014 +0 12 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 234 +0 13 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 243 +0 5 +cfn=(1374) +calls=1 0 +0 28 +0 3 +cfn=(1386) +calls=1 0 +0 47 +0 2 +cfn=(1388) +calls=1 0 +0 15 +0 2 +cob=(7) +cfi=(53) +cfn=(1380) +calls=1 0 +0 100 +0 11 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 245 +0 5 +cfn=(1374) +calls=1 0 +0 28 +0 3 +cfn=(1386) +calls=1 0 +0 47 +0 2 +cfn=(1388) +calls=1 0 +0 15 +0 2 +cob=(7) +cfi=(53) +cfn=(1380) +calls=1 0 +0 100 +0 11 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 219 +0 5 +cfn=(1374) +calls=1 0 +0 28 +0 3 +cfn=(1386) +calls=1 0 +0 47 +0 2 +cfn=(1388) +calls=1 0 +0 15 +0 2 +cob=(7) +cfi=(53) +cfn=(1380) +calls=1 0 +0 100 +0 11 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 234 +0 5 +cfn=(1374) +calls=1 0 +0 28 +0 3 +cfn=(1386) +calls=1 0 +0 47 +0 2 +cfn=(1388) +calls=1 0 +0 15 +0 2 +cob=(7) +cfi=(53) +cfn=(1380) +calls=1 0 +0 100 +0 11 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 241 +0 5 +cfn=(1374) +calls=1 0 +0 28 +0 3 +cfn=(1386) +calls=1 0 +0 47 +0 2 +cfn=(1388) +calls=1 0 +0 15 +0 2 +cob=(7) +cfi=(53) +cfn=(1380) +calls=1 0 +0 100 +0 11 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 234 +0 5 +cfn=(1374) +calls=1 0 +0 28 +0 3 +cfn=(1386) +calls=1 0 +0 47 +0 2 +cfn=(1388) +calls=1 0 +0 15 +0 2 +cob=(7) +cfi=(53) +cfn=(1380) +calls=1 0 +0 100 +0 11 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 235 +0 5 +cfn=(1374) +calls=1 0 +0 28 +0 3 +cfn=(1386) +calls=1 0 +0 47 +0 2 +cfn=(1388) +calls=1 0 +0 15 +0 2 +cob=(7) +cfi=(53) +cfn=(1380) +calls=1 0 +0 100 +0 10 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 219 +0 11 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 219 +0 5 +cfn=(1374) +calls=1 0 +0 28 +0 3 +cfn=(1386) +calls=1 0 +0 47 +0 2 +cfn=(1388) +calls=1 0 +0 15 +0 2 +cob=(7) +cfi=(53) +cfn=(1380) +calls=1 0 +0 100 +0 11 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 223 +0 5 +cfn=(1374) +calls=1 0 +0 28 +0 3 +cfn=(1386) +calls=1 0 +0 47 +0 2 +cfn=(1388) +calls=1 0 +0 15 +0 2 +cob=(7) +cfi=(53) +cfn=(1380) +calls=1 0 +0 100 +0 11 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 230 +0 5 +cfn=(1374) +calls=1 0 +0 28 +0 3 +cfn=(1386) +calls=1 0 +0 47 +0 2 +cfn=(1388) +calls=1 0 +0 15 +0 2 +cob=(7) +cfi=(53) +cfn=(1380) +calls=1 0 +0 100 +0 13 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 235 +0 5 +cfn=(1374) +calls=1 0 +0 28 +0 3 +cfn=(1386) +calls=1 0 +0 47 +0 2 +cfn=(1388) +calls=1 0 +0 15 +0 2 +cob=(7) +cfi=(53) +cfn=(1380) +calls=1 0 +0 100 +0 12 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 57 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 219 +0 5 +cfn=(1374) +calls=1 0 +0 28 +0 3 +cfn=(1386) +calls=1 0 +0 47 +0 2 +cfn=(1388) +calls=1 0 +0 15 +0 2 +cob=(7) +cfi=(53) +cfn=(1380) +calls=1 0 +0 100 +0 13 +cfn=(1946) +calls=1 0 +0 14854 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 466 +0 41 +cfn=(1950) +calls=1 0 +0 2354071 +0 2 +cob=(7) +cfi=(53) +cfn=(1380) +calls=1 0 +0 100 +0 4 +cob=(7) +cfi=(53) +cfn=(1142) +calls=1 0 +0 114 +0 9 +cfn=(2854) +calls=1 0 +0 7084275 +0 16 +cfn=(3000) +calls=1 0 +0 38923 +0 7 +cfn=(3048) +calls=1 0 +0 89880 +0 6 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 349 +0 53 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 13 +cob=(7) +cfi=(53) +cfn=(1380) +calls=1 0 +0 15 +0 3 +cfn=(2618) +calls=1 0 +0 11 +0 7 +cfn=(3084) +calls=1 0 +0 218874 +0 2 +cob=(7) +cfi=(53) +cfn=(1380) +calls=1 0 +0 100 +0 5 +cfn=(3292) +calls=1 0 +0 12101 +0 4 +cfn=(3294) +calls=1 0 +0 1123 +0 16 +cfn=(3304) +calls=1 0 +0 2217 +0 15 +cfn=(3304) +calls=3 0 +0 6129 +0 226 +cfn=(3294) +calls=1 0 +0 1007 +0 16 +cfn=(3304) +calls=1 0 +0 2043 +0 15 +cfn=(3304) +calls=3 0 +0 6129 +0 69984 +cfn=(3306) +calls=1 0 +0 1323487772480 +0 3 +cob=(7) +cfi=(53) +cfn=(3614) +calls=1 0 +0 8381 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1632 +0 12 +cob=(7) +cfi=(53) +cfn=(1474) +calls=1 0 +0 245 +0 2 +cob=(7) +cfi=(53) +cfn=(1498) +calls=1 0 +0 73 +0 4 +cob=(7) +cfi=(53) +cfn=(1394) +calls=1 0 +0 251 +0 11 +cob=(7) +cfi=(53) +cfn=(1474) +calls=1 0 +0 245 +0 2 +cob=(7) +cfi=(53) +cfn=(1498) +calls=1 0 +0 73 +0 4 +cob=(9) +cfi=(58) +cfn=(2626) +calls=1 0 +0 1388 +0 5 +cfn=(3300) +calls=1 0 +0 4177 +0 5 +cfn=(3300) +calls=1 0 +0 4857 +0 250 +cob=(9) +cfi=(58) +cfn=(2626) +calls=61 0 +0 10065 +0 187 +cob=(7) +cfi=(53) +cfn=(1142) +calls=1 0 +0 108 +0 7 +cob=(7) +cfi=(53) +cfn=(1142) +calls=1 0 +0 108 +0 7 +cfn=(2618) +calls=1 0 +0 4900 +0 7 +cfn=(2628) +calls=1 0 +0 5909 +0 2 +cob=(7) +cfi=(53) +cfn=(1380) +calls=1 0 +0 7 +0 2 +cob=(7) +cfi=(53) +cfn=(1380) +calls=1 0 +0 100 +0 2 +cob=(7) +cfi=(53) +cfn=(1380) +calls=1 0 +0 100 +0 5 +cob=(9) +cfi=(58) +cfn=(2626) +calls=1 0 +0 203 +0 5 +cob=(7) +cfi=(53) +cfn=(1380) +calls=1 0 +0 100 +0 2 +cob=(7) +cfi=(53) +cfn=(1380) +calls=1 0 +0 7 +0 2 +cfn=(1388) +calls=1 0 +0 15 +0 14 +cob=(7) +cfi=(53) +cfn=(1254) +calls=1 0 +0 20 +0 5 +cfn=(3078) +calls=1 0 +0 334 +0 3 +cob=(7) +cfi=(53) +cfn=(1380) +calls=1 0 +0 15 +0 6 +cob=(9) +cfi=(58) +cfn=(1868) +calls=1 0 +0 663 +0 3 + +fn=(1374) +0 700 + +fn=(1742) +0 158 +cob=(7) +cfi=(53) +cfn=(880) +calls=7 0 +0 1764 +0 1496 +cob=(7) +cfi=(53) +cfn=(1142) +calls=6 0 +0 548 +0 157 + +fn=(2374) +0 5066308 +cob=(7) +cfi=(53) +cfn=(1380) +calls=150068 0 +0 15006088 +0 293564 +cob=(7) +cfi=(53) +cfn=(1380) +calls=146782 0 +0 14676744 +0 3221861 +cob=(7) +cfi=(53) +cfn=(1142) +calls=150068 0 +0 12155508 +0 1707780 + +fn=(2394) +0 161 +cfn=(2396) +calls=7 0 +0 3798 +0 28 + +fn=(2628) +0 32 +cfn=(2629) std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::_M_erase(std::_Rb_tree_node >*)'2 +calls=1 0 +0 3711 +0 9 +cfn=(2629) +calls=3 0 +0 1351 +0 24 +cob=(7) +cfi=(53) +cfn=(1142) +calls=4 0 +0 450 +0 12 +cob=(7) +cfi=(53) +cfn=(1142) +calls=4 0 +0 324 +0 26 + +fn=(2629) +0 328 +cfn=(2629) +calls=17 0 +0 5045 +0 18 +cfn=(2629) +calls=6 0 +0 2268 +0 138 +cob=(7) +cfi=(53) +cfn=(1142) +calls=23 0 +0 2438 +0 69 +cob=(7) +cfi=(53) +cfn=(1142) +calls=23 0 +0 1863 +0 208 + +fn=(2794) +0 442 +cob=(7) +cfi=(53) +cfn=(2812) +calls=20 0 +0 1605 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1979 +0 130 +cfn=(2798) +calls=6 0 +0 2925 +0 206 +cfn=(2796) +calls=1 0 +0 273 +0 79 +cfn=(2798) +calls=6 0 +0 2482 +0 216 +cfn=(2798) +calls=14 0 +0 6526 +0 28 + +fn=(2832) +0 9 +cob=(7) +cfi=(53) +cfn=(1380) +calls=1 0 +0 7 + +fn=(2860) +0 549 +cfn=(2862) +calls=61 0 +0 14245 +0 488 +cfn=(2864) +calls=61 0 +0 6305123 +0 244 + +fn=(2958) +0 854 + +fn=(2974) +0 427 +cfn=(2862) +calls=7 0 +0 1965 +0 586 +cfn=(2976) +calls=7 0 +0 30494 +0 49 +cfn=(2976) +calls=7 0 +0 147 +0 294 +cob=(9) +cfi=(58) +cfn=(2626) +calls=63 0 +0 10395 +0 215 +cob=(7) +cfi=(53) +cfn=(1142) +calls=6 0 +0 731 +0 73 +cob=(7) +cfi=(53) +cfn=(880) +calls=7 0 +0 5577 +0 52 + +fn=(3072) +0 6588 +cfn=(3074) +calls=1647 0 +0 6588 + +fn=(3088) +0 20 +cfn=(3090) +calls=1 0 +0 346 +0 14 +cob=(7) +cfi=(53) +cfn=(1708) +calls=1 0 +0 291 +0 8 +cob=(7) +cfi=(53) +cfn=(1380) +calls=1 0 +0 100 +0 7 + +fn=(3204) +0 1592 +cfn=(3206) +calls=9 0 +0 30588 +0 36 +cfn=(3208) +calls=9 0 +0 7479 +0 18 +cob=(7) +cfi=(53) +cfn=(2830) +calls=9 0 +0 129 +0 72 + +fn=(3262) +0 24 +cfn=(3204) +calls=4 0 +0 32025 +0 8 +cfn=(3264) BTS::Fibre::Tract::normalize_base_width() +calls=4 0 +0 460 +0 20 + +fn=(3264) +0 460 + +fn=(3270) +0 81 +cfn=(3268) +calls=3 0 +0 6840 +0 59 + +fn=(3328) +0 96 + +fn=(3330) +0 124 +cfn=(3550) +calls=3 0 +0 2141456622 +0 284 + +fn=(3380) +0 7850269440 + +fn=(3420) +0 68256 +cob=(7) +cfi=(53) +cfn=(880) +calls=3318 0 +0 2953326 +0 397686 +cob=(7) +cfi=(53) +cfn=(1142) +calls=2844 0 +0 268786 +0 67782 + +fn=(3448) +0 50780717 +cfn=(3450) +calls=365 0 +0 48243409 +0 30274212 +cfn=(3452) +calls=365 0 +0 16425 +0 1460 +cfn=(3454) std::_Rb_tree >, std::_Select1st > >, std::less, std::allocator > > >::_M_insert_unique_(std::_Rb_tree_const_iterator > >, std::pair > const&) +calls=365 0 +0 135529 +0 1095 +cfn=(3460) +calls=365 0 +0 6570 +0 730 +cfn=(3460) +calls=365 0 +0 6570 +0 1095 +cfn=(3462) +calls=365 0 +0 40305124 +0 2190 +cfn=(3460) +calls=365 0 +0 12470267 +0 2159 + +fn=(3454) +0 6484 +cob=(7) +cfi=(53) +cfn=(2812) +calls=296 0 +0 4733 +0 2440 +cfn=(3458) +calls=192 0 +0 58769 +0 3174 +cfn=(3456) +calls=4 0 +0 1392 +0 300 +cfn=(3458) +calls=22 0 +0 7064 +0 2686 +cfn=(3458) +calls=147 0 +0 48263 +0 224 + +fn=(3470) +0 5110 +cfn=(3224) +calls=365 0 +0 522315 +0 1095 +cfn=(3224) +calls=365 0 +0 522315 +0 1095 +cfn=(3224) +calls=365 0 +0 522315 +0 31025 +cfn=(3268) +calls=365 0 +0 781242 +0 1460 +cfn=(3268) +calls=365 0 +0 781346 +0 1460 +cfn=(3268) +calls=365 0 +0 781221 +0 1460 +cfn=(3268) +calls=365 0 +0 781055 +0 1095 +cfn=(3466) +calls=365 0 +0 320967 +0 2555 +cfn=(3466) +calls=365 0 +0 321069 +0 2555 +cfn=(3466) +calls=365 0 +0 321229 +0 2190 +cfn=(3274) +calls=365 0 +0 291270 +0 730 +cfn=(3274) +calls=365 0 +0 291270 +0 730 +cfn=(3274) +calls=365 0 +0 291270 +0 730 +cfn=(3274) +calls=365 0 +0 291270 +0 4745 +cob=(7) +cfi=(53) +cfn=(880) +calls=365 0 +0 61639 +0 8395 +cfn=(3472) +calls=1095 0 +0 16649881 +0 6205 +cfn=(3274) +calls=365 0 +0 291270 +0 1095 +cfn=(3274) +calls=365 0 +0 291270 +0 1095 +cfn=(3274) +calls=365 0 +0 291270 +0 2920 + +fn=(3490) +0 9490 +cfn=(3224) +calls=365 0 +0 522315 +0 1095 +cfn=(3224) +calls=365 0 +0 522315 +0 2920 +cob=(7) +cfi=(53) +cfn=(880) +calls=365 0 +0 40150 +0 38690 +cfn=(3478) +calls=365 0 +0 429605 +0 4745 +cob=(7) +cfi=(53) +cfn=(880) +calls=365 0 +0 2950619 +0 114975 +cfn=(3492) +calls=22265 0 +0 120765937 +0 91980 +cfn=(3494) +calls=365 0 +0 622325 +0 2920 + +fn=(3492) +0 1460925 +cfn=(3268) +calls=58437 0 +0 107025564 +0 350622 +cfn=(3268) +calls=58437 0 +0 107082789 +0 1110303 +cob=(7) +cfi=(53) +cfn=(880) +calls=58437 0 +0 9590824 +0 3798267 +cob=(7) +cfi=(53) +cfn=(880) +calls=41721 0 +0 7625091 +0 2328777 +cfn=(3472) +calls=125163 0 +0 2103560496 +0 2028303 +cfn=(3478) +calls=58437 0 +0 81470208 +0 701244 + +fn=(3500) +0 6484 +cob=(7) +cfi=(53) +cfn=(2812) +calls=296 0 +0 4733 +0 2440 +cfn=(3504) +calls=192 0 +0 60596 +0 3174 +cfn=(3502) +calls=4 0 +0 1203 +0 300 +cfn=(3504) +calls=22 0 +0 7311 +0 2686 +cfn=(3504) +calls=147 0 +0 49960 +0 224 + +fn=(3514) +0 1090985 +cfn=(3516) +calls=22265 0 +0 1098776209 +0 222650 +cfn=(3516) +calls=44530 0 +0 2181425980 +0 601155 + +fn=(3552) +0 58 + +fn=(3580) +0 187026 +cob=(7) +cfi=(53) +cfn=(2414) +calls=8906 0 +0 227103 +0 26718 +cob=(7) +cfi=(53) +cfn=(2414) +calls=8906 0 +0 222650 +0 93513 +cob=(7) +cfi=(53) +cfn=(2414) +calls=8906 0 +0 298351 +0 80154 + +fn=(3586) +0 1420507 +cfn=(3588) +calls=129137 0 +0 440343323 +0 1937055 +cfn=(3592) +calls=129137 0 +0 2970151 +0 1807918 +cfn=(3592) +calls=258274 0 +0 5940302 +0 33188209 + +fn=(3608) +0 39528 +cfn=(3274) +calls=3294 0 +0 2628612 +0 29646 +cfn=(3274) +calls=9882 0 +0 7885836 +0 49410 + +ob=(13) /usr/lib/valgrind/callgrind-amd64-linux +fl=(91) /build/buildd/valgrind-3.6.0~svn20100212/coregrind/m_trampoline.S +fn=(1274) vgPlain_amd64_linux_REDIR_FOR_vtime +165 2 ++1 2 ++1 2 + +fn=(2782) vgPlain_amd64_linux_REDIR_FOR_vgettimeofday +155 1 ++1 1 ++1 1 + +ob=(12) +fl=(84) +fn=(3608) +0 13176 +cob=(7) +cfi=(53) +cfn=(1142) +calls=3294 0 +0 349164 + +ob=(9) +fl=(58) +fn=(2494) +0 36 +cob=(4) +cfi=(71) +cfn=(1148) +calls=6 3692 +0 576 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1642 +0 18 +cob=(4) +cfi=(71) +cfn=(1148) +calls=6 3692 +0 468 + +fn=(2902) gsl_vector_subvector +0 17385 + +fn=(2926) gsl_matrix_submatrix +0 8052 + +fn=(2598) +0 24 + +fn=(2898) +0 20069 +cfn=(2900) gsl_matrix_row +calls=549 0 +0 9333 +0 2196 +cfn=(2900) +calls=549 0 +0 9333 +0 2928 +cfn=(2902) +calls=366 0 +0 6954 +0 1830 +cfn=(2902) +calls=366 0 +0 6954 +0 1464 +cfn=(2904) gsl_blas_ddot +calls=366 0 +0 18878 +0 1098 +cfn=(2900) +calls=183 0 +0 3111 +0 915 +cfn=(2902) +calls=183 0 +0 3477 +0 366 +cfn=(2912) gsl_blas_dnrm2 +calls=183 0 +0 14762 +0 14335 + +fn=(2900) +0 21777 + +fn=(2930) gsl_blas_dtrmv +0 5124 +cob=(8) +cfi=(57) +cfn=(2936) +calls=244 0 +0 37210 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 872 +0 488 + +fn=(428) +0 6 + +fn=(2604) +0 6 +cob=(4) +cfi=(71) +cfn=(1148) +calls=1 3692 +0 78 +0 3 +cob=(4) +cfi=(71) +cfn=(1148) +calls=1 3692 +0 78 + +fn=(2886) +0 2379 +cob=(8) +cfi=(57) +cfn=(2892) +calls=61 0 +0 1269593 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 838 +0 305 + +fn=(2904) +0 15372 +cob=(8) +cfi=(57) +cfn=(2910) +calls=1281 0 +0 47580 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 822 +0 5124 + +fn=(2964) +0 1342 +cob=(8) +cfi=(57) +cfn=(2970) +calls=61 0 +0 256444 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 846 +0 488 + +fn=(422) +0 6 + +fn=(434) +0 11 + +fn=(2592) +0 8 +cob=(4) +cfi=(71) +cfn=(886) +calls=1 3615 +0 95 +0 5 +cob=(4) +cfi=(71) +cfn=(886) +calls=1 3615 +0 95 +0 9 + +fn=(2928) gsl_matrix_subcolumn +0 40687 + +fn=(1868) +0 1129304 +cob=(4) +cfi=(71) +cfn=(886) +calls=141163 3615 +0 13467749 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1742 +0 705815 +cob=(4) +cfi=(71) +cfn=(886) +calls=141163 3615 +0 36369870 +0 1270467 + +fn=(2912) +0 732 +cob=(8) +cfi=(57) +cfn=(2918) +calls=183 0 +0 13176 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 854 + +fn=(2924) +0 8174 +cfn=(2926) +calls=244 0 +0 8052 +0 4880 +cfn=(2928) +calls=244 0 +0 5612 +0 3904 +cfn=(2930) +calls=244 0 +0 43694 +0 976 +cfn=(2938) gsl_blas_dscal +calls=244 0 +0 8288 +0 2013 +cfn=(2928) +calls=61 0 +0 1403 +0 1830 +cfn=(2928) +calls=183 0 +0 4209 +0 2196 +cfn=(2928) +calls=366 0 +0 8418 +0 10370 +cfn=(2928) +calls=610 0 +0 14030 +0 8540 +cfn=(2904) +calls=610 0 +0 31720 +0 6954 +cfn=(2928) +calls=244 0 +0 5612 +0 3416 +cfn=(2904) +calls=244 0 +0 15616 +0 3294 +cfn=(2928) +calls=61 0 +0 1403 +0 854 +cfn=(2904) +calls=61 0 +0 2684 +0 8174 + +fn=(2938) +0 976 +cob=(8) +cfi=(57) +cfn=(2944) +calls=244 0 +0 6466 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 846 + +fn=(2478) +0 48 +cob=(4) +cfi=(71) +cfn=(886) +calls=6 3615 +0 586 +0 30 +cob=(4) +cfi=(71) +cfn=(886) +calls=6 3615 +0 1270 +0 54 + +fn=(2626) +0 846246 +cob=(4) +cfi=(71) +cfn=(1148) +calls=141041 3692 +0 16935027 +0 423123 +cob=(4) +cfi=(71) +cfn=(1148) +calls=141041 3692 +0 11001198 + +fn=(2950) +0 1891 +cob=(8) +cfi=(57) +cfn=(2956) +calls=61 0 +0 1614365 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 872 +0 671 + +fn=(3826) +0 10 +cob=(4) +cfi=(153) +cfn=(3726) +calls=1 31 +0 430 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1810 +0 13 + +ob=(6) +fl=(134) +fn=(3016) +44 12 ++1 2 +-1 4 ++1 6 ++1 4 ++1 4 ++6 6 ++1 8 ++26 2 + +fl=(137) +fn=(3376) +90 300 ++11 120 ++1 120 ++1 120 ++1 120 ++3 120 ++1 3 ++2 3 ++1 3 +-3 3 ++2 36 ++3 3 +-2 3 ++2 21 +785 3 +339 354 +116 114 ++1 27 ++6 9 +-5 9 +-1 9 ++3 18 +-3 9 ++4 18 +-4 9 ++1 9 +-1 9 ++5 9 +-4 9 ++5 18 ++1 18 +-5 9 +-1 9 ++6 9 +-5 9 ++1 45 ++1 9 +-1 9 ++1 54 ++6 90 ++3 9 +-3 9 ++1 18 ++2 81 ++4 144 ++2 110 ++1 66 ++5 12 ++1 12 +-1 36 ++1 12 +-1 12 ++1 48 ++2 12 ++3 12 +-2 12 ++7 12 +-8 12 ++1 24 ++5 24 ++2 24 +-7 24 ++5 24 ++2 12 +-7 12 ++7 48 +-7 24 ++7 12 +-7 12 ++7 144 ++3 12 +-3 12 ++1 24 ++2 72 +-11 10 ++3 10 +-2 10 ++7 10 +-8 10 ++1 20 ++5 20 ++2 20 +-7 20 ++5 20 ++2 10 +-7 10 ++7 40 +-7 20 ++7 10 +-7 10 ++7 120 ++3 10 +-3 10 ++1 20 ++2 140 +827 3 +339 1 +-78 1 ++78 5 +160 52 ++1 52 ++3 26 +-3 26 ++3 26 ++2 26 +-5 26 ++1 26 ++1 52 +-1 26 ++3 26 +-1 26 +-2 26 ++4 26 +-2 130 ++3 26 ++1 26 +-1 26 ++1 26 +-1 26 ++1 26 ++1 78 +-1 26 ++1 78 ++2 104 ++3 18 ++1 18 +-1 18 ++1 93 ++1 39 ++2 54 ++2 3 +-2 3 ++1 6 ++1 6 ++1 8 ++1 18 +694 4 +316 6 +138 20 ++1 10 +-1 20 ++1 10 +-1 10 ++1 30 +659 8 ++1 6 ++1 4 ++1 1 ++1 1 +-1 2 ++1 1 +-1 1 ++1 2 ++8 1 ++3 1 ++1 1 ++4 1 +-8 1 ++8 1 +-4 1 ++2 1 ++2 1 ++2 1 +-4 1 ++6 1 +-2 1 +-4 1 ++2 1 ++4 6 +-2 1 ++2 17 ++1 1 +-1 3 ++1 2 +-1 2 ++2 1 +-2 1 ++2 1 ++1 1 +-3 1 +-12 1 ++3 1 ++1 1 ++4 1 +-8 1 ++8 1 +-4 1 ++2 1 ++2 1 ++2 1 +-4 1 ++6 1 +-2 1 +-4 1 ++2 1 ++4 6 +-2 1 ++2 17 ++1 1 +-1 3 ++1 2 +-1 2 ++2 1 +-2 1 ++2 1 ++1 1 +-3 1 ++2 1 ++1 1 ++2 6 +-3 1 ++1 1 ++2 8 +209 16 ++1 20 ++1 4 ++6 4 +-5 4 +-1 4 ++10 4 +-9 4 +-1 4 ++8 4 +-8 4 ++1 4 ++2 4 ++7 4 +-4 4 ++4 4 +-4 4 +-5 4 ++5 4 ++4 12 +-9 8 ++7 4 +-7 4 ++9 4 +-8 4 ++6 4 +-6 4 ++6 8 ++2 4 +-2 4 ++2 4 +-2 8 ++2 8 +-2 4 ++2 40 ++1 4 +-1 4 ++1 4 ++1 8 ++1 8 +-13 4 ++6 4 +-5 4 +-1 4 ++10 4 +-9 4 +-1 4 ++8 4 +-8 4 ++1 4 ++2 4 ++7 4 +-4 4 ++4 4 +-4 4 +-5 4 ++5 4 ++4 12 +-9 8 ++7 4 +-7 4 ++9 4 +-8 4 ++6 4 +-6 4 ++6 8 ++2 4 +-2 4 ++2 4 +-2 8 ++2 8 +-2 4 ++2 40 ++1 4 +-1 4 ++1 4 ++1 8 ++1 16 ++1 91 +667 1 ++1 1 +-1 2 ++1 1 +-1 1 ++1 3 ++1 2 +224 12 +-39 72 ++4 9 ++6 9 +-3 9 +-3 9 ++10 9 +-10 9 ++1 9 +-1 9 ++5 9 ++1 18 ++4 9 +-9 9 ++2 9 ++7 45 +-8 9 ++1 9 ++7 9 +-8 9 ++1 18 ++7 9 +-7 9 ++7 9 +-7 18 ++7 18 +-7 9 ++7 18 +-7 9 ++7 63 ++1 9 +-1 27 ++1 9 ++1 18 ++1 18 +-13 6 ++6 6 +-3 6 +-3 6 ++10 6 +-10 6 ++1 6 +-1 6 ++5 6 ++1 12 ++4 6 +-9 6 ++2 6 ++7 30 +-8 6 ++1 6 ++7 6 +-8 6 ++1 12 ++7 6 +-7 6 ++7 6 +-7 12 ++7 12 +-7 6 ++7 12 +-7 6 ++7 42 ++1 6 +-1 18 ++1 6 ++1 12 ++1 26 ++1 117 +800 2 ++1 1 +-1 2 ++4 1 ++3 1 ++1 1 ++5 1 +-9 1 ++9 1 +-5 1 ++2 1 ++3 1 ++2 1 +-5 1 ++7 1 +-2 1 +-5 1 ++3 1 ++4 6 +-2 1 ++2 17 ++1 1 +-1 5 ++1 2 +-1 1 ++2 1 ++1 1 +-3 1 ++2 2 ++1 1 ++1 2 ++1 8 ++1 4 ++4 2 +202 24 +-14 36 +-7 6 + +fn=(3366) +348 240 ++5 120 ++2 180 ++2 120 ++2 120 ++1 36 ++1 12 ++8 12 +-8 12 ++3 12 +-3 12 ++3 12 ++7 36 +-10 12 ++1 12 +-1 12 ++5 12 +-4 12 ++9 12 +-2 12 ++2 12 +-2 24 ++2 24 +-8 12 ++1 12 ++7 12 +-8 12 ++1 60 ++7 12 +-7 12 ++7 144 ++1 12 +-1 12 ++1 12 ++2 84 ++4 96 ++1 132 ++1 66 ++1 22 +-1 22 ++1 22 ++1 44 +-1 22 ++2 47 ++1 39 ++2 3 +-2 3 ++1 3 +-1 3 ++1 3 ++1 6 ++1 8 ++47 16 +587 240 +360 24 ++53 52 ++1 52 ++3 26 +-3 26 ++3 26 +-3 26 ++1 26 ++1 26 ++1 26 +-1 26 +-1 26 ++3 26 +-1 26 +-2 26 ++2 26 ++2 26 +-2 78 ++3 52 ++1 26 +-1 26 ++1 26 ++1 78 +-1 26 ++1 26 ++2 104 ++35 106 ++1 14 ++6 14 +-5 14 +-1 14 ++8 14 ++2 28 +-9 14 +-1 28 ++1 14 ++2 14 ++7 14 +-4 14 ++4 14 +-4 14 +-5 14 ++5 14 ++4 42 +-9 28 ++7 14 +-7 14 ++9 14 +-8 14 ++6 14 +-6 14 ++6 70 ++2 14 +-2 14 ++2 168 ++1 14 +-1 14 ++1 14 ++1 28 ++1 28 +-13 4 ++6 4 +-5 4 +-1 4 ++8 4 ++2 8 +-9 4 +-1 8 ++1 4 ++2 4 ++7 4 +-4 4 ++4 4 +-4 4 +-5 4 ++5 4 ++4 12 +-9 8 ++7 4 +-7 4 ++9 4 +-8 4 ++6 4 +-6 4 ++6 20 ++2 4 +-2 4 ++2 48 ++1 4 +-1 4 ++1 4 ++1 8 ++1 26 ++1 72 +1125 42 +391 57 ++1 50 ++1 10 ++6 10 +-6 30 ++1 10 +-1 10 ++3 10 ++2 10 +-4 10 ++5 20 ++4 20 +-8 10 ++1 10 ++7 20 +-8 10 ++8 30 +-7 40 ++7 20 +-7 10 ++7 10 +-7 10 ++7 80 ++1 10 +-1 30 ++2 10 +-1 10 ++1 20 ++1 20 +-13 9 ++6 9 +-6 27 ++1 9 +-1 9 ++3 9 ++2 9 +-4 9 ++5 18 ++4 18 +-8 9 ++1 9 ++7 18 +-8 9 ++8 27 +-7 36 ++7 18 +-7 9 ++7 9 +-7 9 ++7 72 ++1 9 +-1 27 ++2 9 +-1 9 ++1 18 ++1 38 ++47 104 ++75 52 ++21 84 +391 36 +-4 6 ++35 78 +-16 27 ++21 8 ++1 8 +-1 8 ++1 8 ++1 17 ++1 13 ++2 1 +-2 2 ++1 2 ++1 2 ++1 5 ++4 26 ++2 4 ++6 4 +-6 12 ++1 4 +-1 4 ++3 4 ++2 4 +-4 4 ++5 8 ++4 8 +-8 4 ++1 4 ++7 8 +-8 4 ++8 12 +-7 16 ++7 8 +-7 4 ++7 4 +-7 4 ++7 32 ++1 4 +-1 12 ++2 4 +-1 4 ++1 8 ++1 8 +-13 3 ++6 3 +-6 9 ++1 3 +-1 3 ++3 3 ++2 3 +-4 3 ++5 6 ++4 6 +-8 3 ++1 3 ++7 6 +-8 3 ++8 9 +-7 12 ++7 6 +-7 3 ++7 3 +-7 3 ++7 24 ++1 3 +-1 9 ++2 3 +-1 3 ++1 6 ++1 15 ++21 27 +-21 12 +-14 18 + +fl=(130) /build/buildd/eglibc-2.11.1/math/../sysdeps/ieee754/dbl-64/s_finite.c +fn=(2880) finite +33 38400 ++2 6400 + +fl=(52) +fn=(246) +0 6 + +fn=(258) +0 11 + +fn=(3886) +0 10 +cob=(4) +cfi=(153) +cfn=(3726) +calls=1 31 +0 430 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1810 +0 13 + +fn=(252) +0 6 + +fl=(132) /build/buildd/eglibc-2.11.1/math/../sysdeps/ieee754/dbl-64/e_pow.c +fn=(2986) __ieee754_pow +58 600 ++17 300 +-17 2100 ++14 300 ++1 300 ++1 300 ++63 300 +-71 300 ++2 300 +-1 300 ++1 600 ++10 540 ++3 540 +-3 360 +-9 900 ++2 900 ++1 1200 ++1 900 ++1 720 ++1 1140 ++80 1800 ++48 360 +78 180 +203 180 ++4 180 +-3 360 ++3 360 ++3 720 ++5 1260 ++1 180 ++1 540 ++1 360 ++37 180 ++1 180 +-2 180 ++1 180 ++1 360 ++1 180 +-2 180 ++5 180 +-3 180 +-1 180 +-1 180 ++2 180 ++3 180 ++2 180 +-5 180 ++1 180 ++2 180 ++2 180 +-2 180 ++2 180 +-4 180 ++2 180 ++1 180 ++1 180 +-1 180 ++1 3240 ++1 180 +-1 180 ++1 180 ++2 540 +83 180 ++10 360 +-10 180 ++3 180 +-1 180 +-2 180 ++3 180 +-2 540 ++3 360 +-2 180 ++2 180 ++2 180 ++1 180 +-1 180 ++1 720 ++1 360 ++2 360 ++1 2520 +cfi=(129) /build/buildd/eglibc-2.11.1/math/../sysdeps/ieee754/dbl-64/e_exp.c +cfn=(2990) __exp1 +calls=180 +70 +* 15840 ++1 1800 +-22 240 +211 1620 + +fl=(129) +fn=(2990) +164 540 ++1 360 ++1 360 ++2 540 ++1 180 ++19 180 ++6 180 +-25 360 ++25 180 +-24 180 ++2 180 ++5 180 +-5 180 +-2 360 ++4 180 ++1 180 ++5 180 +-5 180 ++2 360 ++2 180 ++1 180 +-1 180 ++6 180 ++1 180 +-6 180 ++1 180 ++4 180 ++1 180 +-1 180 ++3 180 ++1 180 +-4 180 ++4 360 +-9 180 ++9 180 +-1 180 ++1 180 +-8 1080 ++7 720 ++1 180 +-1 180 ++1 900 ++2 720 ++1 180 +-1 180 ++3 180 +-2 180 ++2 1260 +-11 900 ++11 360 ++58 360 + +fn=(2878) __ieee754_exp +57 12200 ++1 12200 ++1 12200 ++2 18300 ++2 6000 ++19 6000 +-19 12000 ++6 6000 +-1 6000 +-5 6000 ++1 6000 ++2 6000 ++5 6000 +-5 6000 +-2 12000 ++4 6000 ++3 6000 +-2 12000 ++2 6000 +-2 6000 ++4 6000 ++1 6000 +-1 6000 ++2 6000 ++4 6000 ++1 6000 +-6 6000 ++5 6000 ++1 6000 +-1 6000 ++3 6000 ++1 6000 +-4 6000 ++4 18000 +-9 6000 ++8 24000 +-7 12000 ++8 6000 +-8 18000 ++8 6000 +-8 6000 ++7 6000 ++1 6000 +-1 6000 ++1 24000 ++2 30000 ++1 12000 ++2 36000 ++36 6000 +-1 30000 ++1 6000 ++23 12000 +-55 300 ++55 200 + +fl=(128) +fn=(2876) +38 12200 ++5 12200 +cfi=(129) +cfn=(2878) +calls=6100 +14 +* 517400 ++1 6100 +-1 6100 ++1 18300 ++1 18300 +cfi=(130) +cfn=(2880) +calls=6100 -12 +* 42700 +* 24400 ++1 12200 ++2 12200 ++5 18300 + +fl=(138) +fn=(3388) +44 1494720 ++1 249120 +-1 498240 ++1 747360 ++1 498240 ++1 498240 ++7 508746 ++1 339164 ++1 678328 ++1 339164 ++1 678328 ++21 1017492 ++2 169582 +-2 477228 ++2 79538 +-33 318152 ++1 318152 ++1 126855 ++5 4 ++2 5965 + +fl=(133) /build/buildd/eglibc-2.11.1/math/../sysdeps/ieee754/dbl-64/s_isnan.c +fn=(2988) isnan +33 1800 ++2 600 +-2 600 ++2 5400 ++3 600 + +fl=(131) +fn=(2984) +29 900 ++5 300 +cfi=(132) +cfn=(2986) +calls=300 +24 +* 55080 ++1 300 +-1 300 ++1 1200 +cfi=(133) +cfn=(2988) +calls=300 -2 +* 4500 +* 600 ++1 600 +cfi=(133) +cfn=(2988) +calls=300 -3 +* 4500 +* 600 ++29 900 +-23 1200 ++11 900 +cfi=(130) +cfn=(2880) +calls=300 -20 +* 2100 +* 900 ++8 900 + +fl=(127) +fn=(2870) +34 6100 ++1 6100 ++1 6100 ++1 6100 ++1 6100 ++1 6100 ++1 6100 ++1 6100 ++3 6100 + +fl=(70) +fn=(868) +39 1 ++1 4 ++1 2 ++1 2 ++6 1 ++1 1 +-1 1 ++1 2 ++12 1 + +ob=(4) +fl=(118) /build/buildd/eglibc-2.11.1/stdlib/../sysdeps/ieee754/dbl-64/mpn2dbl.c +fn=(1842) __mpn_construct_double +40 245 +-6 980 ++6 490 ++1 1470 ++7 245 + +fl=(86) /build/buildd/eglibc-2.11.1/setjmp/../sysdeps/x86_64/bsd-_setjmp.S +fn=(1224) _setjmp +34 1 ++2 1 +cfi=(87) /build/buildd/eglibc-2.11.1/setjmp/../sysdeps/x86_64/setjmp.S +cfn=(1226) __sigsetjmp +calls=1 -10 +* 27 + +fl=(148) /build/buildd/eglibc-2.11.1/stdlib/../sysdeps/x86_64/rshift.S +fn=(3658) __mpn_rshift +25 2 ++1 2 ++1 2 ++1 2 ++1 2 ++1 2 ++1 2 ++1 2 ++1 2 ++1 2 ++1 2 ++1 2 ++1 4 ++3 2 ++1 2 ++1 2 ++1 2 ++1 2 ++1 2 ++1 2 ++12 2 ++1 2 ++1 2 ++1 2 + +fl=(46) +fn=(208) __libc_global_ctors +19 1 ++7 1 +-7 5 ++1 1 +cfi=(47) /build/buildd/eglibc-2.11.1/string/../sysdeps/x86_64/cacheinfo.c +cfn=(210) init_cacheinfo +calls=1 487 +* 6258 +-1 1 ++1 1 +cfi=(50) /build/buildd/eglibc-2.11.1/elf/dl-altinit.c +cfn=(222) dlinit_alt +calls=1 +13 +* 4 +-1 6 ++10 2 + +fn=(3924) +19 1 ++17 1 +-17 2 ++20 2 + +fl=(142) /build/buildd/eglibc-2.11.1/string/../sysdeps/x86_64/strchrnul.S +fn=(3646) strchrnul +27 2 ++1 2 ++1 2 ++1 2 ++1 2 ++1 2 ++1 2 ++1 2 ++1 2 ++1 2 ++1 2 ++1 2 ++1 2 ++1 2 ++1 2 ++1 2 ++1 2 ++1 2 ++1 2 ++1 2 ++12 2 ++1 2 ++1 2 + +fl=(50) +fn=(222) +33 3 ++1 1 + +fl=(85) +fn=(1048) +96 7 ++10 1 +-10 3 ++10 3 ++52 1 +-52 1 ++52 1 ++1 4 +cfi=(56) +cfn=(362) +calls=1 57 +* 62 ++22 4 ++3 2 ++1 5 +cob=(12) +cfi=(84) +cfn=(1050) +calls=1 0 +* 217056 ++4 4 ++15 2 ++9 2 +cfi=(86) +cfn=(1224) +calls=1 34 +* 29 ++1 2 ++5 2 ++1 2 ++3 2 ++3 5 +cob=(12) +cfi=(84) +cfn=(1230) +calls=1 0 +* 1323498631965 ++32 2 +cfi=(151) /build/buildd/eglibc-2.11.1/stdlib/exit.c +cfn=(3678) exit +calls=1 49 +* 94492 +106 2 + +fl=(105) +fn=(1482) +29 3 ++3 3 +-3 6 ++3 42 ++1 9 +fi=(104) /build/buildd/eglibc-2.11.1/libio/libioP.h +984 6 ++1 33 +fe=(105) +36 9 +-3 9 +cfi=(100) /build/buildd/eglibc-2.11.1/libio/genops.c +cfn=(1484) __overflow +calls=3 246 +* 417 +* 6 + +fl=(61) +fn=(538) +46 10 ++12 1 +-12 1 ++12 1 ++8 2 ++3 4 ++6 4 ++1 3 +281 9 +63 2 ++12 3 +280 2 + +fl=(72) /build/buildd/eglibc-2.11.1/malloc/hooks.c +fn=(888) malloc_hook_ini +36 1 +-1 2 ++1 1 ++1 1 +cfi=(73) /build/buildd/eglibc-2.11.1/malloc/arena.c +cfn=(890) ptmalloc_init +calls=1 467 +* 59667 ++1 1 ++1 1 +-1 1 +cfi=(71) +cfn=(887) malloc'2 +calls=1 3615 +* 1059 + +fl=(89) +fn=(1248) +25 1545 ++1 1545 ++1 1545 ++1 1545 ++1 1545 ++1 1545 ++1 1545 ++1 1545 ++1 1545 ++1 1545 ++1 1545 ++1 1545 ++1 1545 ++1 1545 ++1 1545 ++1 1545 ++1 1545 ++1 1545 ++1 1184 ++1 1184 ++2 882 ++1 882 ++1 882 ++1 882 ++1 882 ++1 882 ++1 525 ++1 525 ++2 971 ++1 971 ++2 718 ++1 718 ++1 718 ++1 718 ++1 718 ++1 718 ++1 574 + +fl=(62) +fn=(610) +32 4 ++2 8 +-2 4 ++2 4 ++3 8 ++29 4 +-28 4 ++28 8 ++1 12 ++2 12 ++4 12 ++1 4 + +fl=(115) /build/buildd/eglibc-2.11.1/stdlib/mul.c +fn=(1832) __mpn_mul +58 4428 ++6 369 +-6 369 ++6 369 ++12 1107 ++5 369 ++1 738 ++9 738 +cfi=(116) /build/buildd/eglibc-2.11.1/stdlib/../sysdeps/x86_64/mul_1.S +cfn=(1834) __mpn_mul_1 +calls=369 -65 +* 5559 ++2 369 ++5 369 +-5 369 ++5 369 ++54 2952 + +fl=(63) +fn=(616) +33 896 ++9 256 ++5 128 ++1 128 +-1 128 ++38 896 + +fl=(154) /build/buildd/eglibc-2.11.1/nptl/../nptl/sysdeps/unix/sysv/linux/unregister-atfork.c +fn=(3728) __unregister_atfork +29 8 ++8 8 +-8 16 ++11 16 ++1 32 ++5 8 +-6 24 ++82 16 + +fl=(92) +fn=(1280) +211 2 ++1 6 ++1 3 +cfi=(93) /build/buildd/eglibc-2.11.1/stdlib/random_r.c +cfn=(1282) srandom_r +calls=1 -48 +* 10209 ++1 4 ++1 2 + +fl=(98) +fn=(1408) +37 4 ++1 4 +-1 4 ++1 4 +-1 28 ++4 8 ++2 60 ++1 18 +fi=(104) +984 8 ++1 24 +fe=(98) +51 8 ++4 28 +-11 1 ++1 5 +cfi=(99) /build/buildd/eglibc-2.11.1/libio/fileops.c +cfn=(1410) _IO_file_xsputn@@GLIBC_2.2.5 +calls=1 1296 +* 2273 +* 15 +cfi=(99) +cfn=(1410) +calls=3 1296 +* 476 +* 16 +fi=(104) +985 24 +fe=(98) + +fl=(47) +fn=(210) +487 4 ++13 3 +673 5 +501 1 +cfi=(48) /build/buildd/eglibc-2.11.1/csu/../sysdeps/x86_64/multiarch/init-arch.c +cfn=(212) __init_cpu_features +calls=1 49 +* 44 +* 1 ++6 2 ++2 3 +cfn=(214) handle_intel +calls=1 256 +* 2197 ++4 2 +-4 1 ++4 1 +cfn=(214) +calls=1 256 +* 2211 ++2 1 +-2 1 ++2 2 ++12 1 ++17 1 +-18 1 ++1 1 ++10 3 ++7 1 +-7 1 ++7 2 ++7 6 ++6 2 +-6 8 ++6 4 ++3 15 ++2 1 ++6 6 ++7 1 +-7 1 ++11 2 ++27 2 ++56 2 ++2 1 ++1 1 +-1 2 ++4 2 ++2 1 ++1 1 +-1 3 +-63 7 +-88 3 +cfn=(214) +calls=1 256 +* 1694 +* 3 + +fn=(216) intel_check_word +163 132 ++1 24 ++8 12 +-2 72 ++16 66 ++9 2 +-1 1 ++28 5 +-1 1 ++1 1 +cfi=(49) /build/buildd/eglibc-2.11.1/stdlib/bsearch.c +cfn=(218) bsearch +calls=1 27 +* 153 +* 145 +-1 29 ++1 29 +cfi=(49) +cfn=(218) +calls=29 27 +* 4845 ++2 60 ++2 28 ++14 10 ++6 28 +-74 56 ++2 30 ++2 60 +-4 10 ++79 80 +-10 4 +-13 2 ++2 4 ++2 2 ++19 16 + +fn=(220) intel_02_known_compare +152 784 ++3 378 ++1 196 + +fn=(214) +256 24 ++1 12 ++7 3 ++1 9 ++8 6 ++5 3 +-5 6 ++5 3 ++7 15 +cfn=(216) +calls=3 163 +* 2415 ++1 6 ++3 15 +cfn=(216) +calls=3 163 +* 1791 ++1 6 ++3 15 +cfn=(216) +calls=3 163 +* 69 ++1 6 ++3 15 +cfn=(216) +calls=3 163 +* 1632 ++1 6 +-31 2 ++13 3 ++1 3 +-1 6 ++22 7 ++5 24 + +fl=(77) /build/buildd/eglibc-2.11.1/malloc/morecore.c +fn=(906) __default_morecore +48 487 ++1 487 +cfi=(78) /build/buildd/eglibc-2.11.1/misc/sbrk.c +cfn=(908) sbrk +calls=487 -14 +* 23423 ++1 1461 ++3 974 + +fl=(100) +fn=(1930) _IO_default_finish +687 10 ++2 15 ++6 15 ++3 15 ++6 5 ++6 5 +-6 5 +cfn=(1916) _IO_un_link +calls=5 64 +* 50 + +fn=(1414) _IO_doallocbuf +419 1 ++1 1 +-1 1 ++1 1 ++6 2 +-4 2 ++1 3 +cfi=(101) /build/buildd/eglibc-2.11.1/libio/filedoalloc.c +cfn=(1416) _IO_file_doallocate +calls=1 88 +* 89 +* 2 + +fn=(1588) _IO_link_in +104 40 ++1 30 ++4 5 +-2 10 ++2 25 ++1 55 ++1 5 ++1 75 ++4 5 ++2 5 +-4 5 ++1 5 +-1 5 ++4 35 ++2 5 +-1 5 ++1 45 ++1 10 ++3 40 +-6 30 + +fn=(1916) +64 60 ++1 30 ++4 30 ++1 55 ++1 5 ++1 75 ++2 15 ++2 10 ++4 2 ++3 4 ++1 8 ++6 5 ++2 40 ++2 5 +-1 5 ++1 45 ++1 10 ++3 60 +-15 4 ++3 2 ++1 2 +-1 2 ++2 2 ++4 30 +-14 3 ++2 3 +-2 6 + +fn=(3926) _IO_cleanup +1007 1 ++3 1 +-3 4 ++3 1 +cfn=(3928) _IO_flush_all_lockp +calls=1 823 +* 82 +-59 1 ++59 1 +-59 2 ++11 2 +-9 21 ++9 13 ++7 5 ++10 5 +cfi=(99) +cfn=(3930) _IO_file_setbuf@@GLIBC_2.2.5 +calls=1 453 +* 78 ++2 2 ++6 3 +-36 9 ++71 7 +-51 1 ++4 1 +-4 1 ++2 1 ++2 1 +-2 1 ++3 1 +-2 1 ++2 3 ++6 12 + +fn=(1582) _IO_no_init +648 54 ++1 6 +cfn=(1584) _IO_old_init +calls=6 -13 +* 141 ++3 6 +-2 6 ++2 6 ++2 5 ++1 5 ++1 5 ++1 5 ++1 5 ++1 5 ++1 5 ++1 5 ++1 5 ++1 5 ++1 5 ++1 5 ++2 5 ++3 5 ++1 30 +-1 1 ++1 6 + +fn=(1584) +636 6 +-21 6 ++1 6 +-1 6 ++2 6 ++1 6 ++1 6 ++17 6 +-16 6 ++1 6 ++1 6 ++1 6 ++1 6 ++1 6 ++2 6 ++1 6 ++1 6 ++1 6 ++1 6 ++5 6 ++1 21 + +fn=(1920) _IO_unsave_markers +1117 10 ++20 10 ++1 5 + +fn=(3932) _IO_default_setbuf +562 5 ++1 1 +-1 2 ++1 1 +cfi=(99) +cfn=(1508) _IO_file_sync@@GLIBC_2.2.5 +calls=1 899 +* 13 +* 2 ++2 2 ++2 1 ++1 5 +cfn=(1424) _IO_setb +calls=1 404 +* 19 ++7 3 ++1 3 ++2 6 + +fn=(1428) _IO_default_xsputn +452 3 ++3 6 +-3 9 ++1 3 +-1 9 ++1 3 ++2 4 ++5 172 ++25 254 +cfi=(99) +cfn=(1412) _IO_file_overflow@@GLIBC_2.2.5 +calls=42 837 +* 1386 +* 126 ++2 42 ++1 42 ++1 2 ++1 18 + +fn=(3928) +823 8 ++6 6 ++1 2 ++5 1 +-1 1 ++2 2 +-2 1 ++2 3 ++33 2 ++4 9 +-37 8 ++6 2 +-4 2 ++4 5 +-4 1 ++4 2 ++14 3 +-2 3 ++2 3 ++7 6 +-21 12 + +fn=(1424) +404 32 ++1 8 +-1 8 ++1 18 ++4 8 +-2 8 ++1 8 ++1 8 ++3 7 ++1 32 +-3 2 + +fn=(1484) +246 9 ++2 9 +cfi=(99) +cfn=(1412) +calls=3 837 +* 399 + +fl=(69) +fn=(642) +26 572399506 ++1 572399506 ++1 572399506 ++1 572399506 ++1 572399506 ++1 572399506 ++1 572399506 ++1 572399506 ++1 572399506 ++1 572399506 ++1 572399506 ++1 572399506 ++2 10786 ++1 10786 ++1 10786 ++1 10786 ++1 10786 ++1 10786 ++2 572399506 ++1 572399506 ++1 572399506 ++1 572399506 + +fl=(93) +fn=(1282) +165 5 ++8 2 ++44 5 +-42 1 ++1 2 ++3 1 ++2 3 ++3 1 +-1 1 ++1 1 ++5 1 ++1 4 ++7 13 ++2 3 ++1 1 +-10 3 ++7 348 ++2 87 ++1 29 +-10 87 ++13 1 ++2 1 +-1 1 ++2 1 +-3 1 ++3 1 +-3 1 ++3 2 ++3 3 +cfn=(1284) random_r +calls=1 367 +* 26 +* 927 +cfn=(1284) +calls=309 367 +* 8024 +-3 622 + +fn=(1284) +367 1240 ++5 310 +-2 310 ++2 620 ++9 310 ++1 310 ++1 310 ++3 930 ++3 310 +-1 310 ++2 310 +-2 310 ++2 310 ++7 300 ++4 300 +-3 600 ++4 900 +-9 20 ++8 10 ++1 30 + +fl=(141) /build/buildd/eglibc-2.11.1/stdio-common/vfprintf.c +fn=(3644) vfprintf +210 10 ++35 1 +-35 1 ++35 2 +1288 3 ++4 5 ++11 2 ++11 1 +fi=(157) /build/buildd/eglibc-2.11.1/stdio-common/printf-parse.h +99 2 +fe=(141) +1314 5 +fi=(157) +99 1 +cfi=(142) +cfn=(3646) +calls=1 -72 +* 23 +fe=(141) +1329 1 +fi=(157) +99 1 +fe=(141) +1329 2 ++4 7 +cfi=(100) +cfn=(1428) +calls=1 452 +* 18 +* 2 +1996 2 ++1 3 +1288 2 +2000 8 +1333 4 ++4 1 +-4 1 ++4 2 +1808 1 +1337 4 +1808 1 +1948 1 +1337 4 +1948 1 +1337 1 +1948 1 ++3 1 +-3 3 ++3 1 ++61 2 +1383 18 +1951 1 +1383 15 +1951 1 +1383 1 +1632 2 ++8 1 +fi=(157) +99 3 +cfi=(142) +cfn=(3646) +calls=1 -72 +* 23 +fe=(141) +1644 1 +fi=(157) +99 1 +fe=(141) +1644 11 +cfi=(100) +cfn=(1428) +calls=1 452 +* 18 +* 12 ++2 2 +1526 1 ++1 3 ++43 14 +1383 1 +1546 5 ++67 50 +cfi=(143) /build/buildd/eglibc-2.11.1/stdio-common/printf_fp.c +cfn=(3648) __printf_fp +calls=1 163 +* 2262 +* 10 +-46 2 +-35 1 +-1 1 ++1 4 ++4 8 ++3 1 +-3 1 ++3 6 ++74 10 + +fl=(101) +fn=(1416) +88 4 ++15 6 +cfi=(99) +cfn=(1418) _IO_file_stat +calls=1 1233 +* 14 +* 2 ++2 4 ++12 3 ++3 6 +cfi=(103) +cfn=(1422) +calls=1 -38 +* 6 +* 3 ++1 4 +cfi=(100) +cfn=(1424) +calls=1 404 +* 18 +* 1 ++2 4 +-13 1 +-2 9 ++8 1 +-3 1 ++3 2 + +fl=(82) +fn=(986) +44 114 ++1 114 ++1 114 ++4 114 ++1 114 ++1 114 ++1 114 ++2 114 ++1 114 ++2 96 ++5 96 ++1 96 ++1 96 ++1 96 ++1 96 +315 1 ++1 1 ++1 1 ++1 1 +-2 66 ++1 66 ++1 66 ++20 1 ++1 1 ++1 1 +-1 6 ++1 6 ++23 2 ++1 2 ++1 2 ++1 2 ++23 2 ++1 2 ++1 2 ++1 2 +-2 2 ++1 2 ++1 2 ++24 3 ++1 3 ++24 2 ++1 2 ++1 2 ++22 1 ++1 1 ++1 1 ++1 1 ++1 1 +-3 3 ++1 3 ++1 3 ++1 3 +-2 3 ++1 3 ++1 3 ++22 2 ++1 2 ++1 2 ++1 2 ++1 2 ++1 2 +-4 1 ++1 1 ++1 1 ++1 1 ++1 1 +-3 1 ++1 1 ++1 1 ++1 1 ++8 18 ++1 18 ++1 18 ++1 18 ++1 18 ++1 18 ++1 18 ++5 18 ++1 18 ++1 18 ++1 18 ++1 18 ++80 18 ++1 18 +746 18 ++1 18 ++2 18 ++1 18 +891 18 ++1 18 ++1 18 +1008 18 ++1 18 ++1 36 ++4 18 ++1 18 ++1 18 ++1 18 ++1 18 ++1 18 ++1 18 ++1 18 ++1 18 ++1 18 ++2 18 ++1 18 +-12 126 ++1 126 ++1 126 ++1 126 ++1 126 ++1 126 ++1 126 ++1 126 ++1 126 ++1 126 ++2 126 ++1 126 ++1 18 ++5 18 ++1 18 ++1 18 ++1 18 ++1 18 + +fl=(66) /build/buildd/eglibc-2.11.1/elf/dl-profstub.c +fn=(626) _dl_mcount_wrapper_check +39 384 ++1 128 + +fl=(145) /build/buildd/eglibc-2.11.1/math/../sysdeps/ieee754/dbl-64/s_isinf.c +fn=(3652) isinf +23 4 ++1 1 ++1 1 +-1 3 ++1 6 ++2 1 + +fl=(124) +fn=(2234) +47 10076 ++1 916 + +fl=(87) +fn=(1226) +26 1 ++2 1 ++1 2 ++1 1 ++4 1 ++1 1 ++1 1 ++1 1 ++1 1 ++2 2 ++2 1 ++1 1 ++2 2 ++2 1 ++9 1 +cfi=(88) /build/buildd/eglibc-2.11.1/setjmp/sigjmp.c +cfn=(1228) __sigjmp_save +calls=1 -26 +* 9 + +fl=(119) /build/buildd/eglibc-2.11.1/stdlib/grouping.c +fn=(1862) __correctly_grouped_prefixmb +56 18 ++6 18 +-6 126 ++6 18 +202 144 + +fl=(122) +fn=(2150) +25 2 ++1 2 ++1 2 ++1 2 ++1 2 ++1 2 ++1 2 ++1 2 ++3 2 ++1 2 ++9 2 ++1 2 ++9 2 ++1 2 ++1 2 ++1 2 ++1 2 ++1 2 ++39 2 ++1 2 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++4 1 ++1 1 + +fl=(153) +fn=(3726) +31 16 ++18 8 +-18 8 ++18 8 +-18 40 ++4 32 ++4 1367 ++5 1416 ++2 59 ++1 59 ++2 236 +-5 118 ++7 59 ++5 59 +-2 118 ++2 118 +cob=(7) +cfi=(53) +cfn=(3876) +calls=1 -56 +* 4 +cob=(7) +cfi=(53) +cfn=(3874) +calls=1 -56 +* 4 +cob=(11) +cfi=(60) +cfn=(3784) +calls=1 -56 +* 190 +cob=(11) +cfi=(60) +cfn=(3782) +calls=1 -56 +* 4 +cob=(11) +cfi=(60) +cfn=(3780) +calls=1 -56 +* 4 +cob=(11) +cfi=(60) +cfn=(3778) +calls=1 -56 +* 4 +cob=(11) +cfi=(60) +cfn=(3776) +calls=1 -56 +* 4 +cob=(11) +cfi=(60) +cfn=(3774) +calls=1 -56 +* 4 +cob=(11) +cfi=(60) +cfn=(3772) +calls=1 -56 +* 4 +cob=(11) +cfi=(60) +cfn=(3770) +calls=1 -56 +* 4 +cob=(11) +cfi=(60) +cfn=(3768) +calls=1 -56 +* 4 +cob=(11) +cfi=(60) +cfn=(3762) +calls=1 -56 +* 2054 +cob=(7) +cfi=(53) +cfn=(1380) +calls=2 -56 +* 200 +cob=(11) +cfi=(60) +cfn=(3760) +calls=1 -56 +* 40 +cob=(12) +cfi=(84) +cfn=(1136) +calls=1 -56 +* 4 +cob=(11) +cfi=(60) +cfn=(3752) +calls=1 -56 +* 1920 +cob=(12) +cfi=(84) +cfn=(3750) +calls=1 -56 +* 4 +cob=(11) +cfi=(60) +cfn=(3748) +calls=1 -56 +* 4 +cob=(7) +cfi=(53) +cfn=(3680) +calls=40 -56 +* 3152 ++4 177 +-21 179 +-4 48 ++32 32 ++4 48 +-4 24 ++12 16 ++3 8 +-2 8 ++2 48 +-2 8 +cfi=(154) +cfn=(3728) +calls=8 -51 +* 128 + +fl=(81) +fn=(966) +56 572400102 ++2 572400102 ++2 572400102 ++3 572400039 ++1 572400039 ++2 529335853 ++1 529335853 ++2 529335853 ++1 529335853 ++5 529335853 ++1 529335853 +-1 43064186 ++1 43064186 ++2 43063295 ++1 43063295 ++2 43063295 ++1 86126590 ++5 43063295 ++1 43063295 +-1 529336744 ++1 529336744 ++2 10841 ++1 10841 ++2 10841 ++1 10841 ++5 10841 ++1 10841 +-1 572389198 ++1 572389198 ++2 572399161 ++1 572399161 ++2 572399161 ++1 572399161 ++5 572399161 ++1 572399161 +-1 878 ++1 1339 ++5 461 ++1 461 ++1 461 ++1 461 ++2 461 ++2 461 ++1 461 ++2 461 ++8 572400039 ++8 598 ++6 598 ++2 598 ++1 598 ++3 200 ++1 400 ++5 200 ++1 200 ++2 200 ++2 200 ++1 200 ++2 200 +-8 864 ++1 864 ++2 864 ++2 864 ++1 864 ++2 1064 ++9 200 ++1 200 +-1 398 ++1 398 ++3 598 ++1 598 ++1 598 ++5 460 ++2 460 ++1 460 ++1 460 ++1 460 ++2 460 ++1 460 ++1 460 ++1 460 ++2 460 ++1 460 ++2 460 ++2 23 ++2 23 ++1 23 ++1 23 ++1 23 ++2 23 ++1 23 ++1 23 ++1 23 ++2 23 ++1 23 ++2 40 ++5 17 ++6 17 ++1 17 +-7 581 ++6 581 ++1 581 ++2 63 + +fn=(3666) mempcpy +56 1 ++4 1 ++3 1 ++1 1 ++2 1 ++1 1 ++2 1 ++1 1 ++5 1 ++1 1 ++11 1 ++1 1 ++11 1 ++1 1 ++11 1 ++1 1 ++21 1 ++4 1 + +fl=(102) /build/buildd/eglibc-2.11.1/io/../sysdeps/unix/sysv/linux/wordsize-64/fxstat.c +fn=(1420) _fxstat +37 1 +-1 1 ++1 1 ++1 6 ++4 1 + +fl=(45) /build/buildd/eglibc-2.11.1/string/../sysdeps/x86_64/multiarch/../strrchr.S +fn=(206) __GI_strrchr +26 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++13 1 ++1 1 ++1 1 ++1 1 ++7 1 ++1 1 ++1 1 ++1 1 ++1 1 ++2 1 + +fl=(155) /build/buildd/eglibc-2.11.1/posix/../sysdeps/unix/sysv/linux/_exit.c +fn=(3934) _Exit +33 3 ++2 2 + +fl=(108) +fn=(1576) __fopen_internal +68 35 ++8 5 +-8 5 ++8 5 +cfi=(71) +cfn=(886) +calls=5 3615 +* 1049 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 -46 +* 1095 ++2 5 +-2 5 ++2 5 ++3 5 ++3 25 +-3 5 ++3 5 +cfi=(100) +cfn=(1582) +calls=5 648 +* 285 ++4 5 ++1 5 +-1 5 ++1 5 +cfi=(99) +cfn=(1586) _IO_file_init@@GLIBC_2.2.5 +calls=5 +59 +* 450 ++4 25 +cfi=(99) +cfn=(1590) _IO_file_fopen@@GLIBC_2.2.5 +calls=5 258 +* 587 +* 10 ++2 5 ++5 25 +-5 5 +cfn=(1600) __fopen_maybe_mmap +calls=5 -50 +* 20 + +fn=(1600) +45 5 +-2 5 ++2 5 ++15 5 + +fn=(1574) +107 10 +cfn=(1576) +calls=5 -39 +* 3681 + +fl=(117) /build/buildd/eglibc-2.11.1/stdlib/../sysdeps/x86_64/lshift.S +fn=(1838) __mpn_lshift +26 856 ++1 856 ++1 856 ++1 856 ++1 856 ++1 856 ++1 856 ++1 856 ++1 856 ++1 856 ++19 856 ++2 856 ++1 856 ++1 856 ++1 856 + +fl=(147) /build/buildd/eglibc-2.11.1/stdlib/cmp.c +fn=(3656) __mpn_cmp +43 12 ++2 4 ++1 4 ++1 8 ++8 20 + +fl=(44) /build/buildd/eglibc-2.11.1/misc/init-misc.c +fn=(204) __init_misc +31 3 ++1 1 +-1 1 ++1 4 ++2 3 +cfi=(45) +cfn=(206) +calls=1 -8 +* 33 ++1 2 ++4 3 ++2 4 +-5 3 + +fl=(73) +fn=(890) +467 5 ++8 3 ++1 1 +-66 1 ++2 1 ++1 1 ++1 1 ++1 1 +cfi=(74) /build/buildd/eglibc-2.11.1/misc/../sysdeps/unix/sysv/linux/getpagesize.c +cfn=(892) getpagesize +calls=1 29 +* 6 +519 1 +415 1 ++96 1 +-1 1 ++1 1 ++8 1 ++8 2 ++1 1 +-3 1 ++3 1 +-1 1 ++1 10 +cfi=(76) /build/buildd/eglibc-2.11.1/nptl/../nptl/sysdeps/unix/sysv/linux/register-atfork.c +cfn=(900) __linkin_atfork +calls=1 117 +* 9 ++11 2 ++2 6 +382 90 ++16 45 +-18 138 +622 2 ++5 2 ++1 2 ++2 1 ++1 6 +521 5 +cfi=(75) /build/buildd/eglibc-2.11.1/elf/dl-addr.c +cfn=(894) _dl_addr +calls=1 127 +* 59307 +-2 2 ++2 3 +382 5 + +fl=(135) +fn=(3026) +62 1 ++1 1 ++2 1 ++1 1 ++1 1 ++1 1 ++1 1 + +fn=(3028) +81 2 ++1 2 ++1 2 ++4 2 ++1 2 ++1 2 ++1 2 ++3 2 ++1 2 ++1 2 ++1 2 ++1 2 ++1 2 +1093 2 ++3 2 ++1 2 ++1 2 ++1 2 ++1 2 ++4 2 ++1 2 ++1 2 ++1 2 ++1 2 ++26 2 ++1 2 ++1 2 ++1 2 ++1 2 ++1 2 ++1 2 ++2 12 ++2 2 ++1 2 ++1 2 ++2 4 ++1 4 ++1 4 ++6 2 ++1 2 +1289 2 ++1 2 ++5 2 ++1 2 ++1 2 + +fl=(48) +fn=(212) +49 1 +-5 1 ++5 1 ++3 1 +-3 1 ++3 5 ++42 2 +-63 1 ++23 1 +-23 2 ++6 1 +-6 1 ++6 1 +-6 1 ++29 1 +-22 1 +-1 1 ++23 1 +-22 1 ++22 1 +-29 1 ++7 1 ++23 1 +-24 1 ++1 1 ++23 1 ++5 2 ++2 1 ++1 1 +-1 1 ++1 7 + +fl=(90) +fn=(1272) +32 2 ++3 2 ++1 2 +cob=(13) +cfi=(91) +cfn=(1274) +calls=2 165 +* 6 ++2 2 ++2 2 + +fl=(103) +fn=(3172) __lseek_nocancel +82 5 + +fn=(1422) +82 2140 ++1 428 + +fn=(2846) +82 8 ++1 2 + +fn=(3170) +82 2 +cfn=(3172) +calls=1 * +* 5 + +fl=(78) +fn=(908) +35 2435 ++8 3406 ++4 974 ++4 2916 ++3 486 +cfi=(79) /build/buildd/eglibc-2.11.1/misc/../sysdeps/unix/sysv/linux/x86_64/brk.c +cfn=(910) brk +calls=486 -25 +* 7532 +-3 1458 ++7 2922 +-14 2 +cfi=(79) +cfn=(910) +calls=1 -15 +* 12 +* 5 ++7 1275 + +fl=(88) +fn=(1228) +30 1 +-1 2 ++1 2 ++5 1 +-5 1 ++5 2 + +fl=(67) /build/buildd/eglibc-2.11.1/iconv/gconv_simple.c +fn=(628) __gconv_btwoc_ascii +52 512 ++4 128 + +fl=(97) +fn=(3196) +90 1 ++1 1 ++2 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++5 1 ++1 1 ++9 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++5 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 +1073 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++4 1 ++1 1 ++1 1 ++6 1 ++1 1 ++1 2 ++4 1 ++1 1 ++3 1 ++1 1 ++1 1 ++7 1 ++3 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++7 1 ++1 1 ++2 1 ++1 1 ++2 1 ++1 1 ++1 1 ++7 1 ++3 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 +2052 1 ++2 1 ++1 1 ++1 1 ++1 1 ++6 1 ++6 1 ++1 1 ++2 1 ++1 1 + +fn=(1320) __GI_strncmp +84 1 ++1 1 ++1 1 ++1 1 ++1 1 ++2 1 ++1 1 ++2 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 +2063 1 ++3 1 ++1 1 ++9 1 ++1 1 + +fl=(99) +fn=(1508) +899 10 ++5 10 +-5 10 ++5 30 ++2 10 ++1 20 ++17 20 ++4 20 + +fn=(1412) +837 230 ++1 46 +-1 46 ++1 92 ++7 272 ++35 92 ++3 90 ++3 45 ++1 45 +-1 90 ++1 180 ++5 45 ++1 225 +-45 2 ++12 3 ++9 2 ++4 1 ++4 1 +-1 1 +-5 1 ++1 1 ++4 1 +-3 1 ++1 1 ++3 1 +-3 2 ++3 3 ++1 4 ++3 1 ++12 3 +-12 1 ++12 1 +-12 1 +cfn=(1426) _IO_do_write@@GLIBC_2.2.5 +calls=1 501 +* 17 ++6 9 ++3 3 +-1 9 +cfn=(1426) +calls=3 501 +* 273 +* 6 +-39 2 +cfi=(100) +cfn=(1414) +calls=1 419 +* 102 ++1 6 + +fn=(1426) +501 24 ++1 4 +-1 8 ++1 8 ++2 24 ++11 9 ++7 12 ++8 15 +cfn=(1486) _IO_file_write@@GLIBC_2.2.5 +calls=3 1269 +* 126 ++1 3 +-1 3 ++1 6 ++5 3 +-2 3 ++2 3 +-2 9 ++1 6 ++1 3 +-34 3 ++34 3 +-34 3 ++29 6 ++5 6 + +fn=(1410) +1296 8 ++6 4 +-6 24 ++6 4 +-6 8 ++6 4 ++7 4 +-12 4 ++12 12 ++17 5 ++32 4 +cfn=(1412) +calls=1 837 +* 172 +* 2 ++7 2 ++1 6 ++2 3 ++11 2 ++1 4 +cfi=(100) +cfn=(1428) +calls=1 452 +* 2043 +* 2 +-50 9 ++4 6 +-42 3 ++56 3 +-56 12 ++58 3 +-58 3 ++58 3 ++2 9 ++2 9 ++28 8 ++1 32 +-72 6 ++1 6 +-1 3 ++1 6 ++3 9 ++2 12 +-2 50 ++2 66 +-25 15 ++57 12 +-1 6 ++1 88 +-1 47 +-18 6 + +fn=(1586) +148 15 ++5 5 +-1 5 +-4 5 ++4 5 ++3 5 +cfi=(100) +cfn=(1588) +calls=5 -51 +* 385 ++1 5 ++1 20 + +fn=(1486) +1269 3 ++2 3 +-2 18 ++2 3 +-2 3 ++2 6 ++11 3 +-11 6 ++2 6 ++3 12 +cfi=(106) +cfn=(1488) write +calls=3 82 +* 21 ++1 6 ++9 9 ++3 18 +-6 9 + +fn=(1590) +258 45 ++11 10 +423 35 +271 15 ++25 5 +-10 5 ++10 5 +-10 5 ++10 31 +-7 2 ++7 35 +-25 20 ++65 5 +228 10 ++4 15 +cfi=(106) +cfn=(1592) +calls=5 82 +* 35 +* 5 ++4 10 ++3 5 +-1 5 ++1 10 ++1 10 +-1 5 ++1 5 ++7 10 +cfi=(100) +cfn=(1588) +calls=5 104 +* 55 ++97 15 +cfi=(109) /build/buildd/eglibc-2.11.1/string/../string/strstr.c +cfn=(1596) __GI_strstr +calls=5 53 +* 135 +* 5 ++1 15 +fi=(123) /build/buildd/eglibc-2.11.1/libio/../iconv/gconv_charset.h +39 3 +fe=(99) +289 10 ++13 6 + +fn=(1928) _IO_file_finish@@GLIBC_2.2.5 +206 5 ++1 5 +-1 5 ++1 5 ++6 10 ++1 5 +-1 5 +cfi=(100) +cfn=(1930) +calls=5 687 +* 120 + +fn=(1418) +1233 1 ++2 3 +cfi=(102) +cfn=(1420) +calls=1 37 +* 10 + +fn=(3930) +453 2 ++1 1 +cfi=(100) +cfn=(3932) +calls=1 562 +* 63 +* 2 ++4 1 +-1 3 ++2 3 ++3 3 + +fn=(1918) _IO_file_close_it@@GLIBC_2.2.5 +163 5 ++2 5 +-2 10 ++2 5 +-2 5 ++2 5 ++3 25 ++6 10 +cfi=(100) +cfn=(1920) +calls=5 1117 +* 25 ++2 15 +cfn=(1922) _IO_file_close +calls=5 1260 +* 35 ++4 5 +-4 5 ++4 10 ++9 25 +cfi=(100) +cfn=(1424) +calls=5 404 +* 85 ++1 10 ++3 5 +-3 5 ++1 15 ++2 5 +cfi=(100) +cfn=(1916) +calls=5 64 +* 50 ++5 5 +-4 5 ++1 5 ++1 5 ++2 5 ++1 25 + +fn=(1922) +1260 10 +cfi=(106) +cfn=(1924) __close_nocancel +calls=5 82 +* 25 + +fl=(146) /build/buildd/eglibc-2.11.1/stdlib/../sysdeps/ieee754/dbl-64/dbl2mpn.c +fn=(3654) __mpn_extract_double +36 2 ++2 3 ++1 1 ++9 1 +-9 4 ++9 2 ++9 1 +-9 1 ++9 1 +-9 1 ++9 1 ++47 2 ++4 1 +-4 1 ++4 1 + +fl=(94) +fn=(1296) +37 7 +-1 7 ++1 7 ++1 42 ++4 5 +-4 10 + +fl=(71) +fn=(886) +3615 13981188852 ++5 4660396284 ++1 4660396284 ++3 4660396282 ++33 20971783269 ++3 6990594423 +cfn=(902) _int_malloc +calls=2330198141 4247 +* 112729870269 ++1 2330198141 +-1 2330198141 ++1 2330198141 ++20 9320792564 ++1 20971783264 ++3 16311386987 +-63 1 ++63 5 +-63 1 +cfi=(72) +cfn=(888) +calls=1 36 +* 60734 + +fn=(887) +3615 6 ++5 2 ++1 2 ++3 2 ++33 9 ++3 3 +cfn=(902) +calls=1 4247 +* 1012 ++1 1 +-1 1 ++1 1 ++20 4 ++1 9 ++3 7 + +fn=(904) malloc_consolidate +5074 109968 ++22 27492 ++1 13745 ++2 13745 ++17 13745 ++2 27490 ++5 13745 ++2 27490 +-2 123705 ++2 247410 ++2 110478 ++22 1825717 ++1 18962437 ++4 3909891 ++4 3909891 +-3 3909891 ++1 3909891 ++2 3909891 ++1 533144 ++1 533144 ++3 533144 ++1 533144 ++1 533144 +-2 533144 ++3 533144 +-3 533144 ++12 533144 +-3 533144 ++3 533144 +-12 3376747 ++1 3376747 ++1 3376747 +-2 3376747 ++3 3376747 +-3 3376747 ++12 3376747 +-3 3376747 ++3 3376748 +-3 1 ++3 1 +-41 3909892 +-3 3909892 ++3 7819784 ++1 3909892 ++1 7819784 ++2 7819784 ++1 1744626 ++2 1744626 +-1 1744626 ++2 18328377 ++3 7819784 ++1 7819782 ++6 4168348 ++26 646015 +-7 1 ++1 1 +-1 3 +2479 3 ++5 3 ++5 1 ++2 1 +-2 1 ++2 1 +5184 109968 +2480 1 +5070 2 +2480 3 +-2 2 ++2 378 +-2 253 ++10 3 +5142 216 ++8 1178 +-8 112 ++8 25 +-8 24 ++8 3 + +fn=(1148) +3692 4649346090 ++5 4649346090 ++1 4649346090 ++5 4649346090 ++6 2324673045 +-3 2324673045 ++3 4649346090 ++15 6974019132 ++12 13948038264 ++2 6974019132 +cfn=(1150) _int_free +calls=2324673044 4762 +* 109266899123 ++1 9298692176 ++2 6974019135 +-29 7 ++4 1 ++1 1 +-1 1 ++1 2 +3531 2 ++1 1 ++6 6 ++10 1 +-3 1 ++1 1 ++2 1 +cfi=(103) +cfn=(2846) +calls=1 82 +* 5 ++3 2 + +fn=(902) +4247 20971783440 ++30 18641585280 ++8 4660396320 ++1 6989820393 ++1 2329940131 ++12 2329940131 +-12 2329940131 ++14 4659880262 ++1 13923436458 ++7 2320572743 ++3 2320572743 +-3 2320572743 ++4 6961718229 +4750 20971783440 +4327 19250834 ++1 28844475 ++1 48074125 ++2 28844475 ++1 433742 ++3 216870 ++1 433740 ++6 216870 ++1 216870 ++2 216870 +-4 216870 ++4 433740 ++4 216870 +-1 216870 ++1 433740 ++19 92956 ++1 31776 ++1 39956 +cfn=(904) +calls=9989 5074 +* 154135595 +* 19978 +4736 9989 +4405 9989 +-16 9989 +4736 9989 +4501 19978 +4736 9989 +4405 9989 +4736 9989 +4389 29967 +4736 9398558 +4405 9398558 +-16 9398558 +4736 9398558 +4501 18797116 +4736 9398558 +4405 9398558 +4736 9398558 +4389 28195674 +4736 456 +4389 1811850 ++3 4275122 +-2 4275122 ++1 8550244 ++1 8550244 ++3 4275122 ++10 16362712 ++35 646656 +-5 646656 ++1 646656 ++4 646656 ++13 1206988 ++1 1169152 ++1 1753728 ++1 584576 ++45 2338304 ++4 584576 +-4 1169152 ++1 584576 ++1 584576 +-2 584576 ++7 584576 +-4 584576 ++1 584576 ++3 584576 +-7 75672 ++4 18918 +-4 37836 ++1 18918 ++1 18918 +-2 18918 ++7 18918 +-4 18918 ++1 18918 ++3 18918 ++9 11474750 ++1 42324 ++3 31743 ++1 9192 ++66 5732805 ++4 5732805 +-4 5732805 ++1 17198415 ++1 5732805 ++2 5732805 +-2 5732805 ++2 5732805 +-1 5732805 ++1 5732805 +-1 5732805 ++6 23092142 ++11 745236 ++3 1127312 +-2 563656 +-1 1127312 ++7 372618 ++3 745236 ++1 40586 ++1 40586 ++1 40586 +-2 121758 ++60 40586 +4459 89064 ++1 3348 ++1 3348 ++3 6696 +-4 15570 ++1 15570 ++3 31140 ++4 15924 +-2 3981 ++3 7962 ++9 9681 ++1 31590 ++2 12568 ++1 37704 +-23 106752 ++15 754 +-1 754 ++1 754 ++1 3016 +-16 33560 +-91 2226 ++39 3833404 +-2 15056030 ++6 3628466 ++1 7256932 ++4 3628466 +-3 7256932 ++1 3628466 ++1 7256932 ++1 3628466 ++2 3449524 ++1 3449524 ++3 3449524 ++3 3449524 +-3 20697144 ++2 6899048 +-2 3449524 ++6 3449524 +-4 3449524 ++5 13798096 +-7 178942 ++3 178942 +-3 1073652 ++2 357884 +-2 178942 ++6 178942 +-4 178942 ++5 715768 ++69 59748 +-39 73925 +-91 40112 ++91 1775 +-91 2868 +4599 64687356 ++2 64646716 ++2 145887 +4485 3227 ++6 974 +-1 974 ++1 974 ++1 974 ++1 1948 ++2 6454 +-53 43162 +-1 86324 ++1 86324 ++4 43162 +-1 43162 ++1 86324 +-78 32 +-35 4 +cfn=(904) +calls=1 5074 +* 670 +* 3 +4487 4506 +4697 5400773 ++1 5400773 +-1 5400773 ++1 10801546 ++2 10801546 ++33 1886 ++1 912 ++1 2280 +cfn=(904) +calls=456 5074 +* 200150 +* 456 ++14 1368 +-14 456 ++14 456 +4393 664064 +4625 664064 ++3 332032 +-3 332032 ++3 332032 ++2 332032 ++3 332032 +-3 664064 ++3 3356713 ++3 664064 ++1 253939 ++1 253939 +-1 253939 ++1 507878 ++37 336602 +-1 336602 ++1 1014376 +4524 4570 ++1 22850 +-1 110 ++1 550 ++6 13864 ++3 23 ++1 23 +-1 23 ++1 23 +-1 23 ++1 23 +-1 4547 ++1 4547 +-1 4547 ++1 4547 +-1 4547 ++1 45677 ++3 9140 ++1 59 ++1 236 +4649 78093 ++1 234279 +-6 78093 ++17 78093 +-6 78093 ++1 78093 ++2 78093 +-1 78093 ++4 78093 ++1 72934 ++1 156186 ++2 11501 ++1 11501 ++2 11501 ++3 11501 +-3 34503 ++3 11501 +-3 34503 ++2 11501 +-2 11501 ++2 34503 +-2 66592 ++3 66592 +-3 199776 ++3 66592 +-3 199776 ++2 66592 +-2 66592 ++2 199776 +4531 26 +4704 21599320 +-2 5399830 ++2 21599320 ++2 5399830 +-2 5399830 ++2 5399830 +-3 5399830 ++1 5399830 ++2 5399830 +-2 5399830 ++6 5399830 +-1 5399830 +-3 5399830 ++4 16199490 +2990 1948 ++13 487 +-13 487 ++13 490 ++14 5 ++7 2 ++60 486 ++9 972 +-9 486 ++9 3883 ++10 1458 ++4 1458 +3418 1458 ++1 486 ++8 1944 ++4 1458 +-2 486 ++2 1458 ++1 486 +-1 486 ++1 486 +-2 486 ++1 972 ++1 486 ++2 486 +4745 3409 +3074 972 +4549 4511 ++1 13533 ++9 4511 +-14 4511 ++10 4511 ++1 4511 ++2 4511 +-1 4511 ++2 4511 ++2 16 ++1 16 ++2 16 ++3 16 +-3 48 ++3 16 +-3 48 ++2 16 +-2 16 ++2 48 +-2 4495 ++3 4495 +-3 13485 ++3 4495 +-3 13485 ++2 4495 +-2 4495 ++2 13485 ++67 131391 +3169 2430 ++19 486 +-19 486 ++19 2430 ++8 486 +-8 486 ++8 486 ++1 2430 +cfi=(77) +cfn=(906) +calls=486 48 +* 26805 ++2 486 +-2 486 ++2 1458 ++2 122 ++1 122 +4746 122 +3247 972 ++1 1 ++1 2 ++6 1 +-6 1 ++6 1 +-6 970 ++6 485 +-6 485 ++6 1447 ++1 300 +-40 850 ++1 4 ++3 3 ++4 2 +-4 1272 ++4 1700 ++34 3406 ++40 5 ++19 1 ++3 2 ++1 3 ++2 3 ++1 4 +cfi=(77) +cfn=(906) +calls=1 48 +* 27 ++12 3 ++5 2 ++1 2 +4746 1 +3360 1 ++1 2 +-1 1 ++1 2 ++1 1 ++11 2 +-13 425 ++1 850 +-1 425 ++1 850 ++1 425 ++11 850 ++6 850 ++1 850 ++15 425 +-15 425 ++8 425 ++3 425 ++4 425 ++4 696 +cfn=(1150) +calls=232 4762 +* 11363 +* 232 +-40 2550 +-70 2 ++61 850 ++3 1275 +3226 3400 +cfi=(103) +cfn=(1422) +calls=425 82 +* 2550 ++2 425 +-2 425 ++2 850 ++12 425 ++6 850 +-14 1275 +3099 970 +-73 7 +cfi=(103) +cfn=(1422) +calls=1 82 +* 6 ++2 1 +-2 1 ++2 1 ++14 3 ++13 3 ++5 5 ++1 1 ++2 1 ++1 1 +-1 1 ++1 1 ++1 1 ++9 2 +4531 9068 ++4 59241 + +fn=(984) calloc +4017 18 +-13 18 ++13 18 +-3 18 ++3 18 +-13 108 ++10 18 ++3 36 ++8 36 ++1 36 ++15 198 ++7 18 ++8 18 +-7 36 ++7 36 ++7 54 +cfn=(902) +calls=18 4247 +* 2281 +* 18 ++3 72 ++2 198 ++74 162 +-36 18 +-3 18 ++3 72 ++10 18 ++1 36 ++1 36 ++2 36 ++1 54 +cfi=(82) +cfn=(986) +calls=18 44 +* 2448 +* 18 + +fn=(1150) +4762 20922059484 ++15 6974019828 ++6 13948039656 ++13 4649346552 ++13 4649346552 ++79 379716 ++21 569574 ++6 189858 +-10 189858 ++10 189858 ++8 569574 ++7 379716 +-1 189858 ++2 379716 ++6 569574 ++4 379716 ++1 1100 ++2 1100 +-1 1100 ++2 12350 ++3 379716 ++2 379344 ++7 180589 ++8 180589 ++1 180589 ++1 361178 +-2 9083 ++1 9083 ++1 18166 ++7 189672 +-2 189672 ++1 189672 ++1 189672 ++2 10182 ++1 10182 ++2 10182 ++3 10182 +-2 10182 ++2 10182 ++1 10182 +-1 10182 ++31 20364 +-34 179490 ++3 179490 +-2 179490 ++2 179490 ++1 179490 +-1 179490 ++31 359352 ++1 6606 ++3 9909 +4821 2324483418 +-1 6973450254 ++2 4648966836 ++27 6973450254 ++4 2324483418 +-1 2324483418 ++1 2324483418 ++20 6973450254 ++6 2324483418 ++1 2324483418 +5053 18597386208 +-99 101315 ++1 18166 ++60 6600 +cfn=(904) +calls=3300 +59 +* 2302912 +* 3300 +-21 186 ++2 186 +-1 744 ++24 9909 ++1 6606 +3465 1 ++4 7 ++2 2 +4917 3318 ++37 25592 +-9 936 + +fl=(79) +fn=(910) +29 487 ++3 2922 ++2 1461 ++7 974 +-5 1275 ++1 425 + +fl=(96) +fn=(1318) +36 8 ++1 1 +cfi=(69) +cfn=(642) +calls=1 -11 +* 16 +* 1 ++4 4 ++56 8 +-56 2 ++3 2 ++37 1 +-8 1 ++6 1 +-1 1 ++3 3 ++3 18 ++6 4 +cfi=(97) +cfn=(1320) +calls=1 -6 +* 29 +* 2 ++1 2 +-10 32 ++11 2 + +fl=(113) +fn=(1794) +47 2514 ++5 5028 +-5 12570 ++1 2514 +-1 2514 ++5 5028 ++5 7542 ++3 4588 ++1 2294 ++12 9176 ++6 13049 ++30 17598 +-36 5735 +cfi=(114) /build/buildd/eglibc-2.11.1/string/wordcopy.c +cfn=(1796) _wordcopy_fwd_aligned +calls=1147 -35 +* 69784 +* 1147 + +fl=(111) +fn=(1672) +37 42 ++7 7 + +fl=(49) +fn=(218) +27 390 ++7 468 ++2 196 ++2 196 +-2 196 ++1 784 ++1 392 +cfi=(47) +cfn=(220) +calls=196 152 +* 1358 ++1 392 ++2 70 ++1 63 +-8 211 ++14 99 +-14 12 ++14 171 + +fl=(74) +fn=(892) +29 5 ++15 1 + +fl=(107) +fn=(1506) +36 9 +-1 18 ++1 9 ++6 135 ++1 27 +cfi=(99) +cfn=(1508) +calls=9 899 +* 117 +* 18 +fi=(104) +984 9 +fe=(107) +43 9 +fi=(104) +984 9 ++1 99 +fe=(107) +47 27 + +fl=(75) +fn=(894) +127 9 ++5 1 +-5 2 ++5 2 +cob=(1) +cfi=(2) +cfn=(896) +calls=1 835 +* 2 ++3 5 ++1 4 ++1 40 ++1 2 +31 2 ++1 2 ++3 3 ++5 1 ++6 1 +-6 1 ++1 3 ++2 3 ++3 1 ++5 3 ++74 1 +-74 1 ++74 4 +-72 1 ++19 1 +-18 2 +-1 1010 ++19 1010 +-18 2020 ++2 3600 ++14 1248 ++2 3744 +-10 2496 ++1 1248 +-1 4296 ++1 900 +-1 1800 ++2 8592 ++1 6435 +-3 5518 ++3 614 +-3 5278 ++10 5307 +-21 4042 ++85 27 +-36 2 ++1 2 ++1 2 ++3 2 ++41 2 +cob=(1) +cfi=(2) +cfn=(898) +calls=1 841 +* 2 ++3 9 +-32 1 ++1 3 + +fl=(126) +fn=(2780) +29 1 ++3 1 ++1 2 ++4 1 +cob=(13) +cfi=(91) +cfn=(2782) +calls=1 155 +* 3 ++2 1 ++1 1 ++3 1 ++2 1 + +fl=(76) +fn=(900) +117 1 ++2 4 +-1 3 ++2 1 + +fl=(106) +fn=(1488) +82 6 +cfn=(1490) __write_nocancel +calls=3 * +* 15 + +fn=(2852) +82 2 +cfn=(1924) +calls=1 * +* 5 + +fn=(1490) +82 15 + +fn=(1592) +82 12 +cfn=(1594) __open_nocancel +calls=6 * +* 30 + +fn=(1678) +82 12 +cfn=(1680) __read_nocancel +calls=6 * +* 30 + +fn=(1594) +82 30 + +fn=(1680) +82 30 + +fn=(1924) +82 30 + +fl=(95) +fn=(1302) +34 14 ++2 7 + +fl=(56) +fn=(364) __new_exitfn +73 608 ++6 608 +-6 608 ++6 3040 ++2 3040 ++2 1824 ++1 3035 +-3 1 ++10 1 +-10 3 ++13 1214 ++25 589 ++1 589 +-1 589 ++1 589 +-1 589 ++7 589 ++1 589 ++3 1178 +-4 19 ++1 19 ++3 1254 ++3 1824 +-39 18 ++4 38 ++2 36 ++1 54 +cfi=(71) +cfn=(984) +calls=18 4017 +* 6169 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 -71 +* 1060 ++2 54 ++2 36 ++1 18 ++6 18 ++1 36 +-1 1 ++1 2 +-32 2 + +fn=(362) +57 1216 +-22 608 ++22 3040 +-22 608 +cfn=(364) +calls=608 +38 +* 29941 ++2 1824 ++4 1216 ++3 608 +-1 608 ++2 608 ++2 1216 ++12 3648 + +fl=(83) +fn=(1012) +178 5 + +fn=(3758) +176 5 + +fl=(64) +fn=(622) +35 768 ++5 256 +-5 768 ++5 1280 ++5 512 ++4 384 +fi=(65) /build/buildd/eglibc-2.11.1/wcsmbs/./wcsmbsload.h ++23 384 +fe=(64) +-20 128 +-2 256 ++2 384 ++5 256 ++3 256 +cfi=(66) +cfn=(626) +calls=128 -21 +* 512 +* 384 +cfi=(67) +cfn=(628) +calls=128 -8 +* 640 ++42 1536 +fi=(65) +-28 512 +fe=(64) + +fl=(151) +fn=(3678) +49 5 +-7 57 ++36 57 +-32 19 ++32 19 +-32 19 ++32 1647 +-32 549 ++32 549 +-32 549 ++3 1216 ++1 3217 +-4 118 ++37 19 ++1 19 +-1 19 ++1 19 ++7 6 +cfi=(100) +cfn=(3926) +calls=1 1007 +* 261 +* 3 ++2 3 +cfi=(155) +cfn=(3934) +calls=1 -60 +* 5 +-19 549 ++4 549 +-4 1098 ++4 549 +-2 1098 ++2 549 +cob=(1) +cfi=(152) +cfn=(3698) +calls=1 +43 +* 28726 +cob=(12) +cfi=(84) +cfn=(3434) +calls=1 -78 +* 15 +cob=(12) +cfi=(84) +cfn=(3696) +calls=1 -78 +* 1360 +cob=(12) +cfi=(84) +cfn=(3692) +calls=3 -78 +* 872 +cob=(12) +cfi=(84) +cfn=(3690) +calls=1 -78 +* 52 +cob=(12) +cfi=(84) +cfn=(3682) +calls=1 -78 +* 73 +cob=(7) +cfi=(53) +cfn=(3680) +calls=68 -78 +* 816 +cob=(7) +cfi=(53) +cfn=(1380) +calls=473 -78 +* 47300 +* 549 ++9 36 +cfi=(71) +cfn=(1148) +calls=18 3692 +* 1890 +* 36 + +fl=(140) /build/buildd/eglibc-2.11.1/libio/strops.c +fn=(3642) _IO_str_init_static_internal +40 6 ++4 1 +-4 2 ++4 1 ++6 5 +cfi=(100) +cfn=(1424) +calls=1 404 +* 17 ++5 1 +-3 1 ++1 1 ++1 1 ++1 1 ++2 1 ++1 1 ++1 1 ++9 1 ++1 6 +-23 5 + +fl=(40) +fn=(196) +52 6 ++6 1 +-6 2 ++6 2 ++17 1 +-2 1 ++1 1 +fi=(42) /build/buildd/eglibc-2.11.1/csu/../sysdeps/unix/sysv/linux/x86_64/init-first.c +-41 2 +fe=(40) ++42 1 +fi=(42) +-42 2 +fi=(41) /build/buildd/eglibc-2.11.1/csu/../sysdeps/generic/dl-hash.h ++2 3 +fe=(40) ++32 1 +-9 1 ++9 4 +fi=(41) +-29 1 +-1 2 ++1 3 ++3 1 +-1 3 ++1 3 +fi=(42) +-8 2 ++2 2 +-2 1 ++2 1 +cfi=(43) /build/buildd/eglibc-2.11.1/elf/../sysdeps/unix/sysv/linux/dl-vdso.c +cfn=(202) _dl_vdso_vsym +calls=1 -8 +* 8 ++8 1 +-5 2 ++5 1 +-5 1 ++2 2 ++1 1 ++2 1 +cfi=(43) +cfn=(202) +calls=1 -16 +* 8 +fe=(40) ++46 3 +fi=(42) +-45 2 ++1 1 +fe=(40) ++44 1 +cfi=(44) +cfn=(204) +calls=1 -58 +* 57 ++8 1 +cfi=(46) +cfn=(208) +calls=1 -78 +* 6280 ++2 6 +fi=(41) +-55 1 +-1 3 ++1 3 ++2 4 ++1 5 ++3 4 +-3 1 ++4 2 ++13 1 ++1 2 +-18 2 ++3 12 +-3 3 ++4 6 ++13 3 ++1 6 +-18 8 +fe=(40) + +fl=(80) +fn=(940) +32 3 ++1 3 ++2 3 ++1 3 ++1 3 ++2 3 + +fl=(116) +fn=(1834) +26 376 ++1 376 ++1 376 ++1 376 ++1 376 ++2 376 ++1 376 ++1 376 ++1 376 ++1 376 ++1 376 ++1 376 ++1 376 +-7 3 ++1 3 ++1 3 ++1 3 ++1 3 ++1 3 ++1 3 ++1 3 ++1 376 ++1 376 + +fl=(120) +fn=(1914) +43 15 ++14 5 +-14 5 ++14 10 ++3 80 ++1 10 +fi=(104) +984 10 ++1 30 +fe=(120) +66 20 +cfi=(99) +cfn=(1928) +calls=5 206 +* 160 ++1 15 ++18 30 ++2 5 ++1 10 +cfi=(71) +cfn=(1148) +calls=5 3692 +* 635 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 -58 +* 1009 ++4 25 +-10 10 +-20 10 +cfi=(99) +cfn=(1918) +calls=5 163 +* 415 +* 15 +-4 5 +cfi=(100) +cfn=(1916) +calls=5 +6 +* 418 +* 15 +fi=(104) +985 30 +fe=(120) + +fl=(121) +fn=(2148) +29 1 ++1 1 ++2 1 ++1 1 ++1 1 ++2 1 + +fl=(139) +fn=(3640) +101 8 ++9 1 +-9 1 ++9 3 ++6 5 +-11 1 ++11 1 +cfi=(100) +cfn=(1582) +calls=1 648 +* 41 ++1 1 ++2 4 ++3 1 +-5 1 ++1 1 ++1 1 +cfi=(140) +cfn=(3642) +calls=1 -79 +* 52 ++1 4 +cfi=(141) +cfn=(3644) +calls=1 +90 +* 2621 ++2 2 ++1 2 ++2 7 + +fl=(114) +fn=(1796) +38 6882 ++71 3063 ++1 3063 ++2 3063 ++1 3063 ++2 3063 ++1 3063 ++2 3063 ++1 3063 ++3 3063 ++3 6126 +-13 3 ++1 3 ++2 3 ++1 3 ++2 3 ++1 3 ++3 3 ++3 6 +-7 129 ++1 129 ++3 129 ++3 258 +-4 2048 +-24 2048 ++1 2048 ++2 2048 ++1 2048 ++2 2048 ++1 2048 ++2 2048 ++1 4096 +-7 4 ++1 4 ++2 4 ++1 4 ++2 4 ++1 8 +-29 8 ++2 4 ++2 4 ++1 4 +-42 129 ++3 387 ++1 129 ++8 3 ++3 9 ++1 3 ++2 1011 ++3 3033 ++1 1011 ++67 2294 + +fl=(112) +fn=(1836) str_to_mpn +283 245 +fi=(158) /build/buildd/eglibc-2.11.1/stdlib/../stdlib/gmp.h +447 245 +fe=(112) +283 980 ++6 245 +-6 980 ++6 245 +-6 1225 ++6 245 ++39 490 +-5 5136 ++3 332 ++7 332 ++3 166 ++3 166 +-3 332 ++1 166 ++2 166 +-3 166 ++3 166 +-3 1118 ++3 1118 +-3 2236 ++1 1118 ++2 1118 +-3 1118 ++3 1118 +-46 2078 ++48 735 ++9 245 +-2 490 ++2 245 +-2 245 ++2 245 ++2 245 ++1 245 ++12 2205 +-82 247 +fi=(158) +447 247 +fe=(112) +283 988 ++6 247 +-6 988 ++6 247 +-6 1235 ++6 247 ++39 494 +-5 5184 ++3 328 ++7 328 ++3 164 ++3 164 +-3 328 ++1 164 ++2 164 +-3 164 ++3 164 +-3 1132 ++3 1132 +-3 2264 ++1 1132 ++2 1132 +-3 1132 ++3 1132 +-46 2098 ++48 741 ++9 247 +-2 494 ++2 247 +-2 247 ++2 247 ++2 247 ++1 247 ++12 2223 + +fn=(2328) ____strtof_l_internal +416 2331 ++56 259 +-2 259 +-54 259 ++56 259 ++15 518 ++17 259 ++1 1036 +cfi=(69) +cfn=(642) +calls=259 26 +* 4144 ++22 518 +-22 259 ++22 259 +-6 259 ++6 777 ++3 518 ++1 777 ++3 518 ++5 483 ++13 777 ++1 1295 ++75 774 ++19 518 ++1 972 ++1 390 +-1 390 ++17 259 ++6 518 ++1 1167 ++6 390 ++1 780 +-7 546 ++42 1957 ++13 490 ++16 245 +-2 245 ++2 245 ++42 490 ++9 490 ++1 1043 +-1 546 ++7 182 ++1 182 +-1 182 ++1 728 ++1 546 ++4 3964 ++3 925 +-1 925 ++1 1850 +-7 2775 ++7 132 +-1 132 ++1 264 +-7 1271 +561 777 +1585 2072 +678 543 +-6 362 +819 126 ++5 2 ++1 2 ++8 3 ++5 2 ++5 5 ++7 3 ++2 1 +-2 1 ++2 1 +-2 3 ++2 1 +-2 1 ++2 1 ++28 4 ++2 6 ++2 2 ++1 2 ++7 1 +-7 2 ++7 1 ++2 245 ++8 1162 ++19 490 ++1 245 ++2 490 ++3 719 ++26 490 ++77 1402 ++2 228 ++1 228 ++3 228 +-4 228 ++4 456 +-4 17 ++1 17 ++3 17 +-4 17 ++4 34 ++6 490 ++6 245 +-15 245 ++15 2492 +1221 910 ++8 546 ++20 182 +-20 728 ++20 182 +-20 364 ++20 182 +-20 364 ++14 182 ++1 546 +-1 182 ++1 546 +cfi=(81) +cfn=(966) +calls=182 56 +* 3276 ++18 722 +-3 360 ++1 360 +-24 1084 ++3 363 ++2 726 ++8 1629 +cfi=(115) +cfn=(1832) +calls=181 58 +* 9050 ++4 181 ++1 181 +-1 181 ++1 181 ++1 362 ++7 181 +-7 362 ++7 363 ++2 728 ++4 2184 +cfn=(1836) +calls=182 283 +* 22154 ++17 182 ++2 182 +-2 546 ++2 364 ++4 910 +cfi=(117) +cfn=(1838) +calls=182 26 +* 2730 ++1 910 +cfi=(117) +cfn=(1838) +calls=182 26 +* 2730 ++1 546 ++13 182 +-2 182 ++2 182 +1577 910 +cfn=(1840) round_and_return +calls=182 182 +* 7434 +* 182 +818 364 ++1 493 ++73 244 +-7 244 ++7 244 ++2 546 ++8 189 +718 244 ++22 488 ++1 244 +1045 66 +537 392 ++91 1560 +1045 6 +927 80 ++9 32 ++2 32 ++10 48 +-1 16 ++1 16 +-1 16 ++2 16 +-1 32 +-1 32 +795 252 +-52 490 +1051 1071 +cfn=(1836) +calls=63 283 +* 5796 +* 63 ++6 189 +828 4 +1101 63 ++1 126 +-1 126 ++1 63 ++4 126 ++9 126 ++32 126 ++3 504 ++2 126 ++8 126 ++2 630 +cfi=(117) +cfn=(1838) +calls=63 26 +* 945 ++4 189 ++15 441 +cfn=(1840) +calls=63 182 +* 2268 +* 63 +764 28 +-65 84 +cfi=(119) +cfn=(1862) +calls=14 56 +* 252 ++5 98 +1030 85 +1313 182 ++1 182 ++5 182 ++38 364 +-38 364 ++38 3640 ++4 1456 +1097 126 +1265 765 +cfi=(81) +cfn=(966) +calls=153 56 +* 2754 +* 306 + +fn=(1786) ____strtod_l_internal +416 2277 ++56 253 +-2 253 +-54 253 ++56 253 ++15 506 ++17 253 ++1 1012 +cfi=(69) +cfn=(642) +calls=253 26 +* 4048 ++22 506 +-22 253 ++22 253 +-6 253 ++6 759 ++3 506 ++1 759 ++3 506 ++5 474 ++13 759 ++1 1265 ++75 778 ++19 506 ++1 944 ++1 370 +-1 370 ++17 253 ++6 506 ++1 1129 ++6 370 ++1 740 +-7 514 ++42 1989 ++13 498 ++16 249 +-2 249 ++2 249 ++42 498 ++9 498 ++1 1061 +-1 552 ++7 184 ++1 184 +-1 184 ++1 736 ++1 552 ++4 3996 ++3 929 +-1 929 ++1 1858 +-7 2787 ++7 140 +-1 140 ++1 280 +-7 1305 +561 759 +1585 2024 +678 543 +-6 362 +819 130 ++5 2 ++1 2 ++8 3 ++5 2 ++5 5 ++7 3 ++2 1 +-2 1 ++2 1 +-2 3 ++2 1 +-2 1 ++2 1 ++28 4 ++2 6 ++2 2 ++1 2 ++7 1 +-7 2 ++7 1 ++2 245 ++8 1168 ++19 498 ++1 249 ++2 498 ++3 719 ++26 490 ++77 1402 ++2 228 ++1 228 ++3 228 +-4 228 ++4 456 +-4 17 ++1 17 ++3 17 +-4 17 ++4 34 ++6 490 ++6 245 +-15 245 ++15 2448 +1221 900 ++8 540 ++20 180 +-20 720 ++20 180 +-20 360 ++20 180 +-20 360 ++14 180 ++1 540 +-1 180 ++1 540 +cfi=(81) +cfn=(966) +calls=180 56 +* 3240 ++18 712 +-3 361 ++1 361 +-24 1082 ++3 365 ++2 730 ++8 1665 +cfi=(115) +cfn=(1832) +calls=185 58 +* 9250 ++4 185 ++1 185 +-1 185 ++1 185 ++1 370 ++7 185 +-7 370 ++7 365 ++2 720 ++4 2160 +cfn=(1836) +calls=180 283 +* 22182 ++17 180 ++2 180 +-2 540 ++2 360 ++4 900 +cfi=(117) +cfn=(1838) +calls=180 26 +* 2700 ++1 900 +cfi=(117) +cfn=(1838) +calls=180 26 +* 2700 ++1 540 ++13 180 +-2 180 ++2 180 +1577 900 +cfn=(1840) +calls=180 182 +* 7850 +* 180 +818 368 ++1 501 ++73 248 +-7 248 ++7 248 ++2 552 ++3 4 +-3 12 ++8 195 +718 248 ++22 496 ++1 248 +1045 36 +537 380 ++91 1480 +1045 4 +927 80 ++9 32 ++2 32 ++10 48 +-1 16 ++1 16 +-1 16 ++2 16 +-1 32 +-1 32 +795 260 +-52 498 +1051 1139 +cfn=(1836) +calls=67 283 +* 6004 +* 67 ++6 201 +828 4 +1101 67 ++1 134 +-1 134 ++1 67 ++4 134 ++9 134 ++32 134 ++3 520 ++2 130 ++8 130 ++2 650 +cfi=(117) +cfn=(1838) +calls=65 26 +* 975 ++4 195 ++15 455 +cfn=(1840) +calls=65 182 +* 2535 +* 65 +764 8 +-65 24 +cfi=(119) +cfn=(1862) +calls=4 56 +* 72 ++5 28 +1030 85 +1313 180 ++1 180 ++5 180 ++38 360 +-38 360 ++38 360 +-38 2 ++38 3199 ++4 1440 +-4 6 ++2 1 +-2 1 ++2 1 +390 6 +1357 18 +389 15 +cfi=(117) +cfn=(1838) +calls=3 26 +* 45 ++1 18 +1097 134 ++89 14 +cfi=(81) +cfn=(966) +calls=2 56 +* 36 +* 22 ++79 785 +cfi=(81) +cfn=(966) +calls=157 56 +* 2826 +* 314 ++92 4 + +fn=(1840) +182 1470 ++1 245 +-1 735 ++1 490 ++56 784 +fi=(158) +448 98 +fe=(112) +245 98 +fi=(158) +449 98 +fe=(112) +245 98 ++10 196 ++8 490 ++3 735 ++1 1225 +-1 245 +cfi=(125) /build/buildd/eglibc-2.11.1/stdlib/../sysdeps/ieee754/flt-32/mpn2flt.c +cfn=(2330) __mpn_construct_float +calls=245 34 +* 2695 +-84 1470 ++1 245 +-1 735 ++1 490 ++56 739 +fi=(158) +448 83 +fe=(112) +245 166 +fi=(158) +449 83 +fe=(112) +245 83 ++10 166 ++8 490 ++3 735 ++1 1225 +-1 245 +cfi=(118) +cfn=(1842) +calls=245 40 +* 3430 + +fn=(2326) +1601 777 +cfn=(2328) +calls=259 416 +* 154525 + +fn=(1784) +1601 759 +cfn=(1786) +calls=253 416 +* 155089 + +fl=(150) /build/buildd/eglibc-2.11.1/stdlib/divrem.c +fn=(3664) __mpn_divrem +57 70 ++3 7 +-3 14 ++3 7 +245 63 +73 7 ++1 7 ++2 21 ++6 21 ++1 14 +-38 18 ++38 6 ++1 6 +-1 6 ++1 12 +-1 18 ++4 7 +-2 7 ++2 14 ++3 7 ++2 7 + +fl=(125) +fn=(2330) +34 245 ++2 245 +-2 735 ++2 1225 ++6 245 + +fl=(43) +fn=(202) +27 2 ++1 4 ++4 4 ++14 2 ++4 4 + +fl=(109) +fn=(1596) +53 45 ++10 15 ++2 10 +fi=(110) /build/buildd/eglibc-2.11.1/string/../string/str-two-way.h +273 5 +fe=(109) +89 45 +-26 15 + +fl=(136) +fn=(3194) +62 1 ++1 1 ++3 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++2 1 + +fl=(68) +fn=(640) +28 45 ++6 9 +-6 18 ++3 9 +cfi=(69) +cfn=(642) +calls=9 -5 +* 156 ++3 9 +-3 9 ++3 18 ++8 40 ++1 80 +-8 40 ++2 80 +cfi=(69) +cfn=(642) +calls=40 -11 +* 724 +* 18 +cfi=(69) +cfn=(642) +calls=9 -11 +* 144 ++2 391 ++9 9 ++1 9 +-1 9 ++1 45 + +fl=(144) /build/buildd/eglibc-2.11.1/math/../sysdeps/ieee754/dbl-64/s_isnan.c +fn=(3650) isnan +33 3 ++2 1 +-2 1 ++2 9 ++3 1 + +fl=(143) +fn=(3648) +163 10 ++33 1 ++2 1 ++22 4 ++59 1 +-59 2 ++59 1 ++2 6 ++1 1 ++23 3 ++96 1 ++3 1 +-3 1 ++3 3 +cfi=(144) +cfn=(3650) +calls=1 33 +* 15 +* 4 +-66 3 ++16 2 ++65 4 +cfi=(145) +cfn=(3652) +calls=1 23 +* 16 +* 4 +1265 9 +435 10 +cfi=(146) +cfn=(3654) +calls=1 36 +* 23 +* 1 ++4 2 ++36 1 ++12 1 +-12 9 ++4 4 ++1 2 ++1 2 +-2 1 ++1 1 +-1 1 ++2 1 ++7 1 +-8 1 ++1 1 ++7 1 ++9 3 ++15 4 +-18 2 ++59 4 +-59 2 ++59 4 +-6 1 +-1 1 ++1 6 +cfi=(81) +cfn=(966) +calls=1 56 +* 23 +* 1 ++15 15 ++11 26 +-2 24 +-54 12 ++4 48 +-4 1 ++4 4 ++2 8 ++30 24 +cfi=(115) +cfn=(1832) +calls=3 58 +* 174 ++4 9 ++2 12 +-54 17 +cfi=(117) +cfn=(1838) +calls=1 26 +* 15 ++3 9 ++1 1 +-1 1 ++1 1 ++1 5 ++52 20 +cfi=(147) +cfn=(3656) +calls=4 43 +* 48 +* 13 ++3 5 +cfi=(81) +cfn=(966) +calls=1 56 +* 23 ++1 2 ++2 1 +-2 1 ++1 2 +-1 1 ++1 2 ++1 4 +fi=(149) /build/buildd/eglibc-2.11.1/stdio-common/../include/ctype.h +47 1 +fe=(143) +834 1 +fi=(149) +47 1 +fe=(143) +834 1 +fi=(149) +47 2 +fe=(143) +844 3 ++2 1 +-2 1 ++2 1 ++10 2 ++20 7 ++1 3 ++7 1 +-3 1 ++5 1 +-5 1 ++3 1 ++2 1 +-2 1 ++2 2 ++14 6 ++4 4 ++12 6 ++7 2 +fi=(159) /build/buildd/eglibc-2.11.1/stdio-common/../nptl/sysdeps/pthread/allocalim.h +28 2 +fe=(143) +933 7 ++1 1 ++3 1 +-3 1 ++3 2 ++3 1 +-3 1 ++3 13 ++2 1 ++1 2 +cfn=(3662) hack_digit.15661 +calls=1 236 +* 114 +* 2 +-3 11 ++6 10 ++3 3 ++8 5 ++22 1 +-15 1 ++15 7 +cfn=(3662) +calls=1 236 +* 103 ++1 8 +1102 5 ++7 3 ++3 2 ++6 3 ++2 3 ++19 1 ++1 1 +-1 1 ++1 5 ++4 3 ++14 3 ++6 3 ++2 7 ++2 1 +-2 1 ++2 4 ++3 2 ++7 5 ++9 3 ++47 3 ++17 5 ++3 3 ++7 3 +-92 2 +-5 3 +574 1 ++6 6 +-6 1 ++6 1 ++4 7 ++4 1 ++2 3 +1173 3 ++78 137 +-58 3 ++4 3 +cfi=(69) +cfn=(642) +calls=1 26 +* 16 +* 1 ++2 5 ++6 5 ++1 3 ++11 6 ++1 1 ++6 2 +-6 1 ++6 8 ++3 20 ++3 20 +-6 33 ++1 33 ++1 3 +cfi=(81) +cfn=(3666) +calls=1 56 +* 18 +* 2 ++25 5 +464 4 +877 3 ++80 12 ++15 5 +-6 5 ++2 5 +-5 22 ++4 10 +cfn=(3662) +calls=5 236 +* 565 ++1 5 +-1 5 ++1 5 +-4 10 +1175 2 +604 2 ++15 6 ++16 4 ++2 1 +-2 4 +cfi=(148) +cfn=(3658) +calls=1 25 +* 25 ++16 2 +-1 1 ++1 3 +-1 1 ++1 3 +cfi=(148) +cfn=(3658) +calls=1 25 +* 25 ++3 9 +-38 3 +1149 4 +584 5 + +fn=(3662) +236 28 ++3 21 ++2 21 ++7 21 ++4 49 +cfi=(150) +cfn=(3664) +calls=7 57 +* 339 ++1 28 ++4 7 +-1 7 +-3 7 ++1 7 ++3 35 ++11 21 +cfi=(116) +cfn=(1834) +calls=7 26 +* 105 ++1 14 ++1 36 ++4 12 +-4 6 ++4 12 +-4 1 ++4 2 +-4 1 ++4 2 + +totals: 1323501268167 diff --git a/profiles/callgrind.out.16517 b/profiles/callgrind.out.16517 new file mode 100755 index 0000000..e69de29 diff --git a/profiles/callgrind.out.3008 b/profiles/callgrind.out.3008 new file mode 100755 index 0000000..653a7a6 --- /dev/null +++ b/profiles/callgrind.out.3008 @@ -0,0 +1,37718 @@ +version: 1 +creator: callgrind-3.6.0.SVN-Debian +pid: 3008 +cmd: test_gradient fibre/tract/random-p_0-16-4.tst analysis/test_gradient/prob_likelihood_log_prob_call.tst -object Prob::Likelihood::ImageDiff::Gaussian -func log_prob -hess -obs image/tract/single/y/gauss/snr20/a.mif +part: 1 + + +desc: I1 cache: +desc: D1 cache: +desc: L2 cache: + +desc: Timerange: Basic block 0 - 856665900000 +desc: Trigger: Program termination + +positions: line +events: Ir +summary: 7351907657194 + + +ob=(10) /lib/libz.so.1.2.3.3 +fl=(59) ??? +fn=(448) 0x0000000000002300 +0 6 + +fn=(442) 0x0000000000002260 +0 6 + +fn=(454) 0x000000000000ed00 +0 11 + +ob=(7) /usr/lib/libstdc++.so.6.0.13 +fl=(53) ??? +fn=(2852) std::_Rb_tree_increment(std::_Rb_tree_node_base*) +0 141593184 + +fn=(550) std::locale::id::_M_id() const +0 57307 + +fn=(604) std::ctype::_M_initialize_ctype() +0 10 +cob=(4) /lib/libc-2.11.1.so +cfi=(62) /build/buildd/eglibc-2.11.1/locale/uselocale.c +cfn=(610) uselocale +calls=1 32 +0 21 +cob=(1) /lib/ld-2.11.1.so +cfi=(54) /build/buildd/eglibc-2.11.1/elf/../sysdeps/x86_64/dl-trampoline.S +cfn=(356) _dl_runtime_resolve +calls=1 30 +0 1748 +0 898 +cob=(4) +cfi=(63) /build/buildd/eglibc-2.11.1/wcsmbs/wctob.c +cfn=(616) wctob +calls=128 33 +0 2432 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1674 +0 260 +cob=(4) +cfi=(64) /build/buildd/eglibc-2.11.1/wcsmbs/btowc.c +cfn=(622) btowc +calls=1 35 +0 20 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1657 +0 510 +cob=(4) +cfi=(64) +cfn=(622) +calls=255 35 +0 9196 +0 1091 +cfn=(634) std::ctype::_M_convert_to_wmask(unsigned short) const +calls=8 0 +0 3013 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1150 +0 16 +cfn=(634) +calls=4 0 +0 793 +0 99 +cob=(4) +cfi=(62) +cfn=(610) +calls=1 32 +0 21 +0 2 + +fn=(684) std::messages::messages(unsigned long) +0 11 +cfn=(524) std::locale::facet::_S_get_c_locale() +calls=1 0 +0 7 +0 2 +cfn=(512) std::locale::facet::_S_get_c_name() +calls=1 0 +0 2 +0 4 + +fn=(772) std::ctype const& std::use_facet >(std::locale const&) +0 7004 +cfn=(550) +calls=1751 0 +0 8755 +0 19261 +cfn=(764) __dynamic_cast +calls=1751 0 +0 164594 +0 7004 + +fn=(1372) std::string::_M_leak_hard() +0 3408 + +fn=(1514) std::basic_streambuf >::xsputn(char const*, long) +0 13564 +cfn=(3578) std::basic_filebuf >::overflow(int) +calls=2 0 +0 108 +cfn=(1516) std::basic_stringbuf, std::allocator >::overflow(int) +calls=333 0 +0 123331 +0 11922 +cob=(4) +cfi=(81) /build/buildd/eglibc-2.11.1/string/../sysdeps/x86_64/memcpy.S +cfn=(966) memcpy +calls=488 56 +0 12012 +0 2440 + +fn=(1594) std::string::compare(char const*) const +0 12768 +cob=(4) +cfi=(69) /build/buildd/eglibc-2.11.1/string/../sysdeps/x86_64/multiarch/../strlen.S +cfn=(642) __GI_strlen +calls=1596 26 +0 29328 +0 33706 + +fn=(1614) std::__basic_file::__basic_file(pthread_mutex_t*) +0 27 + +fn=(1706) std::basic_filebuf >::_M_set_buffer(long) +0 431 + +fn=(1800) std::string::find_last_not_of(char const*, unsigned long, unsigned long) const +0 6069 +cob=(4) +cfi=(89) /build/buildd/eglibc-2.11.1/string/../sysdeps/x86_64/memchr.S +cfn=(1252) memchr +calls=1 25 +0 22 +0 1516 +cob=(4) +cfi=(89) +cfn=(1252) +calls=379 25 +0 8693 +0 3416 + +fn=(1824) std::num_get > >::do_get(std::istreambuf_iterator >, std::istreambuf_iterator >, std::ios_base&, std::_Ios_Iostate&, double&) const +0 6026 +cfn=(1384) std::string::reserve(unsigned long) +calls=262 0 +0 47557 +0 2882 +cfn=(1830) std::num_get > >::_M_extract_float(std::istreambuf_iterator >, std::istreambuf_iterator >, std::ios_base&, std::_Ios_Iostate&, std::string&) const +calls=262 0 +0 139732 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1951 +0 1834 +cfn=(524) +calls=262 0 +0 1834 +0 1572 +cfn=(1842) void std::__convert_to_v(char const*, double&, std::_Ios_Iostate&, __locale_struct* const&) +calls=262 0 +0 169124 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1435 +0 9536 +cfn=(1310) std::string::_Rep::_M_destroy(std::allocator const&) +calls=262 0 +0 21484 +0 1310 + +fn=(1832) 0x000000000008ba20 +0 7803 +cfn=(550) +calls=867 0 +0 4335 +0 12138 + +fn=(1904) 0x000000000008a140 +0 2352 + +fn=(2310) std::num_get > >::do_get(std::istreambuf_iterator >, std::istreambuf_iterator >, std::ios_base&, std::_Ios_Iostate&, long&) const +0 100 +cfn=(2316) std::istreambuf_iterator > std::num_get > >::_M_extract_int(std::istreambuf_iterator >, std::istreambuf_iterator >, std::ios_base&, std::_Ios_Iostate&, long&) const +calls=10 0 +0 2801 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1905 +0 20 + +fn=(3162) std::ostream::put(char) +0 30 +cfn=(1512) std::ostream::sentry::sentry(std::ostream&) +calls=3 0 +0 63 +0 67 +cfn=(3164) __gnu_cxx::stdio_sync_filebuf >::overflow(int) +calls=1 0 +0 1854 +0 2 + +fn=(3294) std::__num_base::_S_format_float(std::ios_base const&, char*, char) +0 135 + +fn=(3360) std::basic_ifstream >::basic_ifstream() +0 30 +cfn=(722) std::ios_base::ios_base() +calls=3 0 +0 291 +0 66 +cfn=(728) std::basic_ios >::init(std::basic_streambuf >*) +calls=3 0 +0 2124 +0 24 +cfn=(1608) std::basic_filebuf >::basic_filebuf() +calls=3 0 +0 795 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1228 +0 9 +cfn=(728) +calls=3 0 +0 2124 +0 21 + +fn=(3586) std::basic_filebuf >::_M_convert_to_external(char*, long) +0 38 +cfn=(1740) std::codecvt::do_always_noconv() const +calls=2 0 +0 4 +0 32 +cfn=(3592) std::__basic_file::xsputn(char const*, long) +calls=2 0 +0 1775 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1114 +0 6 + +fn=(580) std::__timepunct::__timepunct(std::__timepunct_cache*, unsigned long) +0 13 +cfn=(512) +calls=1 0 +0 2 +0 4 +cfn=(586) std::__timepunct::_M_initialize_timepunct(__locale_struct*) +calls=1 0 +0 114 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1401 +0 3 + +fn=(678) std::__timepunct::_M_initialize_timepunct(__locale_struct*) +0 9 +cfn=(524) +calls=1 0 +0 7 +0 96 + +fn=(792) bool std::has_facet > > >(std::locale const&) +0 6972 +cfn=(550) +calls=1743 0 +0 8715 +0 19173 +cfn=(764) +calls=1743 0 +0 102837 +0 6972 + +fn=(810) std::basic_ios >::_M_cache_locale(std::locale const&) +0 28 +cfn=(816) bool std::has_facet >(std::locale const&) +calls=4 0 +0 332 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1166 +0 16 +cfn=(822) std::ctype const& std::use_facet >(std::locale const&) +calls=4 0 +0 332 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1193 +0 12 +cfn=(828) bool std::has_facet > > >(std::locale const&) +calls=4 0 +0 332 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1580 +0 16 +cfn=(834) std::num_put > > const& std::use_facet > > >(std::locale const&) +calls=4 0 +0 332 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1631 +0 12 +cfn=(840) bool std::has_facet > > >(std::locale const&) +calls=4 0 +0 332 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1572 +0 16 +cfn=(846) std::num_get > > const& std::use_facet > > >(std::locale const&) +calls=4 0 +0 332 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1623 +0 20 + +fn=(934) std::basic_string, std::allocator >::basic_string(char const*, std::allocator const&) +0 8262481824 +cob=(4) +cfi=(69) +cfn=(642) +calls=688540152 26 +0 15147882504 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1690 +0 3442700760 +cfn=(942) 0x00000000000a8880 +calls=688540152 0 +0 127218055013 +0 4131240912 + +fn=(1534) std::basic_stringbuf, std::allocator >::str() const +0 6240 +cfn=(1540) std::basic_string, std::allocator >::basic_string(char*, char*, std::allocator const&) +calls=324 0 +0 56891 +0 972 +cfn=(1264) std::string::assign(std::string const&) +calls=324 0 +0 9072 +0 3306 +cfn=(1540) +calls=6 0 +0 1765 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1073 +0 18 +cfn=(1264) +calls=6 0 +0 168 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 992 +0 2664 + +fn=(1556) std::ios_base::~ios_base() +0 5600 +cfn=(1562) std::ios_base::_M_call_callbacks(std::ios_base::event) +calls=700 0 +0 8400 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1226 +0 1400 +cfn=(1568) std::ios_base::_M_dispose_callbacks() +calls=700 0 +0 11200 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1164 +0 5600 +cfn=(746) std::locale::~locale() +calls=700 0 +0 8400 + +fn=(1580) std::string::_M_replace_safe(unsigned long, unsigned long, char const*, unsigned long) +0 121 +cfn=(1586) std::string::_M_mutate(unsigned long, unsigned long, unsigned long) +calls=11 0 +0 2158 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 978 +0 176 +cob=(4) +cfi=(81) +cfn=(966) +calls=11 56 +0 375 +0 11 + +fn=(1620) bool std::has_facet >(std::locale const&) +0 36 +cfn=(550) +calls=9 0 +0 45 +0 99 +cfn=(764) +calls=9 0 +0 531 +0 36 + +fn=(1722) std::ctype::do_widen(char const*, char const*, char*) const +0 5 +cob=(4) +cfi=(81) +cfn=(966) +calls=1 56 +0 113 +0 3 + +fn=(1778) std::basic_streambuf >::sbumpc() +0 1477 + +fn=(1794) std::string::find_first_not_of(char const*, unsigned long, unsigned long) const +0 7658 +cob=(4) +cfi=(89) +cfn=(1252) +calls=482 25 +0 11013 +0 3625 + +fn=(2302) std::istream::operator>>(int&) +0 28 +cfn=(2308) std::istream& std::istream::_M_extract(long&) +calls=4 0 +0 3445 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1080 +0 72 + +fn=(2308) +0 90 +cfn=(1736) std::istream::sentry::sentry(std::istream&, bool) +calls=10 0 +0 514 +0 230 +cfn=(2310) +calls=10 0 +0 4826 +0 120 +cfn=(1712) std::basic_ios >::clear(std::_Ios_Iostate) +calls=10 0 +0 80 +0 50 + +fn=(2316) +0 160 +cfn=(1832) +calls=10 0 +0 280 +0 2085 +cfn=(1860) std::basic_stringbuf, std::allocator >::underflow() +calls=1 0 +0 16 +0 71 +cfn=(1860) +calls=9 0 +0 144 +0 45 + +fn=(2438) std::string::compare(std::string const&) const +0 11657220930 + +fn=(2546) std::num_get > >::do_get(std::istreambuf_iterator >, std::istreambuf_iterator >, std::ios_base&, std::_Ios_Iostate&, unsigned long&) const +0 10 +cfn=(2552) std::istreambuf_iterator > std::num_get > >::_M_extract_int(std::istreambuf_iterator >, std::istreambuf_iterator >, std::ios_base&, std::_Ios_Iostate&, unsigned long&) const +calls=1 0 +0 417 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1921 +0 2 + +fn=(2758) std::ostreambuf_iterator > std::num_put > >::_M_insert_int(std::ostreambuf_iterator >, std::ios_base&, char, unsigned long) const +0 7150 +cfn=(1832) +calls=325 0 +0 9100 +0 6825 +cfn=(2724) 0x00000000000874e0 +calls=325 0 +0 7093 +0 7474 +cfn=(3128) __gnu_cxx::stdio_sync_filebuf >::xsputn(char const*, long) +calls=1 0 +0 247 +cfn=(1514) +calls=324 0 +0 128121 +0 5547 + +fn=(2834) std::_Rb_tree_decrement(std::_Rb_tree_node_base const*) +0 904 +cfn=(2840) std::_Rb_tree_decrement(std::_Rb_tree_node_base*) +calls=904 0 +0 13728 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1313 + +fn=(2846) std::_Rb_tree_increment(std::_Rb_tree_node_base const*) +0 10312467 +cfn=(2852) +calls=10312467 0 +0 141485262 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1247 + +fn=(296) 0x00000000000ac590 +0 49 + +fn=(532) std::locale::facet::_S_create_c_locale(__locale_struct*&, char const*, __locale_struct*) +0 4 +cob=(4) +cfi=(61) /build/buildd/eglibc-2.11.1/locale/newlocale.c +cfn=(538) newlocale +calls=1 46 +0 42 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1796 +0 5 + +fn=(544) std::locale::_Impl::_M_install_facet(std::locale::id const*, std::locale::facet const*) +0 364 +cfn=(550) +calls=28 0 +0 392 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1024 +0 6328 + +fn=(634) +0 100 +cob=(4) +cfi=(68) /build/buildd/eglibc-2.11.1/wctype/wctype_l.c +cfn=(640) wctype_l +calls=1 28 +0 134 +0 13 +cob=(4) +cfi=(68) +cfn=(640) +calls=1 28 +0 254 +0 17 +cob=(4) +cfi=(68) +cfn=(640) +calls=1 28 +0 387 +0 3 +cob=(4) +cfi=(68) +cfn=(640) +calls=1 28 +0 230 +0 3 +cob=(4) +cfi=(68) +cfn=(640) +calls=1 28 +0 350 +0 3 +cob=(4) +cfi=(68) +cfn=(640) +calls=1 28 +0 98 +0 3 +cob=(4) +cfi=(68) +cfn=(640) +calls=1 28 +0 171 +0 3 +cob=(4) +cfi=(68) +cfn=(640) +calls=1 28 +0 74 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1796 +0 3 +cob=(4) +cfi=(68) +cfn=(640) +calls=1 28 +0 164 + +fn=(654) std::numpunct::_M_initialize_numpunct(__locale_struct*) +0 345 + +fn=(672) std::__timepunct::__timepunct(std::__timepunct_cache*, unsigned long) +0 13 +cfn=(512) +calls=1 0 +0 2 +0 4 +cfn=(678) +calls=1 0 +0 112 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1409 +0 3 + +fn=(688) 0x000000000006a230 +0 38054 +cfn=(696) __cxa_guard_acquire +calls=1 0 +0 24 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 980 +0 6 +cfn=(708) __cxa_guard_release +calls=1 0 +0 5 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1056 +0 1 + +fn=(746) +0 37800 + +fn=(786) std::num_put > > const& std::use_facet > > >(std::locale const&) +0 6972 +cfn=(550) +calls=1743 0 +0 8715 +0 19173 +cfn=(764) +calls=1743 0 +0 102837 +0 6972 + +fn=(840) +0 16 +cfn=(550) +calls=4 0 +0 20 +0 44 +cfn=(764) +calls=4 0 +0 236 +0 16 + +fn=(1174) operator delete(void*) +0 29623820190 +cob=(4) +cfi=(71) /build/buildd/eglibc-2.11.1/malloc/malloc.c +cfn=(1180) free +calls=9874606730 3692 +0 770221890094 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1642 + +fn=(1384) +0 35376 +cfn=(1390) std::string::_Rep::_M_clone(std::allocator const&, unsigned long) +calls=2211 0 +0 430895 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1075 +0 24075 +cfn=(1310) +calls=12 0 +0 984 +0 4164 + +fn=(1406) std::string::append(std::string const&) +0 7584 +cfn=(1384) +calls=350 0 +0 78225 +0 2208 +cob=(4) +cfi=(81) +cfn=(966) +calls=39 56 +0 1111 +0 4923 + +fn=(1448) 0x00000000000a8b30 +0 24789 +cfn=(952) std::string::_Rep::_S_create(unsigned long, unsigned long, std::allocator const&) +calls=1651 0 +0 223759 +0 11716 +cob=(4) +cfi=(81) +cfn=(966) +calls=1278 56 +0 40326 +0 17659 + +fn=(1468) std::basic_string, std::allocator >::~basic_string() +0 24146393518 +cfn=(1310) +calls=687160390 0 +0 56347152232 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1077 +0 8967712350 + +fn=(1540) +0 2640 +cfn=(1448) +calls=330 0 +0 54696 +0 1320 + +fn=(1568) +0 11200 + +fn=(1574) std::string::assign(char const*, unsigned long) +0 240 +cfn=(1580) +calls=11 0 +0 3819 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1076 + +fn=(1638) std::__basic_file::is_open() const +0 168 + +fn=(1738) std::basic_filebuf >::underflow() +0 396 +cfn=(1740) +calls=11 0 +0 22 +0 66 +cfn=(1746) std::__basic_file::xsgetn(char*, long) +calls=11 0 +0 4830 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1121 +0 36 +cfn=(1706) +calls=1 0 +0 15 +0 53 +cfn=(1706) +calls=10 0 +0 160 +0 70 + +fn=(1952) std::__basic_file::close() +0 55 +cfn=(1638) +calls=11 0 +0 33 +0 109 +cob=(4) +cfi=(96) /build/buildd/eglibc-2.11.1/csu/errno-loc.c +cfn=(1356) __errno_location +calls=7 34 +0 21 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1834 +0 28 +cob=(4) +cfi=(115) /build/buildd/eglibc-2.11.1/libio/iofclose.c +cfn=(1962) fclose@@GLIBC_2.2.5 +calls=7 43 +0 3834 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1698 +0 35 + +fn=(2232) std::string::compare(unsigned long, unsigned long, char const*) const +0 48 +cob=(4) +cfi=(69) +cfn=(642) +calls=3 26 +0 66 +0 119 + +fn=(2348) std::istream& std::istream::_M_extract(float&) +0 2331 +cfn=(1736) +calls=259 0 +0 12432 +0 5957 +cfn=(2350) std::num_get > >::do_get(std::istreambuf_iterator >, std::istreambuf_iterator >, std::ios_base&, std::_Ios_Iostate&, float&) const +calls=259 0 +0 393742 +0 3108 +cfn=(1712) +calls=259 0 +0 2072 +0 1295 + +fn=(3346) std::_Rb_tree_rotate_right(std::_Rb_tree_node_base*, std::_Rb_tree_node_base*&) +0 9608 + +fn=(3414) std::basic_filebuf >::seekpos(std::fpos<__mbstate_t>, std::_Ios_Openmode) +0 20 +cfn=(1638) +calls=2 0 +0 6 +0 22 +cfn=(3420) std::basic_filebuf >::_M_seek(long, std::_Ios_Seekdir, __mbstate_t) +calls=2 0 +0 3163 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1527 +0 12 + +fn=(3592) +0 32 +cob=(4) +cfi=(104) /build/buildd/eglibc-2.11.1/io/../sysdeps/unix/syscall-template.S +cfn=(3176) write +calls=2 82 +0 14 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1665 +0 32 +cfn=(1752) std::__basic_file::fd() +calls=2 0 +0 18 +0 14 + +fn=(282) 0x00000000000c9500 +0 11 + +fn=(292) 0x00000000000c8ea0 +0 52 + +fn=(368) 0x00000000000639f0 +0 1 + +fn=(492) std::locale::locale() +0 19026 +cfn=(494) 0x000000000006c5c0 +calls=3171 0 +0 89969 +0 3171 +cfn=(688) +calls=3171 0 +0 40126 +0 38052 + +fn=(518) std::ctype::ctype(unsigned short const*, bool, unsigned long) +0 14 +cfn=(524) +calls=1 0 +0 3244 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1149 +0 94 + +fn=(526) 0x0000000000069060 +0 4 +cfn=(532) +calls=1 0 +0 1847 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1384 + +fn=(722) +0 41354 +cfn=(492) +calls=713 0 +0 27807 + +fn=(758) bool std::has_facet >(std::locale const&) +0 6972 +cfn=(550) +calls=1743 0 +0 8715 +0 19173 +cfn=(764) +calls=1743 0 +0 163842 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 959 +0 6972 + +fn=(778) bool std::has_facet > > >(std::locale const&) +0 6972 +cfn=(550) +calls=1743 0 +0 8715 +0 19173 +cfn=(764) +calls=1743 0 +0 102837 +0 6972 + +fn=(780) __cxxabiv1::__si_class_type_info::__do_dyncast(long, __cxxabiv1::__class_type_info::__sub_kind, __cxxabiv1::__class_type_info const*, void const*, __cxxabiv1::__class_type_info const*, void const*, __cxxabiv1::__class_type_info::__dyncast_result&) const +0 119238 + +fn=(828) +0 16 +cfn=(550) +calls=4 0 +0 20 +0 44 +cfn=(764) +calls=4 0 +0 236 +0 16 + +fn=(1608) +0 153 +cfn=(492) +calls=9 0 +0 351 +0 99 +cfn=(1614) +calls=9 0 +0 27 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1219 +0 180 +cfn=(1620) +calls=9 0 +0 747 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1302 +0 36 +cfn=(1626) std::codecvt const& std::use_facet >(std::locale const&) +calls=9 0 +0 747 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1337 +0 45 + +fn=(1626) +0 36 +cfn=(550) +calls=9 0 +0 45 +0 99 +cfn=(764) +calls=9 0 +0 531 +0 36 + +fn=(1788) std::string::find(char, unsigned long) const +0 5320 +cob=(4) +cfi=(89) +cfn=(1252) +calls=532 25 +0 17233 +0 2660 + +fn=(2282) std::string::find_first_of(char const*, unsigned long, unsigned long) const +0 240 +cob=(4) +cfi=(89) +cfn=(1252) +calls=10 25 +0 220 +0 232 +cob=(4) +cfi=(89) +cfn=(1252) +calls=58 25 +0 1387 +0 471 + +fn=(2788) std::num_put > >::do_put(std::ostreambuf_iterator >, std::ios_base&, char, unsigned long) const +0 1620 +cfn=(2758) +calls=324 0 +0 170831 +0 1296 + +fn=(3288) std::ostreambuf_iterator > std::num_put > >::_M_insert_float(std::ostreambuf_iterator >, std::ios_base&, char, char, double) const +0 130 +cfn=(1832) +calls=5 0 +0 140 +0 45 +cfn=(3294) +calls=5 0 +0 135 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1309 +0 15 +cfn=(524) +calls=5 0 +0 35 +0 50 +cfn=(3296) 0x0000000000089420 +calls=5 0 +0 10202 +0 25 +cfn=(772) +calls=5 0 +0 590 +0 85 +cob=(4) +cfi=(89) +cfn=(1252) +calls=5 25 +0 113 +0 107 +cfn=(1514) +calls=5 0 +0 2046 +0 105 +cob=(4) +cfi=(81) +cfn=(966) +calls=5 56 +0 97 +0 5 + +fn=(3296) +0 95 +cob=(4) +cfi=(62) +cfn=(610) +calls=5 32 +0 105 +0 60 +cob=(4) +cfi=(138) /build/buildd/eglibc-2.11.1/libio/vsnprintf.c +cfn=(3306) vsnprintf +calls=5 101 +0 8058 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1729 +0 15 +cob=(4) +cfi=(62) +cfn=(610) +calls=5 32 +0 105 +0 35 + +fn=(524) +0 3751 +cfn=(526) +calls=1 0 +0 3235 +0 3 + +fn=(568) std::moneypunct::_M_initialize_moneypunct(__locale_struct*, char const*) +0 112 + +fn=(728) +0 10458 +cfn=(734) std::ios_base::_M_init() +calls=1743 0 +0 155355 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1040 +0 5229 +cfn=(752) std::basic_ios >::_M_cache_locale(std::locale const&) +calls=1743 0 +0 1052048 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1416 +0 22659 + +fn=(764) +0 283716 +cfn=(780) +calls=7014 0 +0 119238 +cfn=(766) __cxxabiv1::__vmi_class_type_info::__do_dyncast(long, __cxxabiv1::__class_type_info::__sub_kind, __cxxabiv1::__class_type_info const*, void const*, __cxxabiv1::__class_type_info const*, void const*, __cxxabiv1::__class_type_info::__dyncast_result&) const +calls=3494 0 +0 181688 +0 157620 + +fn=(942) +0 10328107697 +cfn=(952) +calls=688540511 0 +0 89003761721 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1077 +0 5508323960 +cob=(4) +cfi=(81) +cfn=(966) +calls=688540479 56 +0 15492521052 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1708 +0 6885405246 + +fn=(952) +0 9639619826 +cfn=(880) operator new(unsigned long) +calls=450 0 +0 51673 +0 688543984 +cfn=(880) +calls=688543984 0 +0 75921937168 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 869 +0 2754177736 + +fn=(1506) std::basic_ostream >& std::__ostream_insert >(std::basic_ostream >&, char const*, long) +0 6706 +cfn=(1512) +calls=479 0 +0 10059 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1011 +0 15328 +cfn=(3572) std::basic_filebuf >::xsputn(char const*, long) +calls=470 0 +0 48844 +cfn=(3128) +calls=1 0 +0 2675 +cfn=(1514) +calls=8 0 +0 4049 +0 1437 + +fn=(1632) std::basic_filebuf >::open(char const*, std::_Ios_Openmode) +0 132 +cfn=(1638) +calls=12 0 +0 36 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1129 +0 156 +cfn=(1644) std::__basic_file::open(char const*, std::_Ios_Openmode, int) +calls=12 0 +0 10039 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1249 +0 24 +cfn=(1688) std::basic_filebuf >::is_open() const +calls=12 0 +0 96 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1351 +0 48 +cfn=(1694) std::basic_filebuf >::_M_allocate_internal_buffer() +calls=12 0 +0 17912 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1481 +0 72 +cfn=(1706) +calls=12 0 +0 180 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1395 +0 84 + +fn=(1694) +0 96 +cfn=(1700) operator new[](unsigned long) +calls=12 0 +0 16891 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 877 +0 48 + +fn=(1746) +0 110 +cfn=(1752) +calls=11 0 +0 1781 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1059 +0 44 +cob=(4) +cfi=(104) +cfn=(1764) read +calls=11 82 +0 77 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1649 +0 110 + +fn=(1752) +0 30 +cob=(4) +cfi=(107) /build/buildd/eglibc-2.11.1/libio/fileno.c +cfn=(1758) fileno +calls=15 37 +0 105 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1682 + +fn=(1830) +0 8336 +cfn=(1832) +calls=521 0 +0 14588 +0 220534 +cfn=(1892) 0x000000000008a190 +calls=196 0 +0 5488 +0 784 +cfn=(1904) +calls=196 0 +0 2352 +0 13897 +cfn=(1860) +calls=11 0 +0 176 +0 2079 +cfn=(1860) +calls=324 0 +0 6618 +0 1620 + +fn=(1860) +0 2880 +cfn=(1866) std::basic_stringbuf, std::allocator >::_M_update_egptr() +calls=360 0 +0 1800 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1434 +0 1080 + +fn=(1892) +0 5488 + +fn=(1934) std::basic_filebuf >::_M_terminate_output() +0 270 + +fn=(1940) std::basic_filebuf >::_M_destroy_internal_buffer() +0 56 +cfn=(1946) operator delete[](void*) +calls=7 0 +0 816 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 888 +0 77 + +fn=(2750) std::ostream& std::ostream::_M_insert(void const*) +0 13 +cfn=(1512) +calls=1 0 +0 21 +0 21 +cfn=(2752) std::num_put > >::do_put(std::ostreambuf_iterator >, std::ios_base&, char, void const*) const +calls=1 0 +0 2496 +0 32 + +fn=(3128) +0 10 +cob=(4) +cfi=(131) /build/buildd/eglibc-2.11.1/libio/iofwrite.c +cfn=(3134) fwrite +calls=2 37 +0 1187 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1725 + +fn=(3164) +0 8 +cob=(4) +cfi=(134) /build/buildd/eglibc-2.11.1/libio/putc.c +cfn=(3170) putc +calls=1 29 +0 181 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1665 + +fn=(3426) std::__basic_file::seekoff(long, std::_Ios_Seekdir) +0 12 +cfn=(1752) +calls=2 0 +0 18 +0 14 +cob=(4) +cfi=(120) /build/buildd/eglibc-2.11.1/misc/../sysdeps/unix/syscall-template.S +cfn=(3432) lseek +calls=2 82 +0 14 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1721 + +fn=(3550) std::basic_ofstream >::basic_ofstream() +0 20 +cfn=(722) +calls=2 0 +0 194 +0 42 +cfn=(728) +calls=2 0 +0 1416 +0 16 +cfn=(1608) +calls=2 0 +0 530 +0 6 +cfn=(728) +calls=2 0 +0 1416 +0 14 + +fn=(2840) +0 15890 + +fn=(3282) std::num_put > >::do_put(std::ostreambuf_iterator >, std::ios_base&, char, double) const +0 30 +cfn=(3288) +calls=5 0 +0 15234 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1759 +0 20 + +fn=(272) 0x000000000005a540 +0 6 + +fn=(512) +0 10 + +fn=(562) std::numpunct::_M_initialize_numpunct(__locale_struct*) +0 410 + +fn=(708) +0 5 + +fn=(822) +0 16 +cfn=(550) +calls=4 0 +0 20 +0 44 +cfn=(764) +calls=4 0 +0 236 +0 16 + +fn=(1246) std::string::find_last_of(char const*, unsigned long, unsigned long) const +0 448 +cob=(4) +cfi=(89) +cfn=(1252) +calls=50 25 +0 1158 +0 44 +cob=(4) +cfi=(89) +cfn=(1252) +calls=11 25 +0 266 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1682 +0 353 + +fn=(1258) std::basic_string, std::allocator >::basic_string(std::string const&) +0 20744681394 +cfn=(1390) +calls=24 0 +0 4762 +0 6914893136 + +fn=(1390) +0 24585 +cfn=(952) +calls=2235 0 +0 340380 +0 37713 +cob=(4) +cfi=(81) +cfn=(966) +calls=1047 56 +0 30885 +0 2094 + +fn=(1512) +0 17157 + +fn=(1646) 0x00000000000c8480 +0 120 + +fn=(1724) std::ctype::do_widen(char) const +0 2 + +fn=(1946) +0 7 +cfn=(1174) +calls=7 0 +0 809 + +fn=(2256) std::string::resize(unsigned long, char) +0 1272 +cfn=(1378) std::string::append(unsigned long, char) +calls=106 0 +0 27617 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 958 + +fn=(2350) +0 5957 +cfn=(1384) +calls=259 0 +0 46620 +0 2849 +cfn=(1830) +calls=259 0 +0 136740 +0 1813 +cfn=(524) +calls=259 0 +0 1813 +0 1554 +cfn=(2356) void std::__convert_to_v(char const*, float&, std::_Ios_Iostate&, __locale_struct* const&) +calls=259 0 +0 163349 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1443 +0 9071 +cfn=(1310) +calls=259 0 +0 21238 +0 1295 + +fn=(2426) std::_Rb_tree_insert_and_rebalance(bool, std::_Rb_tree_node_base*, std::_Rb_tree_node_base*, std::_Rb_tree_node_base&) +0 19967502462 +cfn=(2444) std::_Rb_tree_rotate_left(std::_Rb_tree_node_base*, std::_Rb_tree_node_base*&) +calls=238 0 +0 3831 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1327 +0 610 +cfn=(2444) +calls=122 0 +0 1971 +0 7503 +cfn=(3346) +calls=228 0 +0 3697 +0 1170 +cfn=(3346) +calls=234 0 +0 3821 +0 1290 +cfn=(3346) +calls=122 0 +0 2090 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1310 +0 2409930493 +cfn=(2444) +calls=234 0 +0 4008 +0 468 + +fn=(2532) std::basic_istream >& std::operator>>, std::allocator >(std::basic_istream >&, std::basic_string, std::allocator >&) +0 42 +cfn=(1736) +calls=3 0 +0 144 +0 54 +cfn=(1586) +calls=3 0 +0 114 +0 36 +cfn=(2538) std::locale::locale(std::locale const&) +calls=3 0 +0 18 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1013 +0 6 +cfn=(772) +calls=3 0 +0 354 +0 9 +cfn=(746) +calls=3 0 +0 36 +0 108 +cfn=(1772) std::string::append(char const*, unsigned long) +calls=3 0 +0 672 +0 78 + +fn=(2538) +0 18 + +fn=(3420) +0 22 +cfn=(1934) +calls=2 0 +0 60 +0 26 +cfn=(3426) +calls=2 0 +0 1779 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1240 +0 36 + +fn=(3482) std::istream::read(char*, long) +0 1272 +cfn=(1736) +calls=106 0 +0 3392 +0 1590 +cfn=(3484) std::basic_filebuf >::xsgetn(char*, long) +calls=106 0 +0 12423 +0 318 + +fn=(3492) std::basic_streambuf >::uflow() +0 8 +cfn=(1738) +calls=2 0 +0 230 +0 16 + +fn=(3580) std::basic_filebuf >::sync() +0 20 +cfn=(3578) +calls=2 0 +0 4521 +0 4 + +fn=(3280) std::ostream& std::ostream::_M_insert(double) +0 60 +cfn=(1512) +calls=5 0 +0 105 +0 105 +cfn=(3282) +calls=5 0 +0 17043 +0 155 + +fn=(266) 0x000000000005a4a0 +0 6 + +fn=(278) 0x00000000000d1200 +0 11 +cfn=(282) +calls=1 0 +0 11 +0 16 +cfn=(372) 0x000000000005c2d0 +calls=1 0 +0 57 +cfn=(370) 0x000000000005fef0 +calls=1 0 +0 1 +cfn=(368) +calls=1 0 +0 1 +cfn=(348) 0x0000000000072400 +calls=1 0 +0 1917 +cfn=(322) 0x0000000000087050 +calls=1 0 +0 49 +cfn=(296) +calls=1 0 +0 49 +cfn=(294) 0x00000000000c3ba0 +calls=1 0 +0 1 +cfn=(292) +calls=1 0 +0 52 +0 31 + +fn=(348) +0 8 +cob=(4) +cfi=(56) /build/buildd/eglibc-2.11.1/stdlib/cxa_atexit.c +cfn=(362) __cxa_atexit +calls=1 57 +0 62 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1778 +0 7 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 + +fn=(486) std::ios_base::Init::Init() +0 2124 +cfn=(492) +calls=1 0 +0 66714 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 952 +0 16 +cfn=(492) +calls=1 0 +0 39 +0 14 +cfn=(492) +calls=1 0 +0 39 +0 6 +cfn=(722) +calls=1 0 +0 97 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 970 +0 15 +cfn=(728) +calls=1 0 +0 14869 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1451 +0 3 +cfn=(722) +calls=1 0 +0 97 +0 16 +cfn=(728) +calls=1 0 +0 708 +0 3 +cfn=(722) +calls=1 0 +0 97 +0 14 +cfn=(728) +calls=1 0 +0 708 +0 3 +cfn=(722) +calls=1 0 +0 97 +0 14 +cfn=(728) +calls=1 0 +0 708 +0 16 +cfn=(492) +calls=1 0 +0 39 +0 16 +cfn=(492) +calls=1 0 +0 39 +0 14 +cfn=(492) +calls=1 0 +0 39 +0 6 +cfn=(722) +calls=1 0 +0 97 +0 15 +cfn=(804) std::basic_ios >::init(std::basic_streambuf >*) +calls=1 0 +0 10843 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1453 +0 3 +cfn=(722) +calls=1 0 +0 97 +0 16 +cfn=(804) +calls=1 0 +0 638 +0 3 +cfn=(722) +calls=1 0 +0 97 +0 14 +cfn=(804) +calls=1 0 +0 638 +0 3 +cfn=(722) +calls=1 0 +0 97 +0 14 +cfn=(804) +calls=1 0 +0 638 +0 562 + +fn=(494) +0 5 +cfn=(506) std::locale::_Impl::_Impl(unsigned long) +calls=1 0 +0 63584 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1006 +0 25374 + +fn=(574) std::moneypunct::_M_initialize_moneypunct(__locale_struct*, char const*) +0 112 + +fn=(592) std::messages::messages(unsigned long) +0 11 +cfn=(524) +calls=1 0 +0 7 +0 2 +cfn=(512) +calls=1 0 +0 2 +0 4 + +fn=(648) std::codecvt::codecvt(unsigned long) +0 11 +cfn=(524) +calls=1 0 +0 7 +0 4 + +fn=(666) std::moneypunct::_M_initialize_moneypunct(__locale_struct*, char const*) +0 101 + +fn=(734) +0 15723 +cfn=(492) +calls=1747 0 +0 68133 +0 5241 +cfn=(740) std::locale::operator=(std::locale const&) +calls=1747 0 +0 33193 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 995 +0 3494 +cfn=(746) +calls=1747 0 +0 20964 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 976 +0 6988 + +fn=(752) +0 12201 +cfn=(758) +calls=1743 0 +0 206633 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1190 +0 6972 +cfn=(772) +calls=1743 0 +0 205674 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1219 +0 5229 +cfn=(778) +calls=1743 0 +0 144669 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1580 +0 6972 +cfn=(786) +calls=1743 0 +0 144669 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1599 +0 5229 +cfn=(792) +calls=1743 0 +0 144669 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1572 +0 6972 +cfn=(798) std::num_get > > const& std::use_facet > > >(std::locale const&) +calls=1743 0 +0 144669 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1615 +0 8715 + +fn=(798) +0 6972 +cfn=(550) +calls=1743 0 +0 8715 +0 19173 +cfn=(764) +calls=1743 0 +0 102837 +0 6972 + +fn=(880) +0 88921194984 +cob=(4) +cfi=(71) +cfn=(886) malloc +calls=9880132776 3615 +0 939669252630 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1742 +0 59280796656 + +fn=(1298) std::string::compare(unsigned long, unsigned long, char const*, unsigned long) const +0 5715 + +fn=(1310) +0 687163171 +cfn=(1174) +calls=687163171 0 +0 55660225516 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 870 + +fn=(1378) +0 3270 +cfn=(1384) +calls=109 0 +0 21616 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 950 +0 863 +cob=(4) +cfi=(82) /build/buildd/eglibc-2.11.1/string/../sysdeps/x86_64/memset.S +cfn=(986) memset +calls=106 44 +0 1917 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1690 +0 551 + +fn=(1522) std::string::swap(std::string&) +0 3663 + +fn=(1550) std::basic_stringstream, std::allocator >::~basic_stringstream() +0 7776 +cfn=(746) +calls=324 0 +0 3888 +0 6804 +cfn=(1556) +calls=324 0 +0 21182 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 994 +0 3240 +cfn=(1310) +calls=324 0 +0 34491 +0 1620 + +fn=(1562) +0 8400 + +fn=(1736) +0 29214 +cfn=(1712) +calls=61 0 +0 488 +0 11722 + +fn=(1740) +0 966 + +fn=(1812) std::basic_string, std::allocator >::basic_string(char const*, unsigned long, std::allocator const&) +0 2904 +cfn=(942) +calls=363 0 +0 67448 +0 1452 + +fn=(2056) std::string::rfind(char, unsigned long) const +0 98 + +fn=(2552) +0 16 +cfn=(1832) +calls=1 0 +0 28 +0 352 +cfn=(1860) +calls=1 0 +0 16 +0 5 + +fn=(2722) std::ostreambuf_iterator > std::num_put > >::_M_insert_int(std::ostreambuf_iterator >, std::ios_base&, char, long) const +0 110 +cfn=(1832) +calls=5 0 +0 140 +0 125 +cfn=(2724) +calls=5 0 +0 153 +0 140 +cfn=(1514) +calls=5 0 +0 905 +0 85 + +fn=(3186) std::ostream::flush() +0 30 +cfn=(3580) +calls=2 0 +0 4545 +cfn=(3188) __gnu_cxx::stdio_sync_filebuf >::sync() +calls=1 0 +0 1745 +0 21 + +fn=(3188) +0 2 +cob=(4) +cfi=(135) /build/buildd/eglibc-2.11.1/libio/iofflush.c +cfn=(3194) fflush +calls=1 36 +0 54 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1689 + +fn=(3452) std::istream::get(char*, long, char) +0 60 +cfn=(1736) +calls=4 0 +0 128 +0 3256 +cfn=(1738) +calls=4 0 +0 460 +0 8 + +fn=(3490) std::basic_streambuf >::xsgetn(char*, long) +0 1924 +cfn=(3492) +calls=2 0 +0 254 +0 1816 +cob=(4) +cfi=(81) +cfn=(966) +calls=106 56 +0 2880 +0 530 + +fn=(3572) +0 6580 +cfn=(1740) +calls=470 0 +0 940 +0 11758 +cfn=(1514) +calls=470 0 +0 28256 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1310 + +fn=(3612) std::basic_ifstream >::close() +0 12 +cfn=(1928) std::basic_filebuf >::close() +calls=3 0 +0 1977 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1272 +0 12 + +fn=(506) +0 217 +cfn=(512) +calls=1 0 +0 2 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1153 +0 56 +cfn=(518) +calls=1 0 +0 4501 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1014 +0 4 +cfn=(544) +calls=1 0 +0 1277 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1354 +0 3 +cfn=(556) std::codecvt::codecvt(unsigned long) +calls=1 0 +0 22 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1130 +0 4 +cfn=(544) +calls=1 0 +0 253 +0 23 +cfn=(562) +calls=1 0 +0 410 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1356 +0 5 +cfn=(544) +calls=1 0 +0 253 +0 8 +cfn=(544) +calls=1 0 +0 253 +0 8 +cfn=(544) +calls=1 0 +0 253 +0 5 +cfn=(524) +calls=1 0 +0 7 +0 5 +cfn=(544) +calls=1 0 +0 253 +0 35 +cfn=(568) +calls=1 0 +0 112 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1464 +0 5 +cfn=(544) +calls=1 0 +0 253 +0 35 +cfn=(574) +calls=1 0 +0 112 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1464 +0 5 +cfn=(544) +calls=1 0 +0 253 +0 8 +cfn=(544) +calls=1 0 +0 253 +0 8 +cfn=(544) +calls=1 0 +0 253 +0 56 +cfn=(580) +calls=1 0 +0 1537 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1273 +0 5 +cfn=(544) +calls=1 0 +0 253 +0 8 +cfn=(544) +calls=1 0 +0 253 +0 8 +cfn=(544) +calls=1 0 +0 253 +0 3 +cfn=(592) +calls=1 0 +0 26 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1020 +0 4 +cfn=(544) +calls=1 0 +0 253 +0 3 +cfn=(598) std::ctype::ctype(unsigned long) +calls=1 0 +0 25803 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 978 +0 4 +cfn=(544) +calls=1 0 +0 253 +0 3 +cfn=(648) +calls=1 0 +0 22 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1148 +0 4 +cfn=(544) +calls=1 0 +0 253 +0 23 +cfn=(654) +calls=1 0 +0 345 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1372 +0 4 +cfn=(544) +calls=1 0 +0 253 +0 8 +cfn=(544) +calls=1 0 +0 253 +0 8 +cfn=(544) +calls=1 0 +0 253 +0 5 +cfn=(524) +calls=1 0 +0 7 +0 5 +cfn=(544) +calls=1 0 +0 253 +0 35 +cfn=(660) std::moneypunct::_M_initialize_moneypunct(__locale_struct*, char const*) +calls=1 0 +0 101 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1464 +0 4 +cfn=(544) +calls=1 0 +0 253 +0 35 +cfn=(666) +calls=1 0 +0 101 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1472 +0 4 +cfn=(544) +calls=1 0 +0 253 +0 8 +cfn=(544) +calls=1 0 +0 253 +0 8 +cfn=(544) +calls=1 0 +0 253 +0 56 +cfn=(672) +calls=1 0 +0 1543 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1291 +0 4 +cfn=(544) +calls=1 0 +0 253 +0 8 +cfn=(544) +calls=1 0 +0 253 +0 8 +cfn=(544) +calls=1 0 +0 253 +0 3 +cfn=(684) +calls=1 0 +0 26 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 996 +0 4 +cfn=(544) +calls=1 0 +0 253 +0 3 +cfn=(550) +calls=1 0 +0 5 +0 5 +cfn=(550) +calls=1 0 +0 5 +0 5 +cfn=(550) +calls=1 0 +0 5 +0 5 +cfn=(550) +calls=1 0 +0 5 +0 5 +cfn=(550) +calls=1 0 +0 5 +0 5 +cfn=(550) +calls=1 0 +0 5 +0 5 +cfn=(550) +calls=1 0 +0 5 +0 5 +cfn=(550) +calls=1 0 +0 5 +0 10 + +fn=(598) +0 11 +cfn=(524) +calls=1 0 +0 7 +0 4 +cfn=(604) +calls=1 0 +0 24611 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1167 +0 3 + +fn=(660) +0 101 + +fn=(766) +0 181688 + +fn=(804) +0 24 +cfn=(734) +calls=4 0 +0 352 +0 12 +cfn=(810) +calls=4 0 +0 10877 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1440 +0 52 + +fn=(816) +0 16 +cfn=(550) +calls=4 0 +0 20 +0 44 +cfn=(764) +calls=4 0 +0 236 +0 16 + +fn=(846) +0 16 +cfn=(550) +calls=4 0 +0 20 +0 44 +cfn=(764) +calls=4 0 +0 236 +0 16 + +fn=(1446) std::basic_string, std::allocator >::basic_string(std::string const&, unsigned long, unsigned long) +0 22508 +cfn=(1448) +calls=1324 0 +0 263553 +0 5296 + +fn=(1586) +0 5604 +cfn=(952) +calls=34 0 +0 4977 +0 4448 +cfn=(1310) +calls=1 0 +0 82 +0 101 + +fn=(1688) +0 36 +cfn=(1638) +calls=12 0 +0 36 +0 24 + +fn=(1712) +0 3520 + +fn=(1772) +0 27600 +cfn=(1384) +calls=888 0 +0 214712 +0 6474 +cob=(4) +cfi=(81) +cfn=(966) +calls=549 56 +0 18381 +0 5585 + +fn=(1866) +0 1800 + +fn=(2544) std::istream& std::istream::_M_extract(unsigned long&) +0 9 +cfn=(1736) +calls=1 0 +0 65 +0 23 +cfn=(2546) +calls=1 0 +0 2350 +0 12 +cfn=(1712) +calls=1 0 +0 8 +0 5 + +fn=(2570) std::basic_istringstream, std::allocator >::~basic_istringstream() +0 22 +cfn=(746) +calls=1 0 +0 12 +0 12 +cfn=(1556) +calls=1 0 +0 58 +0 10 +cfn=(1310) +calls=1 0 +0 82 +0 5 + +fn=(2714) std::ostream& std::ostream::_M_insert(long) +0 65 +cfn=(1512) +calls=5 0 +0 105 +0 86 +cfn=(2716) std::num_put > >::do_put(std::ostreambuf_iterator >, std::ios_base&, char, long) const +calls=3 0 +0 622 +0 22 +cfn=(2716) +calls=2 0 +0 2821 +0 124 + +fn=(2716) +0 25 +cfn=(2722) +calls=5 0 +0 1658 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1740 +0 20 + +fn=(2724) +0 7246 + +fn=(2752) +0 13 +cfn=(2758) +calls=1 0 +0 726 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1750 +0 7 + +fn=(3412) std::istream::seekg(std::fpos<__mbstate_t>) +0 40 +cfn=(3414) +calls=2 0 +0 4750 +0 16 + +fn=(3484) +0 2650 +cfn=(3490) +calls=106 0 +0 7404 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1309 +0 1060 + +fn=(294) +0 1 + +fn=(322) +0 49 + +fn=(370) +0 1 + +fn=(372) +0 57 + +fn=(556) +0 11 +cfn=(524) +calls=1 0 +0 7 +0 4 + +fn=(586) +0 10 +cfn=(524) +calls=1 0 +0 7 +0 97 + +fn=(696) +0 24 + +fn=(740) +0 33193 + +fn=(834) +0 16 +cfn=(550) +calls=4 0 +0 20 +0 44 +cfn=(764) +calls=4 0 +0 236 +0 16 + +fn=(1264) +0 12937579 +cfn=(1310) +calls=353 0 +0 28946 +0 6278 + +fn=(1500) std::basic_ostream >& std::operator<< >(std::basic_ostream >&, char const*) +0 2124 +cob=(4) +cfi=(69) +cfn=(642) +calls=236 26 +0 3782 +0 944 +cfn=(1506) +calls=236 0 +0 42750 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1522 +0 1180 + +fn=(1516) +0 12654 +cfn=(1384) +calls=333 0 +0 85333 +0 6327 +cfn=(1522) +calls=333 0 +0 3663 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 999 +0 2331 +cfn=(1528) std::basic_stringbuf, std::allocator >::_M_sync(char*, unsigned long, unsigned long) +calls=333 0 +0 9320 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1372 +0 1332 + +fn=(1528) +0 16943 + +fn=(1644) +0 96 +cfn=(1646) +calls=12 0 +0 120 +0 60 +cfn=(1638) +calls=12 0 +0 36 +0 60 +cob=(4) +cfi=(101) /build/buildd/eglibc-2.11.1/libio/../sysdeps/wordsize-64/../../libio/iofopen.c +cfn=(1656) fopen@@GLIBC_2.2.5 +calls=12 107 +0 7812 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1723 +0 132 + +fn=(1700) +0 24 +cfn=(880) +calls=12 0 +0 16843 +0 24 + +fn=(1720) std::ctype::_M_widen_init() const +0 1041 +cfn=(1722) +calls=1 0 +0 121 +0 270 + +fn=(1730) std::basic_istream >& std::getline, std::allocator >(std::basic_istream >&, std::basic_string, std::allocator >&, char) +0 3390 +cfn=(1736) +calls=226 0 +0 7232 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 994 +0 768 +cfn=(1712) +calls=15 0 +0 120 +0 3390 +cfn=(1586) +calls=226 0 +0 12674 +0 7486 +cob=(4) +cfi=(89) +cfn=(1252) +calls=211 25 +0 8195 +0 1899 +cfn=(1772) +calls=211 0 +0 59666 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 994 +0 3406 +cfn=(1778) +calls=211 0 +0 1477 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1283 +0 479 +cfn=(1860) +calls=14 0 +0 224 +cfn=(1738) +calls=5 0 +0 6079 +0 151 + +fn=(1822) std::istream& std::istream::_M_extract(double&) +0 2907 +cfn=(1736) +calls=323 0 +0 17517 +0 6148 +cfn=(1824) +calls=262 0 +0 406277 +0 3449 +cfn=(1712) +calls=79 0 +0 632 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1346 +0 395 + +fn=(1842) +0 2620 +cob=(4) +cfi=(108) /build/buildd/eglibc-2.11.1/stdlib/strtod_l.c +cfn=(1848) strtod_l +calls=262 1601 +0 160524 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1788 +0 4192 + +fn=(1928) +0 56 +cfn=(1638) +calls=7 0 +0 21 +0 70 +cfn=(1934) +calls=7 0 +0 210 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1391 +0 42 +cfn=(1940) +calls=7 0 +0 1837 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1446 +0 98 +cfn=(1952) +calls=7 0 +0 7583 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1110 +0 28 + +fn=(1990) std::__basic_file::~__basic_file() +0 4 +cfn=(1952) +calls=4 0 +0 64 + +fn=(2356) +0 2590 +cob=(4) +cfi=(108) +cfn=(2362) strtof_l +calls=259 1601 +0 155113 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1770 +0 3876 + +fn=(2444) +0 9810 + +fn=(2786) std::ostream& std::ostream::_M_insert(unsigned long) +0 4212 +cfn=(1512) +calls=324 0 +0 6804 +0 6804 +cfn=(2788) +calls=324 0 +0 173747 +0 10368 + +fn=(3540) std::_Rb_tree_rebalance_for_erase(std::_Rb_tree_node_base*, std::_Rb_tree_node_base&) +0 408 + +fn=(3578) +0 74 +cfn=(3586) +calls=2 0 +0 2969 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1444 +0 10 +cfn=(1706) +calls=2 0 +0 38 +0 36 +cfn=(1706) +calls=2 0 +0 38 +0 20 + +ob=(4) +fl=(141) /build/buildd/eglibc-2.11.1/string/../sysdeps/x86_64/strchrnul.S +fn=(3312) strchrnul +27 50 ++1 50 ++1 50 ++1 50 ++1 50 ++1 50 ++1 50 ++1 50 ++1 50 ++1 50 ++1 50 ++1 50 ++1 50 ++1 50 ++1 50 ++1 50 ++1 50 ++1 50 ++1 50 ++1 50 ++12 50 ++1 50 ++1 50 + +fl=(81) +fn=(966) +56 688544694 ++2 688544694 ++2 688544694 ++3 688544627 ++1 688544627 ++2 344232586 ++1 344232586 ++2 344232586 ++1 344232586 ++5 344232586 ++1 344232586 +-1 344312041 ++1 344312041 ++2 344311084 ++1 344311084 ++2 344311084 ++1 688622168 ++5 344311084 ++1 344311084 +-1 344233543 ++1 344233543 ++2 80764 ++1 80764 ++2 80764 ++1 80764 ++5 80764 ++1 80764 +-1 688463863 ++1 688463863 ++2 688542620 ++1 688542620 ++2 688542620 ++1 688542620 ++5 688542620 ++1 688542620 +-1 2007 ++1 3625 ++5 1618 ++1 1618 ++1 1618 ++1 1618 ++2 1618 ++2 1618 ++1 1618 ++2 1618 ++8 688544627 ++8 617 ++6 617 ++2 617 ++1 617 ++3 208 ++1 416 ++5 208 ++1 208 ++2 208 ++2 208 ++1 208 ++2 208 +-8 890 ++1 890 ++2 890 ++2 890 ++1 890 ++2 1098 ++9 208 ++1 208 +-1 409 ++1 409 ++3 617 ++1 617 ++1 617 ++5 478 ++2 478 ++1 478 ++1 478 ++1 478 ++2 478 ++1 478 ++1 478 ++1 478 ++2 478 ++1 478 ++2 478 ++2 18 ++2 18 ++1 18 ++1 18 ++1 18 ++2 18 ++1 18 ++1 18 ++1 18 ++2 18 ++1 18 ++2 32 ++5 14 ++6 14 ++1 14 +-7 603 ++6 603 ++1 603 ++2 67 + +fn=(3328) mempcpy +56 9 ++4 9 ++3 9 ++1 9 ++2 9 ++1 9 ++2 9 ++1 9 ++5 9 ++1 9 ++2 8 ++1 8 ++2 8 ++1 8 ++5 8 ++1 8 +-1 1 ++1 1 ++2 8 ++1 8 ++2 8 ++1 8 ++5 8 ++1 8 +-1 1 ++1 1 ++2 8 ++1 8 ++2 8 ++1 16 ++5 8 ++1 8 +-1 1 ++1 9 ++5 8 ++1 8 ++1 8 ++1 8 ++2 8 ++2 8 ++1 8 ++2 8 ++6 9 ++4 9 + +fl=(153) /build/buildd/eglibc-2.11.1/debug/fprintf_chk.c +fn=(3934) __fprintf_chk +28 120 ++4 120 ++1 16 ++1 8 ++2 16 ++1 16 +-1 40 ++1 8 +cfi=(140) /build/buildd/eglibc-2.11.1/stdio-common/vfprintf.c +cfn=(3310) vfprintf +calls=8 210 +* 13308 ++3 8 +-3 8 ++3 8 ++1 24 +fi=(157) /build/buildd/eglibc-2.11.1/debug/../libio/libioP.h +993 8 ++1 8 +-1 8 ++1 8 ++1 88 +fe=(153) +45 40 + +fl=(73) /build/buildd/eglibc-2.11.1/malloc/arena.c +fn=(890) ptmalloc_init +467 5 ++8 3 ++1 1 +-66 1 ++2 1 ++1 1 ++1 1 ++1 1 +cfi=(74) /build/buildd/eglibc-2.11.1/misc/../sysdeps/unix/sysv/linux/getpagesize.c +cfn=(892) getpagesize +calls=1 29 +* 6 +519 1 +415 1 ++96 1 +-1 1 ++1 1 ++8 1 ++8 2 ++1 1 +-3 1 ++3 1 +-1 1 ++1 10 +cfi=(76) /build/buildd/eglibc-2.11.1/nptl/../nptl/sysdeps/unix/sysv/linux/register-atfork.c +cfn=(900) __linkin_atfork +calls=1 117 +* 9 ++11 2 ++2 6 +382 92 ++16 46 +-18 141 +622 2 ++5 2 ++1 2 ++2 1 ++1 6 +521 5 +cfi=(75) /build/buildd/eglibc-2.11.1/elf/dl-addr.c +cfn=(894) _dl_addr +calls=1 127 +* 59307 +-2 2 ++2 3 +382 5 + +fl=(89) +fn=(1252) +25 1739 ++1 1739 ++1 1739 ++1 1739 ++1 1739 ++1 1739 ++1 1739 ++1 1739 ++1 1739 ++1 1739 ++1 1739 ++1 1739 ++1 1739 ++1 1739 ++1 1739 ++1 1739 ++1 1739 ++1 1739 ++1 1302 ++1 1302 ++2 924 ++1 924 ++1 924 ++1 924 ++1 924 ++1 924 ++1 540 ++1 540 ++2 1105 ++1 1105 ++2 821 ++1 821 ++1 821 ++1 821 ++1 821 ++1 821 ++1 634 + +fl=(48) /build/buildd/eglibc-2.11.1/csu/../sysdeps/x86_64/multiarch/init-arch.c +fn=(212) __init_cpu_features +49 1 +-5 1 ++5 1 ++3 1 +-3 1 ++3 5 ++42 2 +-63 1 ++23 1 +-23 2 ++6 1 +-6 1 ++6 1 +-6 1 ++29 1 +-22 1 +-1 1 ++23 1 +-22 1 ++22 1 +-29 1 ++7 1 ++23 1 +-24 1 ++1 1 ++23 1 ++5 2 ++2 1 ++1 1 +-1 1 ++1 7 + +fl=(108) +fn=(2362) +1601 777 +cfn=(2364) ____strtof_l_internal +calls=259 416 +* 154336 + +fn=(1850) ____strtod_l_internal +416 2358 ++56 262 +-2 262 +-54 262 ++56 262 ++15 524 ++17 262 ++1 1048 +cfi=(69) +cfn=(642) +calls=262 26 +* 4192 ++22 524 +-22 262 ++22 262 +-6 262 ++6 786 ++3 524 ++1 786 ++3 524 ++5 501 ++13 786 ++1 1310 ++75 824 ++19 524 ++1 973 ++1 374 +-1 374 ++17 262 ++6 524 ++1 1160 ++6 374 ++1 748 +-7 532 ++42 2055 ++13 516 ++16 258 +-2 258 ++2 258 ++42 516 ++9 516 ++1 1102 +-1 564 ++7 188 ++1 188 +-1 188 ++1 752 ++1 564 ++4 4068 ++3 945 +-1 945 ++1 1890 +-7 2835 ++7 144 +-1 144 ++1 288 +-7 1333 +561 786 +1585 2096 +678 549 +-6 366 +819 140 ++5 2 ++1 2 ++8 3 ++5 2 ++5 5 ++7 3 ++2 1 +-2 1 ++2 1 +-2 3 ++2 1 +-2 1 ++2 1 ++28 4 ++2 6 ++2 2 ++1 2 ++7 1 +-7 2 ++7 1 ++2 254 ++8 1208 ++19 516 ++1 258 ++2 516 ++3 746 ++26 508 ++77 1456 ++2 237 ++1 237 ++3 237 +-4 237 ++4 474 +-4 17 ++1 17 ++3 17 +-4 17 ++4 34 ++6 508 ++6 254 +-15 254 ++15 2488 +1221 920 ++8 552 ++20 184 +-20 736 ++20 184 +-20 368 ++20 184 +-20 368 ++14 184 ++1 552 +-1 184 ++1 552 +cfi=(81) +cfn=(966) +calls=184 56 +* 3312 ++18 726 +-3 368 ++1 368 +-24 1104 ++3 373 ++2 746 ++8 1701 +cfi=(110) /build/buildd/eglibc-2.11.1/stdlib/mul.c +cfn=(1880) __mpn_mul +calls=189 58 +* 9450 ++4 189 ++1 189 +-1 189 ++1 189 ++1 378 ++7 189 +-7 378 ++7 373 ++2 736 ++4 2208 +cfn=(1884) str_to_mpn +calls=184 283 +* 22630 ++17 184 ++2 184 +-2 552 ++2 368 ++4 920 +cfi=(112) /build/buildd/eglibc-2.11.1/stdlib/../sysdeps/x86_64/lshift.S +cfn=(1886) __mpn_lshift +calls=184 26 +* 2760 ++1 920 +cfi=(112) +cfn=(1886) +calls=184 26 +* 2760 ++1 552 ++13 184 +-2 184 ++2 184 +1577 920 +cfn=(1888) round_and_return +calls=184 182 +* 8006 +* 184 +818 376 ++1 519 ++73 257 +-7 257 ++7 257 ++2 564 ++3 4 +-3 12 ++8 210 +718 255 ++22 510 ++1 255 +1045 36 +537 380 ++91 1496 +1045 4 +927 80 ++9 32 ++2 32 ++10 48 +-1 16 ++1 16 +-1 16 ++2 16 +-1 32 +-1 32 +795 280 +-52 516 +1051 1258 +cfn=(1884) +calls=74 283 +* 6368 +* 74 ++6 222 +828 4 +1101 74 ++1 148 +-1 148 ++1 74 ++4 148 ++9 148 ++32 148 ++3 560 ++2 140 ++8 140 ++2 700 +cfi=(112) +cfn=(1886) +calls=70 26 +* 1050 ++4 210 ++15 490 +cfn=(1888) +calls=70 182 +* 2730 +* 70 +764 8 +-65 24 +cfi=(114) /build/buildd/eglibc-2.11.1/stdlib/grouping.c +cfn=(1910) __correctly_grouped_prefixmb +calls=4 56 +* 72 ++5 28 +1030 85 +1313 184 ++1 184 ++5 184 ++38 368 +-38 368 ++38 368 +-38 2 ++38 3235 ++4 1472 +-4 10 ++2 1 +-2 1 ++2 1 +390 10 +1357 30 +389 25 +cfi=(112) +cfn=(1886) +calls=5 26 +* 75 ++1 30 +1097 148 ++89 28 +cfi=(81) +cfn=(966) +calls=4 56 +* 72 +* 44 ++79 805 +cfi=(81) +cfn=(966) +calls=161 56 +* 2898 +* 322 ++92 4 + +fn=(1884) +283 245 +fi=(158) /build/buildd/eglibc-2.11.1/stdlib/../stdlib/gmp.h +447 245 +fe=(108) +283 980 ++6 245 +-6 980 ++6 245 +-6 1225 ++6 245 ++39 490 +-5 5136 ++3 332 ++7 332 ++3 166 ++3 166 +-3 332 ++1 166 ++2 166 +-3 166 ++3 166 +-3 1118 ++3 1118 +-3 2236 ++1 1118 ++2 1118 +-3 1118 ++3 1118 +-46 2078 ++48 735 ++9 245 +-2 490 ++2 245 +-2 245 ++2 245 ++2 245 ++1 245 ++12 2205 +-82 258 +fi=(158) +447 258 +fe=(108) +283 1032 ++6 258 +-6 1032 ++6 258 +-6 1290 ++6 258 ++39 516 +-5 5292 ++3 336 ++7 336 ++3 168 ++3 168 +-3 336 ++1 168 ++2 168 +-3 168 ++3 168 +-3 1155 ++3 1155 +-3 2310 ++1 1155 ++2 1155 +-3 1155 ++3 1155 +-46 2130 ++48 774 ++9 258 +-2 516 ++2 258 +-2 258 ++2 258 ++2 258 ++1 258 ++12 2322 + +fn=(1888) +182 1470 ++1 245 +-1 735 ++1 490 ++56 784 +fi=(158) +448 98 +fe=(108) +245 98 +fi=(158) +449 98 +fe=(108) +245 98 ++10 196 ++8 490 ++3 735 ++1 1225 +-1 245 +cfi=(119) /build/buildd/eglibc-2.11.1/stdlib/../sysdeps/ieee754/flt-32/mpn2flt.c +cfn=(2366) __mpn_construct_float +calls=245 34 +* 2695 +-84 1524 ++1 254 +-1 762 ++1 508 ++56 757 +fi=(158) +448 83 +fe=(108) +245 166 +fi=(158) +449 83 +fe=(108) +245 83 ++10 166 ++8 508 ++3 762 ++1 1270 +-1 254 +cfi=(113) /build/buildd/eglibc-2.11.1/stdlib/../sysdeps/ieee754/dbl-64/mpn2dbl.c +cfn=(1890) __mpn_construct_double +calls=254 40 +* 3556 + +fn=(1848) +1601 786 +cfn=(1850) +calls=262 416 +* 159738 + +fn=(2364) +416 2331 ++56 259 +-2 259 +-54 259 ++56 259 ++15 518 ++17 259 ++1 1036 +cfi=(69) +cfn=(642) +calls=259 26 +* 4144 ++22 518 +-22 259 ++22 259 +-6 259 ++6 777 ++3 518 ++1 777 ++3 518 ++5 474 ++13 777 ++1 1295 ++75 768 ++19 512 ++1 960 ++1 384 +-1 384 ++17 256 ++6 512 ++1 1152 ++6 384 ++1 768 +-7 534 ++42 1957 ++13 490 ++16 245 +-2 245 ++2 245 ++42 490 ++9 490 ++1 1043 +-1 546 ++7 182 ++1 182 +-1 182 ++1 728 ++1 546 ++4 3964 ++3 925 +-1 925 ++1 1850 +-7 2775 ++7 132 +-1 132 ++1 264 +-7 1271 +561 777 ++3 9 ++2 6 ++11 6 ++47 15 +1585 2072 +678 543 +-6 362 +819 126 ++5 2 ++1 2 ++8 3 ++5 2 ++5 5 ++7 3 ++2 1 +-2 1 ++2 1 +-2 3 ++2 1 +-2 1 ++2 1 ++28 4 ++2 6 ++2 2 ++1 2 ++7 1 +-7 2 ++7 1 ++2 245 ++8 1162 ++19 490 ++1 245 ++2 490 ++3 719 ++26 490 ++77 1402 ++2 228 ++1 228 ++3 228 +-4 228 ++4 456 +-4 17 ++1 17 ++3 17 +-4 17 ++4 34 ++6 490 ++6 245 +-15 245 ++15 2492 +1221 910 ++8 546 ++20 182 +-20 728 ++20 182 +-20 364 ++20 182 +-20 364 ++14 182 ++1 546 +-1 182 ++1 546 +cfi=(81) +cfn=(966) +calls=182 56 +* 3276 ++18 722 +-3 360 ++1 360 +-24 1084 ++3 363 ++2 726 ++8 1629 +cfi=(110) +cfn=(1880) +calls=181 58 +* 9050 ++4 181 ++1 181 +-1 181 ++1 181 ++1 362 ++7 181 +-7 362 ++7 363 ++2 728 ++4 2184 +cfn=(1884) +calls=182 283 +* 22154 ++17 182 ++2 182 +-2 546 ++2 364 ++4 910 +cfi=(112) +cfn=(1886) +calls=182 26 +* 2730 ++1 910 +cfi=(112) +cfn=(1886) +calls=182 26 +* 2730 ++1 546 ++13 182 +-2 182 ++2 182 +1577 910 +cfn=(1888) +calls=182 182 +* 7434 +* 182 +818 364 ++1 493 ++73 244 +-7 244 ++7 244 ++2 546 ++8 189 +718 244 ++22 488 ++1 244 +1045 51 +537 404 ++91 1536 +1045 6 +927 80 ++9 32 ++2 32 ++10 48 +-1 16 ++1 16 +-1 16 ++2 16 +-1 32 +-1 32 +795 252 +-52 490 +1051 1071 +cfn=(1884) +calls=63 283 +* 5796 +* 63 ++6 189 +828 4 +1101 63 ++1 126 +-1 126 ++1 63 ++4 126 ++9 126 ++32 126 ++3 504 ++2 126 ++8 126 ++2 630 +cfi=(112) +cfn=(1886) +calls=63 26 +* 945 ++4 189 ++15 441 +cfn=(1888) +calls=63 182 +* 2268 +* 63 +764 22 +-65 66 +cfi=(114) +cfn=(1910) +calls=11 56 +* 198 ++5 77 +1030 85 +1313 182 ++1 182 ++5 182 ++38 364 +-38 364 ++38 3640 ++4 1456 +1097 126 +1265 765 +cfi=(81) +cfn=(966) +calls=153 56 +* 2754 +* 306 + +fl=(110) +fn=(1880) +58 4452 ++6 371 +-6 371 ++6 371 ++12 1113 ++5 371 ++1 742 ++9 742 +cfi=(111) /build/buildd/eglibc-2.11.1/stdlib/../sysdeps/x86_64/mul_1.S +cfn=(1882) __mpn_mul_1 +calls=371 -65 +* 5573 ++2 371 ++5 371 +-5 371 ++5 371 ++54 2968 + +fl=(78) /build/buildd/eglibc-2.11.1/misc/sbrk.c +fn=(908) sbrk +35 2435 ++8 3406 ++4 974 ++4 2916 ++3 486 +cfi=(79) /build/buildd/eglibc-2.11.1/misc/../sysdeps/unix/sysv/linux/x86_64/brk.c +cfn=(910) brk +calls=486 -25 +* 7536 +-3 1458 ++7 2922 +-14 2 +cfi=(79) +cfn=(910) +calls=1 -15 +* 12 +* 5 ++7 1278 + +fl=(67) /build/buildd/eglibc-2.11.1/iconv/gconv_simple.c +fn=(628) __gconv_btwoc_ascii +52 512 ++4 128 + +fl=(93) /build/buildd/eglibc-2.11.1/stdlib/random.c +fn=(1334) srand +211 2 ++1 6 ++1 3 +cfi=(94) /build/buildd/eglibc-2.11.1/stdlib/random_r.c +cfn=(1336) srandom_r +calls=1 -48 +* 10209 ++1 4 ++1 2 + +fl=(71) +fn=(886) +3615 59294267520 ++5 19764755840 ++1 19764755840 ++3 19764755838 ++33 88941401271 ++3 29647133757 +cfn=(902) _int_malloc +calls=9882377919 4247 +* 475605678163 ++1 9882377919 +-1 9882377919 ++1 9882377919 ++20 39529511676 ++1 88941401266 ++3 69176645433 +-63 1 ++63 5 +-63 1 +cfi=(72) /build/buildd/eglibc-2.11.1/malloc/hooks.c +cfn=(888) malloc_hook_ini +calls=1 36 +* 60740 + +fn=(887) malloc'2 +3615 6 ++5 2 ++1 2 ++3 2 ++33 9 ++3 3 +cfn=(902) +calls=1 4247 +* 1012 ++1 1 +-1 1 ++1 1 ++20 4 ++1 9 ++3 7 + +fn=(904) malloc_consolidate +5074 728736 ++22 182184 ++1 91091 ++2 91091 ++17 91091 ++2 182182 ++5 91091 ++2 182182 +-2 819819 ++2 1639638 ++2 745454 ++22 1949605 ++1 20202097 ++4 6413313 ++4 6413313 +-3 6413313 ++1 6413313 ++2 6413313 ++1 533997 ++1 533997 ++3 533997 ++1 533997 ++1 533997 +-2 533997 ++3 533997 +-3 533997 ++12 533997 +-3 533997 ++3 533997 +-12 5879316 ++1 5879316 ++1 5879316 +-2 5879316 ++3 5879316 +-3 5879316 ++12 5879316 +-3 5879316 ++3 5879320 +-3 4 ++3 4 +-41 6413317 +-3 6413317 ++3 12826634 ++1 6413317 ++1 12826634 ++2 12826634 ++1 1760261 ++2 1760261 +-1 1760261 ++2 18486266 ++3 12826634 ++1 12826626 ++6 8927416 ++26 4281277 +-7 4 ++1 4 +-1 12 +2479 3 ++5 3 ++5 1 ++2 1 +-2 1 ++2 1 +5184 728736 +2480 1 +5070 2 +2480 3 +-2 2 ++2 378 +-2 253 ++10 3 +5142 249 ++8 1536 +-8 83 ++8 36 +-8 39 ++8 3 + +fn=(1180) +3692 19753702682 ++5 19753702682 ++1 19753702682 ++5 19753702682 ++6 9876851341 +-3 9876851341 ++3 19753702682 ++15 29630554020 ++12 59261108040 ++2 29630554020 +cfn=(1182) _int_free +calls=9876851340 4762 +* 464262912944 ++1 39507405360 ++2 29630554023 +-29 7 ++4 1 ++1 1 +-1 1 ++1 2 +3531 2 ++1 1 ++6 6 ++10 1 +-3 1 ++1 1 ++2 1 +cfi=(120) +cfn=(2868) munmap +calls=1 82 +* 5 ++3 2 + +fn=(902) +4247 88941401451 ++30 79059023512 ++8 19764755878 ++1 29643313458 ++1 9881104486 ++12 9881104486 +-12 9881104486 ++14 19762208972 ++1 59215396344 ++7 9869232724 ++3 9869232724 +-3 9869232724 ++4 29607698172 +4750 88941401451 +4327 26290430 ++1 39241023 ++1 65401705 ++2 39241023 ++1 3371160 ++3 1685579 ++1 3371158 ++6 1685579 ++1 1685579 ++2 1685579 +-4 1685579 ++4 3371158 ++4 1685579 +-1 1685579 ++1 3371158 ++19 589552 ++1 194622 ++1 257000 +cfn=(904) +calls=64250 5074 +* 220270797 +* 128500 +4736 64250 +4405 64250 +-16 64250 +4736 64250 +4501 128500 +4736 64250 +4405 64250 +4736 64250 +4389 192750 +4736 11395386 +4405 11395386 +-16 11395386 +4736 11395386 +4501 22790772 +4736 11395386 +4405 11395386 +4736 11395386 +4389 34186158 +4736 453 +4389 12280536 ++3 7954909 +-2 7954909 ++1 15909818 ++1 15909818 ++3 7954909 ++10 26835104 ++35 4289799 +-5 4289799 ++1 4289799 ++4 4289799 ++13 8186118 ++1 7929520 ++1 11894280 ++1 3964760 ++45 15859040 ++4 3964760 +-4 7929520 ++1 3964760 ++1 3964760 +-2 3964760 ++7 3964760 +-4 3964760 ++1 3964760 ++3 3964760 +-7 513196 ++4 128299 +-4 256598 ++1 128299 ++1 128299 +-2 128299 ++7 128299 +-4 128299 ++1 128299 ++3 128299 ++9 15196478 ++1 259440 ++3 194580 ++1 7670 ++66 7594474 ++4 7594474 +-4 7594474 ++1 22783422 ++1 7594474 ++2 7594474 +-2 7594474 ++2 7594474 +-1 7594474 ++1 7594474 +-1 7594474 ++6 30728242 ++11 4563108 ++3 2361244 +-2 1180622 +-1 2361244 ++7 2281554 ++3 4563108 ++1 93717 ++1 93717 ++1 93717 +-2 281151 ++60 93717 +4459 572884 ++1 14922 ++1 14922 ++3 29844 +-4 113377 ++1 113377 ++3 226754 ++4 154280 +-2 38570 ++3 77140 ++9 9729 ++1 30896 ++2 12205 ++1 36615 +-23 923760 ++15 35327 +-1 35327 ++1 35327 ++1 141308 +-16 189895 +-91 2238 ++39 4901100 +-2 17422152 ++6 3665110 ++1 7330220 ++4 3665110 +-3 7330220 ++1 3665110 ++1 7330220 ++1 3665110 ++2 3447358 ++1 3447358 ++3 3447358 ++3 3447358 +-3 20684148 ++2 6894716 +-2 3447358 ++6 3447358 +-4 3447358 ++5 13789432 +-7 217752 ++3 217752 +-3 1306512 ++2 435504 +-2 217752 ++6 217752 +-4 217752 ++5 871008 ++69 358916 +-39 592975 +-91 294115 ++91 1825 +-91 2871 +4599 64829526 ++2 64812820 ++2 316456 +4485 3243 ++6 961 +-1 961 ++1 961 ++1 961 ++1 1922 ++2 6486 +-53 196740 +-1 393480 ++1 393480 ++4 196740 +-1 196740 ++1 393480 +-78 272 +-35 4 +cfn=(904) +calls=1 5074 +* 670 +* 3 +4487 4564 +4697 5406637 ++1 5406637 +-1 5406637 ++1 10813274 ++2 10813274 ++33 1880 ++1 906 ++1 2265 +cfn=(904) +calls=453 5074 +* 180501 +* 453 ++14 1359 +-14 453 ++14 453 +4393 4375674 +4625 4375674 ++3 2187837 +-3 2187837 ++3 2187837 ++2 2187837 ++3 2187837 +-3 4375674 ++3 22114797 ++3 4375674 ++1 1931370 ++1 1931370 +-1 1931370 ++1 3862740 ++37 2191602 +-1 2191602 ++1 6578571 +4524 3765 ++1 18825 +-1 621 ++1 3105 ++6 11429 ++3 19 ++1 19 +-1 19 ++1 19 +-1 19 ++1 19 +-1 3746 ++1 3746 +-1 3746 ++1 3746 +-1 3746 ++1 37631 ++3 7530 ++1 69 ++1 276 +4649 256467 ++1 769401 +-6 256467 ++17 256467 +-6 256467 ++1 256467 ++2 256467 +-1 256467 ++4 256467 ++1 196267 ++1 512934 ++2 66648 ++1 66648 ++2 66648 ++3 66648 +-3 199944 ++3 66648 +-3 199944 ++2 66648 +-2 66648 ++2 199944 +-2 189819 ++3 189819 +-3 569457 ++3 189819 +-3 569457 ++2 189819 +-2 189819 ++2 569457 +4531 26 +4704 21622788 +-2 5405697 ++2 21622788 ++2 5405697 +-2 5405697 ++2 5405697 +-3 5405697 ++1 5405697 ++2 5405697 +-2 5405697 ++6 5405697 +-1 5405697 +-3 5405697 ++4 16217091 +2990 1948 ++13 487 +-13 487 ++13 490 ++14 5 ++7 2 ++60 486 ++9 972 +-9 486 ++9 3883 ++10 1458 ++4 1458 +3418 1458 ++1 486 ++8 1944 ++4 1458 +-2 486 ++2 1458 ++1 486 +-1 486 ++1 486 +-2 486 ++1 972 ++1 486 ++2 486 +4745 3409 +3074 972 +4549 3696 ++1 11088 ++9 3696 +-14 3696 ++10 3696 ++1 3696 ++2 3696 +-1 3696 ++2 3696 ++5 3696 ++3 3696 +-3 11088 ++3 3696 +-3 11088 ++2 3696 +-2 3696 ++2 11088 ++67 997828 +3169 2430 ++19 486 +-19 486 ++19 2430 ++8 486 +-8 486 ++8 486 ++1 2430 +cfi=(77) /build/buildd/eglibc-2.11.1/malloc/morecore.c +cfn=(906) __default_morecore +calls=486 48 +* 26812 ++2 486 +-2 486 ++2 1458 ++2 120 ++1 120 +4746 120 +3247 972 ++1 1 ++1 2 ++6 1 +-6 1 ++6 1 +-6 970 ++6 485 +-6 485 ++6 1447 ++1 295 +-40 852 ++1 4 ++3 3 ++4 2 +-4 1275 ++4 1704 ++34 3414 ++40 5 ++19 1 ++3 2 ++1 3 ++2 3 ++1 4 +cfi=(77) +cfn=(906) +calls=1 48 +* 27 ++12 3 ++5 2 ++1 2 +4746 1 +3360 1 ++1 2 +-1 1 ++1 2 ++1 1 ++11 2 +-13 426 ++1 852 +-1 426 ++1 852 ++1 426 ++11 852 ++6 852 ++1 852 ++15 426 +-15 426 ++8 426 ++3 426 ++4 426 ++4 639 +cfn=(1182) +calls=213 4762 +* 10715 +* 213 +-40 2556 +-70 2 ++61 852 ++3 1278 +3226 3408 +cfi=(120) +cfn=(2708) mmap +calls=426 82 +* 2556 ++2 426 +-2 426 ++2 852 ++12 426 ++6 852 +-14 1278 +3099 970 +-73 7 +cfi=(120) +cfn=(2708) +calls=1 82 +* 6 ++2 1 +-2 1 ++2 1 ++14 3 ++13 3 ++5 5 ++1 1 ++2 1 ++1 1 +-1 1 ++1 1 ++1 1 ++9 2 +4531 7466 ++4 48776 + +fn=(984) calloc +4017 19 +-13 19 ++13 19 +-3 19 ++3 19 +-13 114 ++10 19 ++3 38 ++8 38 ++1 38 ++15 209 ++7 19 ++8 19 +-7 38 ++7 38 ++7 57 +cfn=(902) +calls=19 4247 +* 2398 +* 19 ++3 76 ++2 209 ++74 171 +-36 19 +-3 19 ++3 76 ++10 19 ++1 38 ++1 38 ++2 38 ++1 57 +cfi=(82) +cfn=(986) +calls=19 44 +* 2584 +* 19 + +fn=(1182) +4762 88891663977 ++15 29630554659 ++6 59261109318 ++13 19753703106 ++13 19753703106 ++79 2410356 ++21 3615534 ++6 1205178 +-10 1205178 ++10 1205178 ++8 3615534 ++7 2410356 +-1 1205178 ++2 2410356 ++6 3615534 ++4 2410356 ++1 1093 ++2 1093 +-1 1093 ++2 12268 ++3 2410356 ++2 2409284 ++7 1116324 ++8 1116324 ++1 1116324 ++1 2232648 +-2 88318 ++1 88318 ++1 176636 ++7 1204642 +-2 1204642 ++1 1204642 ++1 1204642 ++2 75885 ++1 75885 ++2 75885 ++3 75885 +-2 75885 ++2 75885 ++1 75885 +-1 75885 ++31 151770 +-34 1128757 ++3 1128757 +-2 1128757 ++2 1128757 ++1 1128757 +-1 1128757 ++31 2258586 ++1 52798 ++3 79197 +4821 9875646375 +-1 29626939125 ++2 19751292750 ++27 29626939125 ++4 9875646375 +-1 9875646375 ++1 9875646375 ++20 29626939125 ++6 9875646375 ++1 9875646375 +5053 79014812424 +-99 1058758 ++1 176636 ++60 52776 +cfn=(904) +calls=26388 +59 +* 18478890 +* 26388 +-21 536 ++2 536 +-1 2144 ++24 79197 ++1 52798 +3465 1 ++4 7 ++2 2 +4917 5412 ++37 634410 +-9 845 + +fl=(79) +fn=(910) +29 487 ++3 2922 ++2 1461 ++7 974 +-5 1278 ++1 426 + +fl=(99) /build/buildd/eglibc-2.11.1/string/../sysdeps/x86_64/multiarch/memcmp.S +fn=(1474) bcmp +29 2 ++1 2 ++2 2 ++1 2 ++1 2 ++2 2 + +fl=(121) /build/buildd/eglibc-2.11.1/time/../sysdeps/unix/sysv/linux/x86_64/gettimeofday.S +fn=(2802) gettimeofday +29 2 ++3 2 ++1 4 ++4 2 +cob=(13) /usr/lib/valgrind/callgrind-amd64-linux +cfi=(92) /build/buildd/valgrind-3.6.0~svn20100212/coregrind/m_trampoline.S +cfn=(2804) vgPlain_amd64_linux_REDIR_FOR_vgettimeofday +calls=2 155 +* 6 ++2 2 ++1 2 ++3 2 ++2 2 + +fl=(140) +fn=(3310) +210 130 ++35 13 +-35 13 ++35 26 +1288 40 ++4 65 ++11 26 ++11 5 +fi=(154) /build/buildd/eglibc-2.11.1/stdio-common/printf-parse.h +99 10 +fe=(140) +1314 25 +fi=(154) +99 5 +cfi=(141) +cfn=(3312) +calls=5 -72 +* 115 +fe=(140) +1329 5 +fi=(154) +99 5 +fe=(140) +1329 10 ++4 35 +cfi=(102) /build/buildd/eglibc-2.11.1/libio/genops.c +cfn=(3150) _IO_default_xsputn +calls=5 452 +* 90 +* 10 +1996 10 ++1 15 +1288 24 +2000 104 +1306 32 +cfn=(3936) buffered_vfprintf +calls=8 2221 +* 12989 +* 16 ++27 20 ++4 5 +-4 5 ++4 10 +1808 5 +1337 20 +1808 5 +1948 5 +1337 20 +1948 5 +1337 5 +1948 5 ++3 5 +-3 15 ++3 5 ++61 10 +1383 90 +1951 5 +1383 75 +1951 5 +1383 5 +1632 10 ++8 5 +fi=(154) +99 15 +cfi=(141) +cfn=(3312) +calls=5 -72 +* 115 +fe=(140) +1644 5 +fi=(154) +99 5 +fe=(140) +1644 55 +cfi=(102) +cfn=(3150) +calls=5 452 +* 90 +* 60 ++2 10 +1526 5 ++1 15 ++43 70 +1383 5 +1546 25 ++67 250 +cfi=(142) /build/buildd/eglibc-2.11.1/stdio-common/printf_fp.c +cfn=(3314) __printf_fp +calls=5 163 +* 5578 +* 50 +-46 10 +-35 5 +-1 5 ++1 20 ++4 40 ++3 5 +-3 5 ++3 30 ++74 50 + +fn=(3311) vfprintf'2 +210 80 ++35 8 +-35 8 ++35 16 +1288 24 ++4 40 ++11 16 ++11 8 +fi=(154) +99 16 +fe=(140) +1314 40 +fi=(154) +99 8 +cfi=(141) +cfn=(3312) +calls=8 -72 +* 184 +fe=(140) +1329 8 +fi=(154) +99 8 +fe=(140) +1329 16 ++4 56 +cfi=(102) +cfn=(3150) +calls=8 452 +* 408 +* 16 +1996 16 ++1 24 +1288 16 +2000 64 +1333 32 ++4 8 +-4 8 ++4 16 +1808 8 +1337 32 +1808 8 +1948 8 +1337 32 +1948 8 +1337 8 +1948 8 ++3 8 +-3 24 ++3 8 ++61 16 +1383 576 +1951 32 +1383 480 +1951 32 +1383 32 +1608 136 +1383 24 +1632 64 ++8 32 +fi=(154) +99 96 +cfi=(141) +cfn=(3312) +calls=32 -72 +* 736 +fe=(140) +1644 32 +fi=(154) +99 32 +fe=(140) +1644 352 +cfi=(102) +cfn=(3150) +calls=32 452 +* 1152 +* 384 ++2 64 +-16 48 +-17 88 +cfi=(155) /build/buildd/eglibc-2.11.1/stdio-common/_itoa.c +cfn=(3940) _itoa_word +calls=8 176 +* 176 +* 448 +cfi=(102) +cfn=(3150) +calls=8 452 +* 408 +* 224 +fi=(154) +75 24 ++2 56 +fe=(140) +1495 16 ++7 8 +-9 8 ++9 8 ++18 16 ++3 112 +1383 8 +1613 80 ++1 304 +-1 192 +cfi=(156) /build/buildd/eglibc-2.11.1/libio/iopadn.c +cfn=(3942) _IO_padn +calls=8 41 +* 744 +* 88 ++1 144 +cfi=(102) +cfn=(3150) +calls=16 452 +* 1616 +* 672 + +fn=(3936) +2221 48 ++8 24 ++20 8 +-10 8 +-6 8 ++6 32 ++1 8 ++9 8 ++1 8 +-8 8 ++5 8 ++3 8 ++4 8 +cfn=(3311) +calls=8 210 +* 11056 ++6 8 +-6 8 ++6 40 ++1 56 ++12 40 ++2 32 +cfi=(103) /build/buildd/eglibc-2.11.1/libio/fileops.c +cfn=(3136) _IO_file_xsputn@@GLIBC_2.2.5 +calls=8 1296 +* 1389 +* 24 ++6 64 ++1 16 +-53 16 ++56 56 + +fl=(49) /build/buildd/eglibc-2.11.1/stdlib/bsearch.c +fn=(218) bsearch +27 390 ++7 468 ++2 196 ++2 196 +-2 196 ++1 784 ++1 392 +cfi=(47) /build/buildd/eglibc-2.11.1/string/../sysdeps/x86_64/cacheinfo.c +cfn=(220) intel_02_known_compare +calls=196 152 +* 1358 ++1 392 ++2 70 ++1 63 +-8 211 ++14 99 +-14 12 ++14 171 + +fl=(74) +fn=(892) +29 5 ++15 1 + +fl=(94) +fn=(1336) +165 5 ++8 2 ++44 5 +-42 1 ++1 2 ++3 1 ++2 3 ++3 1 +-1 1 ++1 1 ++5 1 ++1 4 ++7 13 ++2 3 ++1 1 +-10 3 ++7 348 ++2 87 ++1 29 +-10 87 ++13 1 ++2 1 +-1 1 ++2 1 +-3 1 ++3 1 +-3 1 ++3 2 ++3 3 +cfn=(1338) random_r +calls=1 367 +* 26 +* 927 +cfn=(1338) +calls=309 367 +* 8024 +-3 622 + +fn=(1338) +367 1240 ++5 310 +-2 310 ++2 620 ++9 310 ++1 310 ++1 310 ++3 930 ++3 310 +-1 310 ++2 310 +-2 310 ++2 310 ++7 300 ++4 300 +-3 600 ++4 900 +-9 20 ++8 10 ++1 30 + +fl=(131) +fn=(3134) +37 2 ++1 2 +-1 2 ++1 2 +-1 14 ++4 4 ++2 30 ++1 8 +fi=(116) /build/buildd/eglibc-2.11.1/libio/libioP.h +984 4 ++1 12 +fe=(131) +51 4 ++4 14 +-11 1 ++1 5 +cfi=(103) +cfn=(3136) +calls=1 1296 +* 881 +* 5 +cfi=(103) +cfn=(3136) +calls=1 1296 +* 177 +* 8 +fi=(116) +985 12 +fe=(131) + +fl=(130) /build/buildd/eglibc-2.11.1/string/../sysdeps/x86_64/multiarch/strcpy.S +fn=(3048) strncpy +62 1 ++1 1 ++2 1 ++1 1 ++1 1 ++1 1 ++1 1 + +fn=(3050) 0x000000000012aa40 +81 3 ++1 3 ++1 3 ++4 3 ++1 3 ++1 3 ++1 3 ++3 3 ++1 3 ++1 3 ++1 3 ++1 3 ++1 3 +1093 3 ++3 3 ++1 3 ++1 3 ++1 3 ++1 3 ++4 3 ++1 3 ++1 3 ++1 3 ++1 3 ++26 3 ++1 3 ++1 3 ++1 3 ++1 3 ++1 3 ++1 3 ++2 18 ++2 3 ++1 3 ++1 3 ++2 6 ++1 6 ++1 6 ++6 3 ++1 3 +1289 3 ++1 3 ++5 3 ++1 3 ++1 3 + +fl=(75) +fn=(894) +127 9 ++5 1 +-5 2 ++5 2 +cob=(1) +cfi=(2) /build/buildd/eglibc-2.11.1/elf/rtld.c +cfn=(896) rtld_lock_default_lock_recursive +calls=1 835 +* 2 ++3 5 ++1 4 ++1 40 ++1 2 +31 2 ++1 2 ++3 3 ++5 1 ++6 1 +-6 1 ++1 3 ++2 3 ++3 1 ++5 3 ++74 1 +-74 1 ++74 4 +-72 1 ++19 1 +-18 2 +-1 1010 ++19 1010 +-18 2020 ++2 3600 ++14 1248 ++2 3744 +-10 2496 ++1 1248 +-1 4296 ++1 900 +-1 1800 ++2 8592 ++1 6435 +-3 5518 ++3 614 +-3 5278 ++10 5307 +-21 4042 ++85 27 +-36 2 ++1 2 ++1 2 ++3 2 ++41 2 +cob=(1) +cfi=(2) +cfn=(898) rtld_lock_default_unlock_recursive +calls=1 841 +* 2 ++3 9 +-32 1 ++1 3 + +fl=(144) /build/buildd/eglibc-2.11.1/math/../sysdeps/ieee754/dbl-64/s_isinf.c +fn=(3318) isinf +23 20 ++1 5 ++1 5 +-1 15 ++1 30 ++2 5 + +fl=(76) +fn=(900) +117 1 ++2 4 +-1 3 ++2 1 + +fl=(149) /build/buildd/eglibc-2.11.1/stdlib/divrem.c +fn=(3336) __mpn_divrem +57 60 ++3 6 +-3 12 ++3 6 +245 54 +73 6 ++1 6 ++2 18 ++6 18 ++1 12 +-38 3 ++38 1 ++1 1 +-1 1 ++1 2 +-1 3 ++4 6 +-2 6 ++2 12 ++3 6 ++2 6 +-14 6 + +fl=(85) /build/buildd/eglibc-2.11.1/csu/libc-start.c +fn=(1048) (below main) +96 7 ++10 1 +-10 3 ++10 3 ++52 1 +-52 1 ++52 1 ++1 4 +cfi=(56) +cfn=(362) +calls=1 57 +* 62 ++22 4 ++3 2 ++1 5 +cob=(12) /home/tclose/Code/Tractography/bin/test_gradient +cfi=(84) ??? +cfn=(1050) __libc_csu_init +calls=1 0 +* 253315 ++4 4 ++15 2 ++9 2 +cfi=(86) /build/buildd/eglibc-2.11.1/setjmp/../sysdeps/x86_64/bsd-_setjmp.S +cfn=(1228) _setjmp +calls=1 34 +* 29 ++1 2 ++5 2 ++1 2 ++3 2 ++3 5 +cob=(12) +cfi=(84) +cfn=(1234) main +calls=1 0 +* 7351904993215 +106 2 + +fl=(56) +fn=(364) __new_exitfn +73 623 ++6 623 +-6 623 ++6 3115 ++2 3115 ++2 1869 ++1 3110 +-3 1 ++10 1 +-10 3 ++13 1244 ++25 603 ++1 603 +-1 603 ++1 603 +-1 603 ++7 603 ++1 603 ++3 1206 +-4 20 ++1 20 ++3 1286 ++3 1869 +-39 19 ++4 40 ++2 38 ++1 57 +cfi=(71) +cfn=(984) +calls=19 4017 +* 6502 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 -71 +* 1060 ++2 57 ++2 38 ++1 19 ++6 19 ++1 38 +-1 1 ++1 2 +-32 2 + +fn=(362) +57 1246 +-22 623 ++22 3115 +-22 623 +cfn=(364) +calls=623 +38 +* 30841 ++2 1869 ++4 1246 ++3 623 +-1 623 ++2 623 ++2 1246 ++12 3738 + +fl=(83) /build/buildd/eglibc-2.11.1/nptl/forward.c +fn=(1012) pthread_mutex_init +178 5 + +fl=(150) /build/buildd/eglibc-2.11.1/string/../sysdeps/x86_64/multiarch/strcmp.S +fn=(3458) strcmp +62 1 ++1 1 ++3 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++2 1 + +fl=(87) /build/buildd/eglibc-2.11.1/setjmp/../sysdeps/x86_64/setjmp.S +fn=(1230) __sigsetjmp +26 1 ++2 1 ++1 2 ++1 1 ++4 1 ++1 1 ++1 1 ++1 1 ++1 1 ++2 2 ++2 1 ++1 1 ++2 2 ++2 1 ++9 1 +cfi=(88) /build/buildd/eglibc-2.11.1/setjmp/sigjmp.c +cfn=(1232) __sigjmp_save +calls=1 -26 +* 9 + +fl=(45) /build/buildd/eglibc-2.11.1/string/../sysdeps/x86_64/multiarch/../strrchr.S +fn=(206) __GI_strrchr +26 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++2 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++2 1 ++1 1 ++1 1 ++1 1 ++7 1 ++1 1 ++1 1 ++1 1 ++1 1 ++2 1 + +fl=(64) +fn=(622) +35 768 ++5 256 +-5 768 ++5 1280 ++5 512 ++4 384 +fi=(65) /build/buildd/eglibc-2.11.1/wcsmbs/./wcsmbsload.h ++23 384 +fe=(64) +-20 128 +-2 256 ++2 384 ++5 256 ++3 256 +cfi=(66) /build/buildd/eglibc-2.11.1/elf/dl-profstub.c +cfn=(626) _dl_mcount_wrapper_check +calls=128 -21 +* 512 +* 384 +cfi=(67) +cfn=(628) +calls=128 -8 +* 640 ++42 1536 +fi=(65) +-28 512 +fe=(64) + +fl=(115) +fn=(1962) +43 21 ++14 7 +-14 7 ++14 14 ++3 112 ++1 14 +fi=(116) +984 14 ++1 42 +fe=(115) +66 28 +cfi=(103) +cfn=(1978) _IO_file_finish@@GLIBC_2.2.5 +calls=7 206 +* 224 ++1 21 ++18 42 ++2 7 ++1 14 +cfi=(71) +cfn=(1180) +calls=7 3692 +* 888 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 -58 +* 1009 ++4 35 +-10 14 +-20 14 +cfi=(103) +cfn=(1966) _IO_file_close_it@@GLIBC_2.2.5 +calls=7 163 +* 581 +* 21 +-4 7 +cfi=(102) +cfn=(1964) _IO_un_link +calls=7 +6 +* 635 +* 21 +fi=(116) +985 42 +fe=(115) + +fl=(44) /build/buildd/eglibc-2.11.1/misc/init-misc.c +fn=(204) __init_misc +31 3 ++1 1 +-1 1 ++1 4 ++2 3 +cfi=(45) +cfn=(206) +calls=1 -8 +* 43 ++1 2 ++4 3 ++2 4 +-5 3 + +fl=(80) /build/buildd/eglibc-2.11.1/string/../sysdeps/x86_64/multiarch/strlen.S +fn=(940) strlen +32 3 ++1 3 ++2 3 ++1 3 ++1 3 ++2 3 + +fl=(112) +fn=(1886) +26 875 ++1 875 ++1 875 ++1 875 ++1 875 ++1 875 ++1 875 ++1 875 ++1 875 ++1 875 ++19 875 ++2 875 ++1 875 ++1 875 ++1 875 + +fl=(118) /build/buildd/eglibc-2.11.1/ctype/ctype.c +fn=(2270) tolower +47 10945 ++1 995 + +fl=(103) +fn=(1668) _IO_file_init@@GLIBC_2.2.5 +148 36 ++5 12 +-1 12 +-4 12 ++4 12 ++3 12 +cfi=(102) +cfn=(1670) _IO_link_in +calls=12 -51 +* 924 ++1 12 ++1 48 + +fn=(1672) _IO_file_fopen@@GLIBC_2.2.5 +258 108 ++11 24 +423 84 +271 46 ++25 2 +-10 2 ++10 2 +-10 2 ++10 14 +-10 10 ++10 10 +-10 10 ++10 77 +-7 7 ++7 62 +-25 40 ++65 12 +228 24 ++4 36 +cfi=(104) +cfn=(1674) open +calls=12 82 +* 84 +* 12 ++4 24 ++3 12 +-1 12 ++1 24 ++1 24 +-1 12 ++1 12 ++7 24 +cfi=(102) +cfn=(1670) +calls=12 104 +* 132 ++97 36 +cfi=(105) /build/buildd/eglibc-2.11.1/string/../string/strstr.c +cfn=(1678) __GI_strstr +calls=12 53 +* 324 +* 12 ++1 36 +fi=(117) /build/buildd/eglibc-2.11.1/libio/../iconv/gconv_charset.h +39 5 +fe=(103) +289 24 ++13 10 + +fn=(3144) _IO_file_stat +1233 1 ++2 3 +cfi=(133) /build/buildd/eglibc-2.11.1/io/../sysdeps/unix/sysv/linux/wordsize-64/fxstat.c +cfn=(3146) _fxstat +calls=1 37 +* 10 + +fn=(3148) _IO_do_write@@GLIBC_2.2.5 +501 60 ++1 10 +-1 20 ++1 20 ++2 60 ++11 3 ++7 4 ++8 5 +cfn=(3174) _IO_file_write@@GLIBC_2.2.5 +calls=1 1269 +* 42 ++1 1 +-1 1 ++1 2 ++5 1 +-2 1 ++2 1 +-2 3 ++1 2 ++1 1 +-34 1 ++34 1 +-34 1 ++29 2 ++5 2 + +fn=(3138) _IO_file_overflow@@GLIBC_2.2.5 +837 115 ++1 23 +-1 23 ++1 46 ++7 130 ++35 46 ++3 28 ++3 14 ++1 14 +-1 28 ++1 56 ++5 14 ++1 70 +-45 4 ++12 6 ++9 4 ++4 2 ++4 2 +-1 2 +-5 2 ++1 2 ++4 2 +-3 2 ++1 2 ++3 2 +-3 4 ++3 6 ++1 8 ++3 9 ++12 27 +-12 9 ++12 9 +-12 9 +cfn=(3148) +calls=9 501 +* 153 ++6 3 ++3 1 +-1 3 +cfn=(3148) +calls=1 501 +* 91 +* 2 +-39 4 +cfi=(102) +cfn=(3140) _IO_doallocbuf +calls=2 419 +* 134 ++1 12 + +fn=(3136) +1296 20 ++6 10 +-6 60 ++6 10 +-6 20 ++6 10 ++7 10 +-12 10 ++12 30 ++17 45 ++32 36 +cfn=(3138) +calls=9 837 +* 561 +* 18 ++7 18 ++1 30 ++2 27 ++11 18 ++1 4 +cfi=(102) +cfn=(3150) +calls=1 452 +* 651 +* 2 +-50 3 ++4 2 +-42 1 ++56 1 +-56 4 ++58 1 +-58 1 ++58 1 ++2 3 ++2 3 ++28 20 ++1 80 +-72 2 ++1 2 +-1 1 ++1 2 ++3 3 ++2 4 +-2 20 ++2 27 +-25 5 ++57 4 +-1 2 ++1 36 +-1 19 +515 24 ++15 40 +cfn=(3174) +calls=8 1269 +* 336 +* 8 ++1 24 ++5 8 +-2 8 ++2 8 +-2 24 ++1 16 ++1 8 +1371 8 ++1 8 +536 8 +1372 8 +-42 2 +522 40 ++9 16 ++5 16 + +fn=(1966) +163 7 ++2 7 +-2 14 ++2 7 +-2 7 ++2 7 ++3 35 ++6 14 +cfi=(102) +cfn=(1968) _IO_unsave_markers +calls=7 1117 +* 35 ++2 21 +cfn=(1970) _IO_file_close +calls=7 1260 +* 49 ++4 7 +-4 7 ++4 14 ++9 35 +cfi=(102) +cfn=(1974) _IO_setb +calls=7 404 +* 119 ++1 14 ++3 7 +-3 7 ++1 21 ++2 7 +cfi=(102) +cfn=(1964) +calls=7 64 +* 70 ++5 7 +-4 7 ++1 7 ++1 7 ++2 7 ++1 35 + +fn=(1970) +1260 14 +cfi=(104) +cfn=(1972) __close_nocancel +calls=7 82 +* 35 + +fn=(1978) +206 7 ++1 7 +-1 7 ++1 7 ++6 14 ++1 7 +-1 7 +cfi=(102) +cfn=(1980) _IO_default_finish +calls=7 687 +* 168 + +fn=(3174) +1269 9 ++2 9 +-2 54 ++2 9 +-2 9 ++2 18 ++11 9 +-11 18 ++2 18 ++3 36 +cfi=(104) +cfn=(3176) +calls=9 82 +* 63 ++1 18 ++9 27 ++3 54 +-6 27 + +fn=(3196) _IO_file_sync@@GLIBC_2.2.5 +899 1 ++5 1 +-5 1 ++5 3 ++2 1 ++1 2 ++17 2 ++4 2 + +fl=(88) +fn=(1232) +30 1 +-1 2 ++1 2 ++5 1 +-5 1 ++5 2 + +fl=(114) +fn=(1910) +56 15 ++6 15 +-6 105 ++6 15 +202 120 + +fl=(145) /build/buildd/eglibc-2.11.1/stdlib/../sysdeps/ieee754/dbl-64/dbl2mpn.c +fn=(3320) __mpn_extract_double +36 10 ++2 15 ++1 5 ++9 5 +-9 20 ++9 10 ++9 5 +-9 5 ++9 5 +-9 5 ++9 5 ++4 2 ++43 8 ++4 4 +-4 4 ++4 4 +-45 1 ++45 2 + +fl=(91) /build/buildd/eglibc-2.11.1/time/../sysdeps/unix/sysv/linux/x86_64/time.S +fn=(1326) time +32 2 ++3 2 ++1 2 +cob=(13) +cfi=(92) +cfn=(1328) vgPlain_amd64_linux_REDIR_FOR_vtime +calls=2 165 +* 6 ++2 2 ++2 2 + +fl=(109) /build/buildd/eglibc-2.11.1/string/wordcopy.c +fn=(1858) _wordcopy_fwd_aligned +38 7044 ++71 3279 ++1 3279 ++2 3279 ++1 3279 ++2 3279 ++1 3279 ++2 3279 ++1 3279 ++3 3279 ++3 6558 +-13 3 ++1 3 ++2 3 ++1 3 ++2 3 ++1 3 ++3 3 ++3 6 +-7 129 ++1 129 ++3 129 ++3 258 +-4 2237 +-24 2237 ++1 2237 ++2 2237 ++1 2237 ++2 2237 ++1 2237 ++2 2237 ++1 4474 +-7 4 ++1 4 ++2 4 ++1 4 ++2 4 ++1 8 +-29 8 ++2 4 ++2 4 ++1 4 +-42 129 ++3 387 ++1 129 ++8 3 ++3 9 ++1 3 ++2 1038 ++3 3114 ++1 1038 ++67 2348 + +fl=(68) +fn=(640) +28 45 ++6 9 +-6 18 ++3 9 +cfi=(69) +cfn=(642) +calls=9 -5 +* 156 ++3 9 +-3 9 ++3 18 ++8 40 ++1 80 +-8 40 ++2 80 +cfi=(69) +cfn=(642) +calls=40 -11 +* 724 +* 18 +cfi=(69) +cfn=(642) +calls=9 -11 +* 144 ++2 391 ++9 9 ++1 9 +-1 9 ++1 45 + +fl=(90) /build/buildd/eglibc-2.11.1/string/memmove.c +fn=(1282) memmove +47 2654 ++5 5308 +-5 13270 ++1 2654 +-1 2654 ++5 5308 ++5 7962 ++3 4696 ++1 2348 ++12 9392 ++6 14610 ++30 18578 +-36 5870 +cfi=(109) +cfn=(1858) +calls=1174 -35 +* 74401 +* 1174 + +fl=(95) /build/buildd/eglibc-2.11.1/io/../sysdeps/unix/sysv/linux/wordsize-64/xstat.c +fn=(1350) _xstat +37 10 +-1 10 ++1 10 ++1 60 ++4 8 +-4 10 + +fl=(120) +fn=(2708) +82 2145 ++1 429 + +fn=(3432) +82 4 +cfn=(3434) __lseek_nocancel +calls=2 * +* 10 + +fn=(2868) +82 8 ++1 2 + +fn=(3434) +82 10 + +fl=(102) +fn=(1670) +104 96 ++1 72 ++4 12 +-2 24 ++2 60 ++1 132 ++1 12 ++1 180 ++4 12 ++2 12 +-4 12 ++1 12 +-1 12 ++4 84 ++2 12 +-1 12 ++1 108 ++1 24 ++3 96 +-6 72 + +fn=(1980) +687 14 ++2 21 ++6 21 ++3 21 ++6 7 ++6 7 +-6 7 +cfn=(1964) +calls=7 64 +* 70 + +fn=(3172) __overflow +246 3 ++2 3 +cfi=(103) +cfn=(3138) +calls=1 837 +* 133 + +fn=(1964) +64 84 ++1 42 ++4 42 ++1 77 ++1 7 ++1 105 ++2 21 ++2 14 ++4 5 ++3 10 ++1 14 + +ob=(8) /usr/lib/libgslcblas.so.0.0.0 +fl=(57) ??? +fn=(2936) cblas_ddot +0 47580 + +fn=(2982) cblas_dsymm +0 1614365 + +fn=(408) 0x0000000000002570 +0 6 + +ob=(4) +fl=(102) +fn=(1964) +84 18 +-1 24 ++7 7 ++2 56 ++2 7 +-1 7 ++1 63 ++1 14 ++3 84 +-15 4 ++3 2 ++1 2 +-1 2 ++2 2 +-2 3 ++1 3 +-1 3 ++2 3 ++4 42 +-14 2 ++2 2 +-2 4 + +fn=(1968) +1117 14 ++20 14 ++1 7 + +fn=(3150) +452 83 ++3 166 +-3 249 ++1 83 +-1 249 ++1 83 ++2 140 ++5 280 ++2 168 ++3 112 ++10 96 ++4 144 ++2 48 +-2 48 ++2 48 ++2 48 ++2 96 +-2 8 ++2 96 +cfi=(103) +cfn=(3138) +calls=13 837 +* 429 +* 39 ++2 13 ++1 13 +-20 16 ++5 8 +-5 8 +cfi=(81) +cfn=(3328) +calls=8 56 +* 320 +* 16 ++21 114 ++1 498 +-42 144 ++32 192 +-1 96 ++1 448 +-1 272 + +fn=(1664) _IO_no_init +648 153 ++1 17 +cfn=(1666) _IO_old_init +calls=17 -13 +* 393 ++3 17 +-2 17 ++2 17 ++2 12 ++1 12 ++1 12 ++1 12 ++1 12 ++1 12 ++1 12 ++1 12 ++1 12 ++1 12 ++1 12 ++1 12 ++2 12 ++3 12 ++1 72 +-1 5 ++1 30 + +fn=(1666) +636 17 +-21 17 ++1 17 +-1 17 ++2 17 ++1 17 ++1 17 ++17 17 +-16 17 ++1 17 ++1 17 ++1 17 ++1 17 ++1 17 ++2 17 ++1 17 ++1 17 ++1 17 ++1 17 ++5 17 ++1 53 + +fn=(1974) +404 56 ++1 14 +-1 14 ++1 28 ++4 14 +-2 14 ++1 14 ++1 14 ++3 13 ++1 56 +-3 2 + +fn=(3140) +419 2 ++1 2 +-1 2 ++1 2 ++6 2 +-4 7 ++1 3 +cfi=(132) /build/buildd/eglibc-2.11.1/libio/filedoalloc.c +cfn=(3142) _IO_file_doallocate +calls=1 88 +* 89 +* 2 ++2 3 ++1 1 +-1 2 +cfn=(1974) +calls=1 -21 +* 17 + +fl=(119) +fn=(2366) +34 245 ++2 245 +-2 735 ++2 1225 ++6 245 + +fl=(46) /build/buildd/eglibc-2.11.1/elf/soinit.c +fn=(208) __libc_global_ctors +19 1 ++7 1 +-7 5 ++1 1 +cfi=(47) +cfn=(210) init_cacheinfo +calls=1 487 +* 6258 +-1 1 ++1 1 +cfi=(50) /build/buildd/eglibc-2.11.1/elf/dl-altinit.c +cfn=(222) dlinit_alt +calls=1 +13 +* 4 +-1 6 ++10 2 + +fl=(105) +fn=(1678) +53 108 ++10 36 ++2 24 +fi=(106) /build/buildd/eglibc-2.11.1/string/../string/str-two-way.h +273 12 +fe=(105) +89 108 +-26 36 + +fl=(132) +fn=(3142) +88 4 ++15 6 +cfi=(103) +cfn=(3144) +calls=1 1233 +* 14 +* 2 ++2 4 ++12 3 ++3 6 +cfi=(120) +cfn=(2708) +calls=1 -38 +* 6 +* 3 ++1 4 +cfi=(102) +cfn=(1974) +calls=1 404 +* 18 +* 1 ++2 4 +-13 1 +-2 9 ++8 1 +-3 1 ++3 2 + +fl=(148) /build/buildd/eglibc-2.11.1/stdlib/cmp.c +fn=(3334) __mpn_cmp +43 6 ++2 2 ++1 2 ++1 4 +-15 4 ++13 1 ++1 3 ++1 2 +-4 4 ++12 1 ++1 1 +-1 5 + +fl=(50) +fn=(222) +33 3 ++1 1 + +fl=(104) +fn=(1972) +82 40 + +fn=(1676) __open_nocancel +82 65 + +fn=(3176) +82 22 +cfn=(3178) __write_nocancel +calls=11 * +* 55 + +fn=(1764) +82 22 +cfn=(1766) __read_nocancel +calls=11 * +* 55 + +fn=(2874) close +82 2 +cfn=(1972) +calls=1 * +* 5 + +fn=(3178) +82 55 + +fn=(1674) +82 26 +cfn=(1676) +calls=13 * +* 65 + +fn=(1766) +82 55 + +fl=(61) +fn=(538) +46 10 ++12 1 +-12 1 ++12 1 ++8 2 ++3 4 ++6 4 ++1 3 +281 9 +63 2 ++12 3 +280 2 + +fl=(72) +fn=(888) +36 1 +-1 2 ++1 1 ++1 1 +cfi=(73) +cfn=(890) +calls=1 467 +* 59673 ++1 1 ++1 1 +-1 1 +cfi=(71) +cfn=(887) +calls=1 3615 +* 1059 + +fl=(135) +fn=(3194) +36 1 +-1 2 ++1 1 ++6 15 ++1 3 +cfi=(103) +cfn=(3196) +calls=1 899 +* 13 +* 2 +fi=(116) +984 1 +fe=(135) +43 1 +fi=(116) +984 1 ++1 11 +fe=(135) +47 3 + +fl=(62) +fn=(610) +32 12 ++2 24 +-2 12 ++2 12 ++3 24 ++29 12 +-28 12 ++28 24 ++1 36 ++2 36 ++4 36 ++1 12 + +fl=(155) +fn=(3940) +176 32 ++10 16 ++9 112 ++9 16 + +fl=(63) +fn=(616) +33 896 ++9 256 ++5 128 ++1 128 +-1 128 ++38 896 + +fl=(100) /build/buildd/eglibc-2.11.1/string/../sysdeps/x86_64/multiarch/../memcmp.S +fn=(1476) __GI_memcmp +25 24 ++1 24 ++1 24 ++1 24 ++1 24 ++1 24 ++1 24 ++1 24 ++3 24 ++1 24 ++1 7 ++1 7 ++1 7 ++1 7 ++1 7 ++1 7 ++1 7 ++2 21 ++1 21 ++1 5 ++1 5 ++1 5 ++1 5 ++1 1 ++1 1 ++1 1 ++2 17 ++1 17 ++1 3 ++1 3 ++1 3 ++1 3 ++1 1 ++1 1 ++1 1 ++2 14 ++1 14 ++1 10 ++1 10 ++1 10 ++1 10 ++1 10 ++1 10 ++1 10 ++2 6 ++1 6 ++1 6 ++1 6 ++1 6 ++1 6 ++1 6 ++1 4 ++1 4 ++1 4 ++1 4 ++1 4 ++7 4 ++2 7 ++4 15 ++1 15 ++1 11 ++1 11 ++1 11 ++1 11 ++1 11 ++1 11 ++1 11 ++1 11 ++1 11 ++1 11 ++1 11 ++4 6 ++1 6 + +fl=(156) +fn=(3942) +41 24 ++7 8 +-7 48 ++7 16 ++10 48 ++14 72 +-6 16 ++2 40 +cfi=(102) +cfn=(3150) +calls=8 452 +* 456 ++1 8 ++2 8 + +fl=(96) +fn=(1356) +34 18 ++2 9 + +fl=(134) +fn=(3170) +29 1 ++3 1 +-3 2 ++3 14 ++1 3 +fi=(116) +984 2 ++1 11 +fe=(134) +36 3 +-3 3 +cfi=(102) +cfn=(3172) +calls=1 246 +* 139 +* 2 + +fl=(139) /build/buildd/eglibc-2.11.1/libio/strops.c +fn=(3308) _IO_str_init_static_internal +40 30 ++4 5 +-4 10 ++4 5 ++6 25 +cfi=(102) +cfn=(1974) +calls=5 404 +* 85 ++5 5 +-3 5 ++1 5 ++1 5 ++1 5 ++2 5 ++1 5 ++1 5 ++9 5 ++1 30 +-23 25 + +fl=(101) +fn=(1682) __fopen_maybe_mmap +45 12 +-2 12 ++2 12 ++15 12 + +fn=(1658) __fopen_internal +68 84 ++8 12 +-8 12 ++8 12 +cfi=(71) +cfn=(886) +calls=12 3615 +* 3022 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 -46 +* 1095 ++2 12 +-2 12 ++2 12 ++3 12 ++3 60 +-3 12 ++3 12 +cfi=(102) +cfn=(1664) +calls=12 648 +* 684 ++4 12 ++1 12 +-1 12 ++1 12 +cfi=(103) +cfn=(1668) +calls=12 +59 +* 1080 ++4 60 +cfi=(103) +cfn=(1672) +calls=12 258 +* 1391 + +ob=(8) +fl=(57) +fn=(2996) cblas_dgemv +0 256444 + +fn=(402) 0x00000000000024d0 +0 6 + +fn=(414) 0x0000000000036cb0 +0 11 + +fn=(2944) cblas_dnrm2 +0 13176 + +fn=(2962) cblas_dtrmv +0 37210 + +fn=(2918) cblas_dgemm +0 15677 + +ob=(4) +fl=(101) +fn=(1658) +93 24 ++2 12 ++5 60 +-5 12 +cfn=(1682) +calls=12 -50 +* 48 + +fn=(1656) +107 24 +cfn=(1658) +calls=12 -39 +* 7788 + +fl=(133) +fn=(3146) +37 1 +-1 1 ++1 1 ++1 6 ++4 1 + +fl=(40) /build/buildd/eglibc-2.11.1/csu/../sysdeps/unix/sysv/linux/x86_64/../init-first.c +fn=(196) _init +52 6 ++6 1 +-6 2 ++6 2 ++17 1 +-2 1 ++1 1 +fi=(42) /build/buildd/eglibc-2.11.1/csu/../sysdeps/unix/sysv/linux/x86_64/init-first.c +-41 2 +fe=(40) ++42 1 +fi=(42) +-42 2 +fi=(41) /build/buildd/eglibc-2.11.1/csu/../sysdeps/generic/dl-hash.h ++2 3 +fe=(40) ++32 1 +-9 1 ++9 4 +fi=(41) +-29 1 +-1 2 ++1 3 ++3 1 +-1 3 ++1 3 +fi=(42) +-8 2 ++2 2 +-2 1 ++2 1 +cfi=(43) /build/buildd/eglibc-2.11.1/elf/../sysdeps/unix/sysv/linux/dl-vdso.c +cfn=(202) _dl_vdso_vsym +calls=1 -8 +* 8 ++8 1 +-5 2 ++5 1 +-5 1 ++2 2 ++1 1 ++2 1 +cfi=(43) +cfn=(202) +calls=1 -16 +* 8 +fe=(40) ++46 3 +fi=(42) +-45 2 ++1 1 +fe=(40) ++44 1 +cfi=(44) +cfn=(204) +calls=1 -58 +* 67 ++8 1 +cfi=(46) +cfn=(208) +calls=1 -78 +* 6280 ++2 6 +fi=(41) +-55 1 +-1 3 ++1 3 ++2 4 ++1 5 ++3 4 +-3 1 ++4 2 ++13 1 ++1 2 +-18 2 ++3 12 +-3 3 ++4 6 ++13 3 ++1 6 +-18 8 +fe=(40) + +fl=(138) +fn=(3306) +101 40 ++9 5 +-9 5 ++9 15 ++6 25 +-11 5 ++11 5 +cfi=(102) +cfn=(1664) +calls=5 648 +* 205 ++1 5 ++2 20 ++3 5 +-5 5 ++1 5 ++1 5 +cfi=(139) +cfn=(3308) +calls=5 -79 +* 260 ++1 20 +cfi=(140) +cfn=(3310) +calls=5 +90 +* 7373 ++2 10 ++1 10 ++2 35 + +fl=(47) +fn=(210) +487 4 ++13 3 +673 5 +501 1 +cfi=(48) +cfn=(212) +calls=1 49 +* 44 +* 1 ++6 2 ++2 3 +cfn=(214) handle_intel +calls=1 256 +* 2197 ++4 2 +-4 1 ++4 1 +cfn=(214) +calls=1 256 +* 2211 ++2 1 +-2 1 ++2 2 ++12 1 ++17 1 +-18 1 ++1 1 ++10 3 ++7 1 +-7 1 ++7 2 ++7 6 ++6 2 +-6 8 ++6 4 ++3 15 ++2 1 ++6 6 ++7 1 +-7 1 ++11 2 ++27 2 ++56 2 ++2 1 ++1 1 +-1 2 ++4 2 ++2 1 ++1 1 +-1 3 +-63 7 +-88 3 +cfn=(214) +calls=1 256 +* 1694 +* 3 + +fn=(216) intel_check_word +163 132 ++1 24 ++8 12 +-2 72 ++16 66 ++9 2 +-1 1 ++28 5 +-1 1 ++1 1 +cfi=(49) +cfn=(218) +calls=1 27 +* 153 +* 145 +-1 29 ++1 29 +cfi=(49) +cfn=(218) +calls=29 27 +* 4845 ++2 60 ++2 28 ++14 10 ++6 28 +-74 56 ++2 30 ++2 60 +-4 10 ++79 80 +-10 4 +-13 2 ++2 4 ++2 2 ++19 16 + +fn=(220) +152 784 ++3 378 ++1 196 + +fn=(214) +256 24 ++1 12 ++7 3 ++1 9 ++8 6 ++5 3 +-5 6 ++5 3 ++7 15 +cfn=(216) +calls=3 163 +* 2415 ++1 6 ++3 15 +cfn=(216) +calls=3 163 +* 1791 ++1 6 ++3 15 +cfn=(216) +calls=3 163 +* 69 ++1 6 ++3 15 +cfn=(216) +calls=3 163 +* 1632 ++1 6 +-31 2 ++13 3 ++1 3 +-1 6 ++22 7 ++5 24 + +fl=(77) +fn=(906) +48 487 ++1 487 +cfi=(78) +cfn=(908) +calls=487 -14 +* 23430 ++1 1461 ++3 974 + +fl=(98) /build/buildd/eglibc-2.11.1/string/../sysdeps/x86_64/multiarch/../strcmp.S +fn=(3460) __strcmp_ssse3 +90 4 ++1 4 ++2 4 ++1 4 ++1 4 ++1 4 ++1 4 ++1 4 ++1 4 ++1 4 ++1 4 ++1 4 ++1 4 ++1 4 ++1 4 ++1 4 ++1 4 ++1 4 ++1 4 ++5 4 ++1 4 ++9 4 ++1 4 ++1 4 ++1 4 ++1 4 ++1 4 ++1 4 ++1 4 ++1 4 ++5 4 ++1 4 ++1 4 ++1 4 ++1 4 ++1 4 +1073 4 ++1 4 ++1 4 ++1 4 ++1 4 ++1 4 ++1 4 ++1 4 ++1 4 ++1 4 ++1 4 ++1 4 ++1 4 ++4 4 ++1 4 ++1 4 ++6 4 ++1 4 ++1 8 ++4 4 ++1 4 ++3 4 ++1 4 ++1 4 ++7 4 ++3 4 ++1 4 ++1 4 ++1 4 ++1 4 ++1 4 ++7 4 ++1 4 ++2 4 ++1 4 ++2 4 ++1 4 ++1 4 ++7 4 ++3 4 ++1 4 ++1 4 ++1 4 ++1 4 ++1 4 +2052 4 ++2 4 ++1 4 ++1 4 ++1 4 ++6 4 ++6 4 ++1 4 ++2 4 ++1 4 + +fn=(1364) __GI_strncmp +84 1 ++1 1 ++1 1 ++1 1 ++1 1 ++2 1 ++1 1 ++2 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 +2063 1 ++3 1 ++1 1 ++9 1 ++1 1 + +fl=(69) +fn=(642) +26 688543263 ++1 688543263 ++1 688543263 ++1 688543263 ++1 688543263 ++1 688543263 ++1 688543263 ++1 688543263 ++1 688543263 ++1 688543263 ++1 688543263 ++1 688543263 ++2 688541310 ++1 688541310 ++1 688541310 ++1 688541310 ++1 688541310 ++1 688541310 ++2 688543263 ++1 688543263 ++1 688543263 ++1 688543263 + +fl=(111) +fn=(1882) +26 393 ++1 393 ++1 393 ++1 393 ++1 393 ++2 393 ++1 393 ++1 393 ++1 393 ++1 393 ++1 393 ++1 393 ++1 393 +-7 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 1 ++1 393 ++1 393 + +fl=(97) /build/buildd/eglibc-2.11.1/stdlib/getenv.c +fn=(1362) getenv +36 8 ++1 1 +cfi=(69) +cfn=(642) +calls=1 -11 +* 16 +* 1 ++4 4 ++56 8 +-56 2 ++3 2 ++37 1 +-8 1 ++6 1 +-1 1 ++3 3 ++3 20 ++6 4 +cfi=(98) +cfn=(1364) +calls=1 -6 +* 29 +* 2 ++1 2 +-10 36 ++11 2 + +fl=(43) +fn=(202) +27 2 ++1 4 ++4 4 ++14 2 ++4 4 + +fl=(82) +fn=(986) +44 125 ++1 125 ++1 125 ++4 125 ++1 125 ++1 125 ++1 125 ++2 125 ++1 125 ++2 106 ++5 106 ++1 106 ++1 106 ++1 106 ++1 106 +315 1 ++1 1 ++1 1 ++1 1 +-2 67 ++1 67 ++1 67 ++20 2 ++1 2 ++1 2 +-1 8 ++1 8 ++23 2 ++1 2 ++1 2 ++1 2 ++23 5 ++1 5 ++1 5 ++1 5 +-2 2 ++1 2 ++1 2 ++24 4 ++1 4 ++24 5 ++1 5 ++1 5 ++22 1 ++1 1 ++1 1 ++1 1 ++1 1 +-3 2 ++1 2 ++1 2 ++1 2 +-2 3 ++1 3 ++1 3 ++22 2 ++1 2 ++1 2 ++1 2 ++1 2 ++1 2 +-4 1 ++1 1 ++1 1 ++1 1 ++1 1 +-3 1 ++1 1 ++1 1 ++1 1 ++8 19 ++1 19 ++1 19 ++1 19 ++1 19 ++1 19 ++1 19 ++5 19 ++1 19 ++1 19 ++1 19 ++1 19 ++80 19 ++1 19 +746 19 ++1 19 ++2 19 ++1 19 +891 19 ++1 19 ++1 19 +1008 19 ++1 19 ++1 38 ++4 19 ++1 19 ++1 19 ++1 19 ++1 19 ++1 19 ++1 19 ++1 19 ++1 19 ++1 19 ++2 19 ++1 19 +-12 133 ++1 133 ++1 133 ++1 133 ++1 133 ++1 133 ++1 133 ++1 133 ++1 133 ++1 133 ++2 133 ++1 133 ++1 19 ++5 19 ++1 19 ++1 19 ++1 19 ++1 19 + +fl=(143) /build/buildd/eglibc-2.11.1/math/../sysdeps/ieee754/dbl-64/s_isnan.c +fn=(3316) isnan +33 15 ++2 5 +-2 5 ++2 45 ++3 5 + +fl=(142) +fn=(3326) hack_digit.15661 +236 120 ++3 110 ++2 81 ++7 18 ++4 42 +cfi=(149) +cfn=(3336) +calls=6 57 +* 251 ++1 24 ++4 6 +-1 6 +-3 6 ++1 6 ++3 45 ++1 5 +-1 10 ++6 5 ++1 5 ++10 10 +-10 5 ++10 10 +-6 3 +cfi=(111) +cfn=(1882) +calls=1 26 +* 15 ++1 2 ++1 6 ++4 2 +-4 1 ++4 2 +-31 42 ++1 21 +-1 21 ++1 21 +-1 42 ++1 21 +cfi=(111) +cfn=(1882) +calls=21 26 +* 315 +* 21 ++30 21 +-30 21 ++30 21 +-30 21 ++30 42 +-35 60 ++35 12 + +fn=(3314) +163 50 ++33 5 ++2 5 ++22 20 ++59 5 +-59 10 ++59 5 ++2 30 ++1 5 ++23 15 ++96 5 ++3 5 +-3 5 ++3 15 +cfi=(143) +cfn=(3316) +calls=5 33 +* 75 +* 20 +-66 15 ++16 10 ++65 20 +cfi=(144) +cfn=(3318) +calls=5 23 +* 80 +* 20 +1265 45 +435 50 +cfi=(145) +cfn=(3320) +calls=5 36 +* 115 +* 5 ++4 10 ++36 5 ++12 5 +-12 45 ++4 20 ++1 10 ++1 10 +-2 5 ++1 5 +-1 5 ++2 5 ++7 5 +-8 5 ++1 5 ++7 5 ++9 6 ++15 8 +-18 4 ++59 8 +-59 4 ++59 8 +-6 2 +-1 2 ++1 12 +cfi=(81) +cfn=(966) +calls=2 56 +* 46 +* 2 ++15 6 ++11 52 +-2 48 +-54 24 ++4 96 +-4 2 ++4 8 ++2 4 +-18 34 +cfi=(112) +cfn=(1886) +calls=2 26 +* 30 ++3 18 ++1 2 +-1 2 ++1 2 ++1 10 ++52 10 +cfi=(148) +cfn=(3334) +calls=2 43 +* 35 +* 8 ++3 10 +cfi=(81) +cfn=(966) +calls=2 56 +* 46 ++1 4 ++2 2 +-2 2 ++1 4 +-1 2 ++1 4 ++1 8 ++91 6 +828 8 +cfi=(112) +cfn=(1886) +calls=2 26 +* 30 ++1 6 ++1 2 +-1 2 +fi=(147) /build/buildd/eglibc-2.11.1/stdio-common/../include/ctype.h +47 2 +fe=(142) +834 2 +fi=(147) +47 2 +fe=(142) +834 2 +fi=(147) +47 7 +fe=(142) +834 3 +fi=(147) +47 3 +fe=(142) +834 3 +fi=(147) +47 6 +fe=(142) +844 15 ++2 5 +-2 5 ++2 5 ++10 10 ++20 35 ++1 17 ++23 30 ++4 20 ++12 30 ++7 10 +fi=(159) /build/buildd/eglibc-2.11.1/stdio-common/../nptl/sysdeps/pthread/allocalim.h +28 10 +fe=(142) +933 35 ++1 5 ++3 5 +-3 5 ++3 12 ++3 4 +-3 4 ++3 52 ++2 4 ++1 8 +cfn=(3326) +calls=4 236 +* 274 +-1 2 ++1 4 +cfn=(3326) +calls=2 236 +* 181 +* 12 +-3 48 ++6 32 + +ob=(8) +fl=(57) +fn=(2918) +0 1253916 + +ob=(4) +fl=(142) +fn=(3314) +946 8 ++3 6 ++8 15 ++22 5 +-15 5 ++15 35 +cfn=(3326) +calls=5 236 +* 298 ++1 40 +1102 48 +-8 15 ++11 15 +-3 40 ++7 38 ++3 4 +-3 1 ++3 6 ++6 15 ++46 15 ++2 35 ++2 5 +-2 5 ++2 20 ++3 10 ++7 25 ++9 15 ++47 15 ++17 25 ++3 15 ++7 15 +-92 10 +-5 15 +574 2 ++6 12 +-6 2 ++6 2 ++4 32 ++4 2 ++2 6 +1173 15 ++78 169 +-58 15 ++4 15 +cfi=(69) +cfn=(642) +calls=5 26 +* 80 +* 5 ++2 25 ++6 25 ++1 15 ++11 30 ++1 5 ++6 10 +-6 5 ++6 40 ++3 22 ++3 22 +-6 36 ++1 36 ++1 3 +cfi=(81) +cfn=(3328) +calls=1 56 +* 18 +* 2 ++25 25 +464 20 +877 12 ++14 5 +-1 5 ++1 27 ++7 4 +-6 8 ++6 4 +-6 4 ++6 9 +-6 2 ++6 1 +-6 1 ++6 2 ++50 6 ++9 62 ++15 16 +-6 16 ++2 16 +-5 32 ++3 3 ++2 3 +-5 58 ++4 38 +cfn=(3326) +calls=19 236 +* 745 ++1 19 +-1 19 ++1 19 ++2 36 ++2 6 +-8 58 +1175 10 +604 4 ++2 2 ++1 8 ++3 6 ++9 4 ++32 4 +-1 2 ++1 6 +-1 2 ++1 6 +cfi=(146) /build/buildd/eglibc-2.11.1/stdlib/../sysdeps/x86_64/rshift.S +cfn=(3322) __mpn_rshift +calls=2 25 +* 50 ++3 18 +957 1 +-2 1 ++2 1 +-1 1 ++1 4 +668 1 +-4 1 ++4 4 +cfi=(112) +cfn=(1886) +calls=1 26 +* 15 ++1 2 ++4 1 ++20 1 +-24 1 ++24 3 +-24 1 ++4 1 ++48 1 +-49 1 ++21 1 +-20 2 ++48 1 +-28 1 +-20 1 ++20 1 +-15 1 ++2 2 +-2 10 ++2 20 ++7 5 ++9 1 ++4 1 +-4 3 ++2 3 ++3 1 +-1 1 ++1 2 +-1 1 ++1 1 +-1 1 ++1 3 ++8 4 ++22 4 ++8 1 ++1 4 ++4 1 +-5 1 ++5 1 ++4 6 ++1 2 ++7 1 ++3 6 ++12 5 +cfi=(146) +cfn=(3322) +calls=1 25 +* 25 ++2 3 ++19 44 +-2 20 +-97 7 +cfi=(110) +cfn=(1880) +calls=1 58 +* 58 +* 1 +-64 8 ++18 22 +cfi=(146) +cfn=(3322) +calls=2 25 +* 50 +* 2 ++67 4 +816 3 + +fl=(146) +fn=(3322) +25 5 ++1 5 ++1 5 ++1 5 ++1 5 ++1 5 ++1 5 ++1 5 ++1 5 ++1 5 ++1 5 ++1 5 ++1 10 ++3 5 ++1 5 ++1 5 ++1 5 ++1 5 ++1 5 ++1 5 ++12 5 ++1 5 ++1 5 ++1 5 + +fl=(66) +fn=(626) +39 384 ++1 128 + +ob=(8) +fl=(57) +fn=(2970) cblas_dscal +0 6466 + +ob=(13) +fl=(92) +fn=(1328) +165 2 ++1 2 ++1 2 + +fn=(2804) +155 2 ++1 2 ++1 2 + +ob=(4) +fl=(107) +fn=(1758) +37 90 ++7 15 + +fl=(86) +fn=(1228) +34 1 ++2 1 +cfi=(87) +cfn=(1230) +calls=1 -10 +* 27 + +fl=(113) +fn=(1890) +40 254 +-6 1016 ++6 508 ++1 1524 ++7 254 + +ob=(1) +fl=(20) /build/buildd/eglibc-2.11.1/io/../sysdeps/unix/syscall-template.S +fn=(92) read +82 36 ++1 9 + +fn=(90) open +82 248 ++1 62 ++1 312 + +fn=(104) close +82 40 ++1 10 + +fn=(56) access +82 36 ++1 9 ++1 54 + +fl=(18) /build/buildd/eglibc-2.11.1/posix/../sysdeps/unix/syscall-template.S +fn=(50) uname +82 4 ++1 1 + +fl=(17) /build/buildd/eglibc-2.11.1/elf/../sysdeps/unix/sysv/linux/dl-sysdep.c +fn=(48) _dl_discover_osversion +67 4 ++2 3 ++85 5 +-45 3 +cfi=(18) +cfn=(50) +calls=1 -27 +* 5 +* 3 ++12 2 ++10 12 ++4 3 +-2 9 ++2 10 ++3 4 +-3 4 ++7 3 +-1 3 ++2 3 ++2 14 ++5 2 + +fl=(54) +fn=(356) +30 388 ++2 388 ++1 388 ++1 388 ++1 388 ++1 388 ++1 388 ++1 388 ++1 388 ++1 388 ++1 388 +cfi=(55) /build/buildd/eglibc-2.11.1/elf/../elf/dl-runtime.c +cfn=(358) _dl_fixup +calls=388 +32 +* 536758 ++1 388 ++1 388 ++1 388 ++1 388 ++1 388 ++1 388 ++1 388 ++1 388 ++1 388 ++2 388 + +fl=(33) /build/buildd/eglibc-2.11.1/string/memmove.c +fn=(124) memmove +47 1 ++5 2 +-5 5 ++1 1 +-1 1 ++5 2 ++5 3 ++22 51 ++30 7 + +fl=(26) /build/buildd/eglibc-2.11.1/elf/dl-misc.c +fn=(116) _dl_sysdep_read_whole_file +44 2 ++3 1 +-3 4 ++3 1 +-3 1 ++3 1 +cfi=(20) +cfn=(90) +calls=1 +35 +* 5 ++1 1 +-1 1 ++1 2 ++2 4 +cfi=(27) /build/buildd/eglibc-2.11.1/io/../sysdeps/unix/sysv/linux/wordsize-64/fxstat.c +cfn=(96) _fxstat +calls=1 -13 +* 10 +* 2 ++2 1 ++3 1 +-3 1 ++3 1 ++13 2 +cfi=(20) +cfn=(104) +calls=1 +14 +* 5 ++3 7 +-14 7 +cfi=(21) /build/buildd/eglibc-2.11.1/misc/../sysdeps/unix/syscall-template.S +cfn=(60) mmap +calls=1 +25 +* 6 +* 2 + +fn=(84) _dl_name_match_p +301 10275 ++1 4110 +cfi=(16) /build/buildd/eglibc-2.11.1/string/../sysdeps/x86_64/multiarch/../strcmp.S +cfn=(44) strcmp +calls=2055 63 +* 14392 +* 4110 ++3 2055 ++2 4110 ++4 2046 +-4 6138 ++1 6249 +cfi=(16) +cfn=(44) +calls=2083 63 +* 47282 +* 4166 ++6 37 +-7 37 ++7 2129 +-7 2018 ++7 6054 + +fl=(28) /build/buildd/eglibc-2.11.1/string/../string/memset.c +fn=(100) memset +32 11 +-2 22 ++2 11 ++5 22 ++1 33 ++1 33 ++3 33 ++4 22 ++8 22 ++1 43 ++2 7 ++1 7 ++1 7 ++1 7 ++1 7 ++1 7 ++1 7 ++1 14 +-9 14 ++2 70 ++1 70 ++1 70 ++1 70 ++1 70 ++1 70 ++1 70 ++1 140 +-9 140 +-30 14 ++43 7 ++3 14 ++1 14 +-4 4 ++3 8 ++1 41 ++2 22 +-2 22 ++2 54 +-2 54 +-47 11 ++53 11 ++4 22 ++8 11 + +fl=(29) /build/buildd/eglibc-2.11.1/elf/dl-deps.c +fn=(106) _dl_map_object_deps +149 1 ++1 1 +-1 2 ++1 1 +-1 2 ++1 1 +-1 1 ++1 2 +-1 4 ++1 1 +-1 1 ++1 2 ++16 1 +-16 1 ++14 1 ++1 1 ++1 1 ++6 3 ++10 1 +-10 1 ++10 1 +-36 5 ++20 1 +-2 1 ++19 1 +-17 1 ++6 1 +-6 1 +-2 1 ++2 1 +-2 1 ++1 1 ++1 1 ++6 3 ++10 1 +-10 1 ++10 5 ++19 1 +-15 1 +338 2 +203 1 ++1 1 +-18 2 +338 1 +201 1 +338 1 +204 1 +338 5 +208 2 ++5 1 ++4 2 +-9 20 ++5 10 ++4 20 ++2 2 ++3 22 ++2 9 ++11 9 +-4 9 +-7 9 ++6 9 ++1 9 +-7 9 ++5 9 ++3 18 ++3 63 ++50 50 ++1 51 +-51 860 ++1 430 ++6 125 +cfi=(22) /build/buildd/eglibc-2.11.1/string/../sysdeps/x86_64/multiarch/../strchr.S +cfn=(62) index +calls=25 26 +* 787 +* 75 ++5 125 +-3 25 ++3 25 +cfi=(24) /build/buildd/eglibc-2.11.1/elf/dl-error.c +cfn=(74) _dl_catch_error +calls=25 -87 +* 58514 ++2 75 ++15 25 ++2 50 ++5 9 ++6 9 ++2 9 +-8 18 ++5 9 +-2 9 ++1 9 ++2 9 ++4 54 +-59 8 ++13 4 +466 22 ++2 27 ++2 27 +cfi=(14) /build/buildd/eglibc-2.11.1/elf/dl-minimal.c +cfn=(36) malloc +calls=9 96 +* 252 ++2 9 +-2 9 ++2 9 ++4 36 +-1 9 ++2 9 +-1 18 +cfi=(15) /build/buildd/eglibc-2.11.1/string/../sysdeps/x86_64/memcpy.S +cfn=(42) memcpy +calls=9 56 +* 253 ++1 36 +cfi=(15) +cfn=(42) +calls=9 56 +* 253 ++3 9 ++4 66 ++2 11 ++1 72 +217 42 ++1 10 +-1 20 ++2 63 +487 4 ++4 2 ++4 5 ++11 4 +cfi=(14) +cfn=(36) +calls=1 96 +* 28 ++2 1 +-2 1 ++2 1 ++5 2 ++1 1 +-1 1 ++1 1 +-1 1 ++1 1 +-1 1 ++1 4 ++8 5 ++4 2 +-10 3 ++6 50 ++4 20 +-10 30 ++13 2 ++46 5 ++2 4 ++35 3 ++7 1 ++6 2 +-6 1 ++6 2 +-6 9 ++6 18 +-6 9 ++6 212 ++5 38 ++4 27 ++1 18 +-1 111 ++1 83 ++3 299 +-1 544 +-7 138 +-13 40 ++40 2 ++10 1 +-8 1 ++8 1 ++3 2 ++3 8 +-30 13 ++6 1 +-6 1 +cfi=(33) +cfn=(124) +calls=1 47 +* 73 ++2 1 ++6 5 +-6 1 ++6 1 +491 2 ++1 3 +288 760 +612 8 +cfi=(15) +cfn=(42) +calls=1 56 +* 64 ++5 4 + +fn=(108) openaux +62 50 ++4 25 +-4 25 ++7 25 +-4 50 ++1 25 +-1 50 ++1 100 +-1 75 +cfi=(19) /build/buildd/eglibc-2.11.1/elf/dl-load.c +cfn=(82) _dl_map_object +calls=25 1958 +* 56564 +* 25 ++5 75 + +fl=(36) /build/buildd/eglibc-2.11.1/elf/dl-reloc.c +fn=(146) _dl_relocate_object +158 66 ++10 22 +-10 33 ++14 11 +-14 22 ++14 11 ++1 55 ++6 22 ++6 33 ++4 22 ++8 33 ++45 11 +fi=(5) /build/buildd/eglibc-2.11.1/elf/../sysdeps/x86_64/dl-machine.h +96 22 +fe=(36) +242 22 +fi=(5) +96 11 ++39 3 +fe=(36) +268 320 +156 20 +fi=(5) +295 10 +fe=(36) +-27 10 +fi=(5) ++27 10 +fi=(4) /build/buildd/eglibc-2.11.1/elf/do-rel.h +65 10 +-8 10 ++1 10 ++1 10 ++6 10 +fe=(36) +268 2 +156 2 +fi=(5) +295 1 +fe=(36) +-27 1 +fi=(5) ++27 1 +fi=(4) +65 1 +-8 1 ++1 1 ++1 1 ++6 12 +-8 11 ++1 11 ++1 11 ++6 11 ++3 32 +fi=(5) +476 10 +-1 20 ++4 20 +-3 1501 +-1 3002 ++4 3002 ++2 4533 ++1 1511 +fi=(4) +68 4533 +fe=(36) +268 165 ++3 33 ++40 11 ++3 22 ++13 22 ++1 22 +cfn=(160) _dl_protect_relro +calls=11 +8 +* 275 +* 11 ++1 88 +fi=(5) +135 20 +-39 20 ++6 20 ++4 30 ++13 10 +-8 10 ++8 20 ++13 10 ++3 10 +-3 10 ++3 30 +fe=(36) ++51 33 ++82 9 +fi=(4) +75 11 ++2 11 +-2 22 ++1 11 ++1 102 ++14 10 +-12 10 ++12 21 +-12 1 ++12 2 ++10 22 ++10 33 ++4 10 ++2 10 +-2 10 ++2 10 +fi=(5) +296 30 +fi=(4) +119 20 ++1 10 ++2 20 +-2 10 +-1 10 +fi=(5) +267 10 +fi=(4) +119 10 +fi=(5) +270 10 +fi=(4) +119 10 ++1 30 +fi=(5) +270 10 +fi=(4) +119 5974 ++1 2987 ++2 5974 +-2 2987 +-1 2987 +fi=(5) +267 2987 +fi=(4) +119 2987 +fi=(5) +270 2987 +fi=(4) +119 2987 ++1 8961 +fi=(5) +270 2987 ++18 5994 ++7 55349 +fi=(4) +120 3688 +fi=(5) +295 5532 +fi=(4) +120 1844 +fi=(5) +295 7397 +fi=(4) +120 14 +fi=(5) +295 21 +fi=(4) +120 7 +fi=(5) +295 22240 +cfi=(6) /build/buildd/eglibc-2.11.1/elf/dl-lookup.c +cfn=(152) _dl_lookup_symbol_x +calls=1851 698 +* 1814887 +* 7404 ++1 8991 ++4 2977 +-4 5954 ++4 8931 ++9 17982 ++85 2983 +fi=(4) +117 5966 +fi=(5) +394 2983 +fi=(4) +117 2993 +fi=(5) +377 30 ++4 30 ++5 20 +fi=(4) +117 10 +fi=(5) +386 20 +fi=(4) +117 20 +fi=(5) +335 3 ++1 2 +fi=(4) +117 1 +fi=(5) +336 1 +fi=(4) +117 2 +fi=(5) +327 6 ++1 3 +fi=(4) +117 3 +fi=(5) +328 3 +fi=(4) +117 6 +fi=(5) +295 14 +fi=(4) +104 30 +fi=(5) +466 9 +fi=(4) +105 9 +fi=(5) +466 18 ++1 18 +fi=(4) +104 9 +fi=(5) +465 9 +fi=(4) +104 9 +fi=(5) +467 9 +fi=(4) +104 9 +fi=(5) +467 5236 +fi=(4) +104 2618 +fi=(5) +465 2618 +fi=(4) +104 2618 +fi=(5) +467 2618 +fi=(4) +104 2618 +fi=(5) +466 2618 +fi=(4) +105 2618 +fi=(5) +466 2618 +fi=(4) +127 5 ++1 2 ++1 2 +-1 1 +fi=(5) +267 1 +fi=(4) +128 1 +fi=(5) +270 1 +fi=(4) +128 3 +fi=(5) +270 1 +fi=(4) +128 4 ++1 4 +-1 2 +fi=(5) +267 2 +fi=(4) +128 2 +fi=(5) +270 2 +fi=(4) +128 6 +fi=(5) +270 2 ++18 6 ++7 117 +cfi=(6) +cfn=(152) +calls=3 698 +* 2668 +* 12 ++1 9 ++4 1 +-4 2 ++4 3 ++9 18 ++85 9 +fi=(4) +127 10 +fi=(5) +295 28349 +fe=(36) + +fn=(160) +336 11 +-2 22 ++1 22 ++1 33 ++2 22 ++2 22 ++1 33 +cfi=(21) +cfn=(98) mprotect +calls=11 82 +* 55 +-1 22 ++7 33 + +fl=(32) /build/buildd/eglibc-2.11.1/elf/dl-tls.c +fn=(162) _dl_add_to_slotinfo +820 2 ++9 2 +-9 6 ++6 4 ++8 6 ++42 2 +-1 6 ++1 4 ++1 8 + +fn=(122) _dl_next_tls_modid +54 2 ++3 6 ++48 4 ++4 4 + +fn=(138) _dl_determine_tlsoffset +116 7 ++6 3 ++3 2 ++36 3 ++2 9 +-38 1 ++38 2 ++3 4 ++4 4 +-4 6 ++2 4 ++2 6 ++12 4 ++4 10 ++2 8 ++10 2 +-37 4 ++37 2 +-37 5 ++41 1 +-1 1 ++52 1 +-51 4 ++52 8 + +fn=(140) _dl_allocate_tls_storage +332 1 ++13 1 +-13 2 ++2 1 ++11 2 +cfi=(14) +cfn=(40) __libc_memalign +calls=1 53 +* 50 ++1 1 +-1 1 ++1 1 ++7 1 ++4 305 +-58 1 ++1 1 +-1 1 ++1 2 +cfi=(14) +cfn=(32) calloc +calls=1 111 +* 37 ++1 2 ++3 1 ++6 2 ++64 5 + +fn=(164) _dl_allocate_tls_init +380 7 ++1 1 +-1 1 ++1 1 ++12 1 +-8 1 ++8 5 ++5 7 ++6 11 ++22 4 ++1 6 ++2 4 ++1 6 ++8 6 ++1 6 ++1 10 +cfi=(15) +cfn=(58) mempcpy +calls=2 56 +* 37 +* 8 +cfi=(28) +cfn=(100) +calls=2 32 +* 112 +* 6 +-42 6 ++6 9 ++3 1 ++1 2 +-1 1 ++1 2 ++6 2 ++2 2 +-2 4 ++2 4 ++38 1 ++3 9 + +fl=(19) +fn=(82) +1958 364 ++7 52 ++1 52 ++3 156 ++12 372 +-12 558 ++5 609 ++1 406 ++2 609 +cfi=(26) +cfn=(84) +calls=203 301 +* 12464 +* 406 +2240 234 +2001 9 +-1 18 ++10 9 +-1 18 ++26 18 +-2 9 ++2 9 +cfi=(22) +cfn=(62) +calls=9 26 +* 282 +* 18 +2172 2 ++1 3 +cfn=(86) expand_dynamic_string_token +calls=1 314 +* 231 ++2 1 +-3 1 ++3 1 ++4 9 +cfn=(88) open_verify +calls=1 1565 +* 202 ++3 1 +-3 1 ++3 1 ++11 27 ++3 18 ++41 9 ++1 63 +-1 9 ++1 27 +cfn=(94) _dl_map_object_from_fd +calls=9 839 +* 13988 +* 18 +2000 18 ++39 16 +cfi=(9) /build/buildd/eglibc-2.11.1/string/../sysdeps/x86_64/multiarch/../rtld-strlen.S +cfn=(18) strlen +calls=8 29 +* 432 +* 8 ++2 8 +-2 8 ++2 8 ++7 32 ++33 24 ++1 112 +cfn=(110) open_path +calls=8 1809 +* 9409 ++6 8 +-6 8 ++6 8 ++7 2 ++71 16 +-78 14 +599 21 +2095 21 ++6 14 +cfi=(31) /build/buildd/eglibc-2.11.1/elf/dl-cache.c +cfn=(114) _dl_load_cache_lookup +calls=7 182 +* 9571 ++2 7 +-2 7 ++2 7 ++4 21 ++12 14 ++22 70 +cfn=(88) +calls=7 1565 +* 1484 ++3 21 ++2 21 +cfn=(120) local_strdup +calls=7 160 +* 983 ++1 7 +-1 7 ++1 14 +-90 8 +-5 16 ++5 8 ++3 16 +-3 8 ++3 16 +-3 8 ++3 56 +-3 24 +599 24 +2058 24 ++13 40 ++1 40 +599 24 +1982 186 +-1 372 ++4 117 ++2 117 +-2 234 ++2 351 +cfi=(16) +cfn=(44) +calls=117 63 +* 2996 +* 351 + +fn=(52) _dl_init_paths +622 1 ++15 2 +-15 8 ++15 3 +cfi=(7) /build/buildd/eglibc-2.11.1/elf/../elf/dl-sysdep.c +cfn=(54) _dl_important_hwcaps +calls=1 353 +* 355 ++4 1 +-4 1 ++4 1 +cfi=(14) +cfn=(36) +calls=1 96 +* 28 ++2 1 +-2 2 ++2 1 ++7 7 ++4 2 +cfi=(14) +cfn=(36) +calls=1 96 +* 53 +* 1 ++3 3 ++7 1 ++22 1 +-3 1 ++1 2 ++2 1 +-23 1 ++23 4 +-22 1 ++18 1 ++4 2 +-12 1 +-2 1 ++3 1 ++2 1 +-3 1 ++4 2 ++4 1 +-3 1 ++3 1 +-8 3 +-2 3 ++3 3 ++2 3 +-3 3 ++4 6 ++4 3 +-3 3 ++3 3 ++1 8 +-1 52 ++2 4 +-1 12 ++1 4 +-1 48 ++1 8 +-1 4 ++1 4 +-1 16 ++1 4 +-1 12 ++3 4 +-14 4 ++14 24 ++7 1 ++4 1 +-5 1 ++6 2 ++2 4 ++2 3 ++32 5 ++8 3 +cfi=(22) +cfn=(62) +calls=1 26 +* 52 +* 2 ++2 2 +cfi=(9) +cfn=(18) +calls=1 29 +* 86 +* 8 +cfi=(15) +cfn=(42) +calls=1 56 +* 62 +* 1 ++17 7 ++2 1 ++1 2 ++1 1 +-4 3 ++2 44 ++1 88 ++1 44 +-4 133 ++7 1 +cfi=(14) +cfn=(36) +calls=1 96 +* 28 ++2 1 +-2 1 ++2 1 ++6 7 +cfn=(64) fillin_rpath +calls=1 384 +* 1630 ++4 3 ++6 1 +-52 1 ++58 2 ++1 8 +-75 1 +-2 1 ++2 2 ++11 2 + +fn=(86) +314 8 ++10 1 +-10 1 ++10 2 +cfi=(22) +cfn=(62) +calls=1 26 +* 43 +* 2 +161 2 +cfi=(9) +cfn=(18) +calls=1 29 +* 81 +* 1 ++1 2 +cfi=(14) +cfn=(36) +calls=1 -66 +* 28 ++2 2 ++3 2 +339 3 +167 1 +339 4 +167 1 +cfi=(15) +cfn=(42) +calls=1 56 +* 47 + +fn=(88) +1565 671 ++36 61 +-36 183 ++36 242 ++21 244 +cfi=(20) +cfn=(90) +calls=61 82 +* 617 ++1 61 +-1 61 ++1 61 ++11 27 +-1 9 ++1 45 +cfi=(20) +cfn=(92) +calls=9 82 +* 45 +* 18 ++7 27 +-7 9 ++7 9 ++16 126 ++50 18 ++5 18 ++2 27 ++6 18 ++7 9 ++1 9 ++1 9 +-2 36 ++1 27 ++16 36 ++15 18 +-15 480 ++1 169 ++4 45 ++1 27 ++14 63 ++2 27 ++5 2 ++1 2 +-13 123 ++16 4 ++6 2 +-3 2 ++1 2 ++1 2 ++1 4 ++14 563 +-13 2 +-1 22 + +fn=(110) +1809 64 ++1 8 +-1 40 ++7 8 +-7 8 ++1 8 ++6 16 ++5 32 ++52 16 +-52 8 ++52 8 +-52 56 ++75 24 +-63 69 ++7 92 +cfi=(15) +cfn=(58) +calls=23 56 +* 617 ++1 23 +-1 23 ++1 161 ++20 16 ++26 3 +-46 479 ++3 184 ++4 318 +cfi=(15) +cfn=(58) +calls=53 56 +* 1032 +* 212 +cfi=(15) +cfn=(58) +calls=53 56 +* 1355 +* 53 +-1 53 ++7 106 ++3 371 +cfn=(88) +calls=53 1565 +* 2596 +* 53 ++2 159 ++26 180 ++2 134 ++39 22 +-41 22 ++41 110 ++7 22 +-2 22 ++2 118 +-67 16 ++1 48 ++79 8 +-79 16 ++6 16 ++3 8 +-3 8 ++3 24 +cfi=(30) /build/buildd/eglibc-2.11.1/io/../sysdeps/unix/sysv/linux/wordsize-64/xstat.c +cfn=(112) _xstat +calls=8 37 +* 98 +-1 16 ++1 8 ++2 12 ++7 24 ++27 3 +cfi=(14) +cfn=(36) +calls=1 96 +* 28 +* 1 ++1 2 +-1 1 ++1 1 ++2 4 +cfi=(15) +cfn=(42) +calls=1 56 +* 51 ++1 2 ++34 72 +-14 21 ++10 14 +-66 6 + +fn=(64) +384 16 ++4 3 +cfi=(14) +cfn=(66) strsep +calls=1 -68 +* 24 +* 9 +cfi=(14) +cfn=(66) +calls=3 -68 +* 866 +* 12 ++3 6 +cfi=(9) +cfn=(18) +calls=3 29 +* 162 ++4 3 +-4 3 ++4 4 ++15 6 ++29 54 ++1 30 +-38 8 ++5 6 ++51 9 ++3 12 +cfi=(14) +cfn=(36) +calls=3 96 +* 84 ++3 3 +-3 3 ++3 3 ++4 3 ++2 9 +-2 6 ++2 3 +cfi=(15) +cfn=(58) +calls=3 56 +* 81 +* 3 ++3 3 +-2 6 ++2 3 ++1 1 ++5 2 ++1 1 +-1 2 ++1 2 +-1 4 ++1 2 +-1 4 ++1 41 ++1 2 +-1 6 ++1 2 +-1 32 +-98 2 ++98 3 ++1 13 +-1 2 ++1 2 +-1 8 ++1 2 +-1 6 ++4 3 +-1 6 ++1 3 ++7 6 ++1 3 ++3 9 ++5 1 ++3 9 +-14 6 +-9 2 + +fn=(94) +839 108 ++11 9 +-11 9 ++11 9 +-11 9 ++11 9 +cfi=(23) /build/buildd/eglibc-2.11.1/elf/dl-debug.c +cfn=(68) _dl_debug_initialize +calls=9 52 +* 81 ++4 27 +-4 9 ++4 9 +cfi=(27) +cfn=(96) +calls=9 37 +* 90 +* 18 ++11 63 ++1 27 +-1 162 ++1 216 ++17 18 ++22 27 ++9 18 ++21 36 ++31 27 ++3 63 +cfi=(12) /build/buildd/eglibc-2.11.1/elf/dl-object.c +cfn=(28) _dl_new_object +calls=9 36 +* 4249 ++1 9 +-1 9 ++1 9 +-52 9 ++63 9 ++1 9 +-64 9 ++63 9 ++2 9 ++3 9 +-4 9 ++1 9 ++2 36 ++1 27 ++1 18 ++22 9 ++8 9 +-25 9 ++17 9 ++8 18 +-8 36 ++8 18 +-8 9 ++8 18 +-8 9 ++8 18 ++89 18 +-47 9 ++47 27 +-47 9 ++47 27 +-88 116 ++6 27 ++1 36 +-8 552 ++1 414 ++60 6 ++4 2 ++1 4 ++1 6 ++4 4 ++3 4 ++4 8 ++6 2 +cfi=(32) +cfn=(122) +calls=2 54 +* 16 +* 6 ++1 2 +-67 90 ++6 108 ++8 18 ++1 18 +-1 18 ++1 18 +-1 36 ++1 18 ++1 126 ++2 54 ++1 54 ++1 54 ++4 18 +-4 18 ++4 45 ++5 81 ++11 9 +-11 81 ++11 9 +-46 6 ++1 2 +1160 27 ++1 27 +-5 18 ++1 9 +-70 8 ++78 36 +982 9 +1178 18 +982 9 +1178 36 ++2 9 +-2 9 ++2 9 ++19 72 +cfi=(21) +cfn=(60) +calls=9 82 +* 54 ++4 9 +-4 9 ++4 18 ++7 27 ++1 9 ++2 9 +-2 9 ++2 9 ++10 18 ++35 54 ++1 27 ++2 36 ++7 72 ++6 9 ++2 9 +-2 9 ++1 9 ++2 18 +-1 36 ++8 18 ++3 18 ++11 72 +cfi=(28) +cfn=(100) +calls=9 32 +* 1296 ++1 54 ++5 18 ++15 18 +-73 90 ++4 18 +-2 18 ++2 90 +cfi=(21) +cfn=(60) +calls=9 82 +* 54 +-2 18 +-29 63 +cfi=(21) +cfn=(98) +calls=9 82 +* 45 +* 9 +1323 9 +-77 9 ++77 18 ++9 9 +fi=(3) /build/buildd/eglibc-2.11.1/elf/dynamic-link.h +113 9 +fe=(19) +1332 9 +fi=(3) +113 9 ++6 9 +-2 9 ++2 18 ++7 9 ++5 9 ++3 9 ++1 9 +-3 9 +-5 18 +-1 212 ++1 132 ++10 44 +-18 132 ++18 9 +-18 27 ++2 410 ++8 152 ++8 152 +-18 456 ++25 27 ++20 36 ++1 36 ++1 36 ++1 36 ++2 36 ++5 36 ++1 35 ++1 36 ++6 27 ++5 18 ++7 18 ++1 36 ++16 27 ++5 1 ++2 1 +-2 2 ++2 1 ++2 2 ++2 2 ++3 27 ++2 2 ++2 2 ++3 18 +fe=(19) +1338 27 ++16 27 ++19 18 ++2 45 ++51 27 ++1 4 ++3 4 +cfi=(20) +cfn=(104) +calls=2 82 +* 10 +* 14 +cfi=(20) +cfn=(104) +calls=7 82 +* 35 +* 18 ++8 18 ++3 18 ++2 9 +-2 9 ++2 9 ++16 18 +cfi=(6) +cfn=(10) _dl_setup_hash +calls=9 843 +* 261 ++4 18 ++1 18 ++17 18 ++4 9 ++5 9 +-5 9 ++1 18 ++4 9 ++8 9 +-1 18 ++20 81 +-35 2 +fi=(3) +128 36 ++3 36 ++3 36 ++1 36 +fe=(19) +1263 21 +-2 21 ++2 7 +-2 7 ++3 7 +-3 7 ++2 7 ++1 42 ++2 28 ++42 24 +cfi=(21) +cfn=(60) +calls=3 82 +* 18 ++3 6 + +fn=(120) +160 28 ++1 7 +cfi=(9) +cfn=(18) +calls=7 29 +* 453 +* 7 ++1 14 +cfi=(14) +cfn=(36) +calls=7 -66 +* 196 ++2 14 ++3 14 ++1 14 +-1 7 ++1 7 +-1 7 +cfi=(15) +cfn=(42) +calls=7 56 +* 215 + +fl=(21) +fn=(98) +82 80 ++1 20 + +fn=(170) munmap +82 4 ++1 1 + +fn=(60) +82 140 ++1 28 + +fl=(24) +fn=(126) _dl_receive_error +198 10 ++1 1 +cfi=(2) +cfn=(76) _dl_initial_error_catch_tsd +calls=1 794 +* 2 ++5 1 +-1 1 +-4 1 ++9 1 ++2 1 +-3 1 ++3 1 +cfi=(2) +cfn=(128) version_check_doit +calls=1 658 +* 26410 ++2 1 ++1 1 ++1 8 + +fn=(74) +160 182 ++9 26 ++2 26 +cfi=(2) +cfn=(76) +calls=26 794 +* 52 +* 26 ++1 26 ++2 52 +-2 26 ++2 26 +cfi=(25) /build/buildd/eglibc-2.11.1/setjmp/../sysdeps/x86_64/setjmp.S +cfn=(78) __sigsetjmp +calls=26 26 +* 494 ++1 26 +-1 26 ++1 26 ++2 52 ++1 26 +-1 26 ++1 26 +cfi=(29) +cfn=(108) +calls=25 62 +* 57089 +cfi=(2) +cfn=(80) map_doit +calls=1 627 +* 2192 ++1 78 ++1 26 ++1 26 +-1 26 ++2 26 +-1 26 ++1 26 ++10 104 + +fl=(27) +fn=(96) +37 10 +-1 10 ++1 10 ++1 60 ++4 10 + +fl=(23) +fn=(68) +52 22 ++5 11 +-5 11 ++5 22 ++4 1 +-1 1 ++1 1 ++1 2 +-1 1 ++1 3 ++1 2 ++4 11 +-10 20 + +fn=(70) _dl_debug_state +77 2 + +fl=(6) +fn=(156) check_match.12169 +132 13320 ++1 4440 ++2 4440 ++2 11100 ++10 6660 ++3 4440 ++5 2220 +-1 2220 ++1 2220 +-1 2220 ++1 2220 ++2 3002 ++19 3002 ++1 7505 ++1 1501 +-1 3002 ++1 4500 +cfi=(16) +cfn=(44) +calls=1500 63 +* 129168 +-1 3000 ++46 15540 +-73 1590 +cfi=(16) +cfn=(44) +calls=318 -87 +* 57763 +* 954 ++29 3 +-2 4 ++28 2157 ++2 8628 +-72 4438 + +fn=(152) +698 6726 +459 2242 +698 8968 +459 2242 +698 15694 +459 11210 ++1 4484 +-1 2242 ++1 6726 +-1 6726 ++1 164080 +-1 82040 ++1 246120 +-1 250604 +700 2242 ++4 2242 ++4 2242 +-8 2242 ++1 4484 ++7 5244 ++5 11210 ++6 20178 ++8 44 +-8 110 ++2 33630 +cfn=(154) do_lookup_x +calls=2242 82 +* 1349271 ++3 4484 +-5 2242 ++33 4484 ++23 6660 ++1 13320 ++35 8880 ++14 6660 ++3 6660 +962 2220 +833 2220 ++1 2220 ++1 17936 +-81 154 ++17 44 ++1 22 ++54 2 + +fn=(10) +843 11 ++4 33 ++5 11 ++3 22 ++2 11 +-1 11 ++3 33 ++5 11 +-4 11 ++1 11 ++3 11 +-3 11 ++7 11 +-5 11 ++1 11 ++4 22 +-7 11 ++5 11 ++2 33 ++13 22 + +fn=(154) +82 22420 ++1 2242 +-6 2242 ++5 4484 +-5 20178 +272 2242 +-42 6726 ++4 2242 +-4 2242 ++42 2242 +-38 2242 +98 2242 +-3 2242 ++1 2242 ++2 2242 ++3 2242 +-3 2242 ++3 2242 +-3 10835 +-3 10835 ++1 10835 ++2 10835 ++3 10835 +-3 10835 ++3 10835 ++4 26154 ++4 26154 ++4 26154 ++7 39231 ++4 13077 ++1 13077 +226 13077 +124 26154 ++1 26154 +226 13077 ++1 26154 ++4 13077 ++3 13077 +-3 26154 ++3 143847 ++24 10857 ++24 21714 +444 32571 ++1 9455 +-1 26696 ++4 43450 ++4 17936 +287 12128 ++4 8664 ++14 2220 +-1 2220 ++1 4440 ++1 2220 +445 8345 +cfi=(26) +cfn=(84) +calls=1669 301 +* 91428 +-1 8345 +241 16632 ++1 5544 ++2 18557 ++10 11209 +-7 30500 ++2 4440 ++1 2220 +-1 2220 ++1 8880 +-1 6660 ++1 8880 +cfn=(156) +calls=2220 132 +* 301257 ++1 13320 ++45 1724 +fi=(37) /build/buildd/eglibc-2.11.1/elf/../sysdeps/generic/dl-hash.h +65 8880 +fe=(6) + +fl=(16) +fn=(44) +63 6120 ++1 6120 ++1 6120 ++1 3471 ++1 3471 ++1 3471 ++1 3471 +cfn=(45) strcmp'2 +calls=3471 -6 +* 212584 ++5 2649 ++1 2649 ++1 2649 ++1 2649 + +fn=(45) +63 29826 ++1 29826 ++1 29826 ++1 28256 ++1 28256 ++1 28256 ++1 28256 +cfn=(45) +calls=26355 -6 +* 1822957 ++2 1901 ++1 1901 ++2 1570 ++1 1570 ++1 1570 ++1 1570 + +fl=(12) +fn=(28) +36 90 ++3 10 +-3 40 ++3 10 +cfi=(9) +cfn=(18) +calls=10 -10 +* 523 ++6 10 +-6 10 ++7 20 ++6 40 +cfi=(14) +cfn=(32) +calls=10 +59 +* 451 ++3 10 +-3 10 ++3 20 ++4 10 ++5 10 +-6 10 ++4 10 ++2 10 +-5 10 ++3 10 ++2 20 +cfi=(15) +cfn=(42) +calls=10 -8 +* 273 ++2 10 +-2 10 ++5 10 +-1 10 +-2 10 ++3 40 ++3 10 +-3 10 ++3 10 ++9 10 +-7 10 ++4 10 ++3 10 +-47 5 ++49 2 +-2 2 ++2 30 +-2 30 ++18 20 +-6 10 ++1 10 ++5 10 +-6 10 ++6 39 ++3 216 ++7 9 +-5 9 ++2 9 ++3 63 ++4 27 ++1 18 ++1 9 ++3 9 +-3 9 ++3 9 +-5 3 ++1 2 ++1 1 ++3 1 +-3 1 ++3 2 ++4 27 ++4 63 ++8 1 ++6 1 +-3 2 ++3 11 +-3 18 ++3 18 ++2 18 +cfi=(9) +cfn=(18) +calls=9 29 +* 470 +* 9 ++4 9 +-4 9 ++4 9 ++64 9 ++4 90 +46 100 ++27 20 ++39 5 ++10 1 ++4 4 ++24 18 +cfi=(14) +cfn=(36) +calls=9 -54 +* 252 ++1 9 +-1 9 ++1 27 ++45 27 +cfi=(15) +cfn=(58) +calls=9 56 +* 309 +* 9 ++6 274 +-1 137 ++1 146 +-1 9 ++1 9 ++2 18 ++3 18 + +fl=(15) +fn=(58) +56 145 ++4 145 ++3 145 ++1 145 ++2 52 ++1 52 ++2 52 ++1 52 ++5 52 ++1 52 +-1 93 ++1 93 ++2 85 ++1 85 ++2 85 ++1 85 ++5 85 ++1 85 +-1 60 ++1 60 ++2 60 ++1 60 ++2 60 ++1 60 ++5 60 ++1 60 +-1 85 ++1 85 ++2 74 ++1 74 ++2 74 ++1 148 ++5 74 ++1 74 +-1 71 ++1 98 ++5 27 ++1 27 ++1 27 ++1 27 ++2 27 ++2 27 ++1 27 ++2 27 ++6 145 ++4 145 ++12 2 ++2 2 ++1 2 ++26 2 ++1 2 ++3 2 ++1 2 ++1 2 ++5 2 ++2 2 ++1 2 ++1 2 ++1 2 ++2 2 ++1 2 ++1 2 ++1 2 ++2 2 ++1 2 ++2 2 ++22 2 ++2 2 + +fn=(42) +56 40 ++2 40 ++2 40 ++3 40 ++1 40 ++2 11 ++1 11 ++2 11 ++1 11 ++5 11 ++1 11 +-1 29 ++1 29 ++2 11 ++1 11 ++2 11 ++1 22 ++5 11 ++1 11 +-1 29 ++1 29 ++2 8 ++1 8 ++2 8 ++1 8 ++5 8 ++1 8 +-1 32 ++1 32 ++2 22 ++1 22 ++2 22 ++1 22 ++5 22 ++1 22 +-1 18 ++1 42 ++5 24 ++1 24 ++1 24 ++1 24 ++2 24 ++2 24 ++1 24 ++2 24 ++8 40 ++8 10 ++6 10 ++2 10 ++1 10 ++3 2 ++1 4 ++5 2 ++1 2 ++2 2 ++2 2 ++1 2 ++2 2 +-8 7 ++1 7 ++2 7 ++2 7 ++1 7 ++2 9 ++9 2 ++1 2 +-1 8 ++1 8 ++3 10 ++1 10 ++1 10 ++5 10 ++2 10 ++1 10 ++1 10 ++1 10 ++2 10 ++1 10 ++1 10 ++1 10 ++2 10 ++1 10 ++2 10 ++2 1 ++2 1 ++1 1 ++1 1 ++1 1 ++2 1 ++1 1 ++1 1 ++1 1 ++2 1 ++1 1 ++2 2 ++5 1 ++6 1 ++1 1 +-7 9 ++6 9 ++1 9 + +fl=(14) +fn=(36) +96 171 +cfn=(40) +calls=57 -43 +* 1556 + +fn=(66) +320 6 ++3 18 ++2 6 ++1 12 ++4 32 ++5 8 +-5 264 ++5 356 ++2 720 ++8 90 +-15 272 ++18 2 ++4 8 +-13 4 ++2 4 ++7 2 ++4 4 + +fn=(32) +111 22 +-3 22 ++3 44 +-3 22 ++3 44 ++4 44 +cfn=(36) +calls=22 -19 +* 722 + +fn=(40) +53 232 ++1 231 ++11 171 ++3 57 +-3 57 ++3 114 +-3 3 ++3 1 +-3 1 ++3 210 ++4 24 ++1 18 ++6 42 +cfi=(21) +cfn=(60) +calls=6 +3 +* 36 ++2 12 ++3 12 ++1 12 +-1 6 ++1 12 ++3 6 ++1 6 ++2 24 +-3 52 ++1 52 ++2 208 +-31 2 +-1 5 + +fl=(8) /build/buildd/eglibc-2.11.1/elf/../sysdeps/unix/sysv/linux/x86_64/brk.c +fn=(14) brk +29 1 ++3 4 ++2 2 +-2 1 ++2 1 ++7 2 + +fl=(31) +fn=(168) _dl_unload_cache +306 1 ++1 4 ++2 2 +cfi=(21) +cfn=(170) +calls=1 82 +* 5 ++1 1 ++2 2 + +fn=(118) _dl_cache_libcmp +169 216 +-29 144 ++2 216 ++20 216 ++2 144 ++4 72 ++1 144 +cfn=(119) _dl_cache_libcmp'2 +calls=72 * +* 6029 + +fn=(119) +169 1086 +-29 746 ++2 1086 ++2 33 ++6 22 ++1 11 +-1 11 ++2 11 +-1 22 ++1 33 ++2 44 ++2 22 ++6 1053 ++2 702 ++4 290 ++1 580 +cfn=(119) +calls=290 * +* 19015 ++3 22 ++1 11 +-8 244 + +fn=(114) +182 56 ++8 14 ++3 21 ++45 14 ++6 21 ++15 14 +-6 7 ++6 7 +cfi=(20) +cfn=(56) +calls=7 82 +* 77 +* 7 ++17 35 +-23 7 ++23 14 +-23 7 ++23 1090 +cfn=(118) +calls=61 169 +* 5686 +* 317 ++21 63 +196 4 +cfi=(26) +cfn=(116) +calls=1 44 +* 68 ++8 2 ++1 1 +-1 2 ++1 3 +-1 13 ++8 1 +-3 2 ++3 3 ++3 1 ++1 2 +-1 1 ++1 1 ++19 2 +-17 2 +-2 22 ++60 141 +cfn=(118) +calls=4 169 +* 356 +* 35 +cfn=(118) +calls=7 169 +* 1139 +* 285 ++16 28 + +fl=(2) +fn=(80) +627 2 ++2 2 +-2 1 ++2 6 +cfi=(19) +cfn=(82) +calls=1 1958 +* 2177 +* 1 ++3 3 + +fn=(142) security_init +848 4 ++2 1 +fi=(35) /build/buildd/eglibc-2.11.1/elf/../sysdeps/unix/sysv/linux/dl-osinfo.h +68 1 ++4 1 ++3 2 ++48 7 +fe=(2) +852 1 ++6 3 ++2 1 +fi=(35) +132 2 ++11 1 +fe=(2) +863 1 ++2 1 ++6 1 ++1 5 + +fn=(2) _dl_start +363 9 ++18 4 +fi=(5) +76 2 +fe=(2) +381 1 ++29 2 +-3 1 +fi=(3) +119 1 +fe=(2) +410 1 +fi=(3) +119 2 ++3 1 ++4 1 ++5 1 ++3 1 ++1 1 +-3 1 +-5 2 +-5 13 ++15 13 +-18 39 ++18 1 +-18 3 ++2 36 ++5 20 ++1 12 ++10 4 +-18 13 ++25 2 ++20 4 ++1 4 ++1 4 ++1 4 ++2 4 ++5 4 ++1 4 ++1 4 ++6 3 ++5 2 ++7 3 ++1 3 ++8 3 ++2 3 ++3 2 ++1 2 +fe=(2) +538 2 ++7 1 +286 2 ++12 2 +cfi=(6) +cfn=(10) +calls=1 843 +* 29 ++1 1 ++1 1 ++1 1 +-2 1 ++3 1 +-2 1 ++1 1 ++1 1 ++21 1 ++10 1 +-10 3 ++10 1 +-6 1 +-4 1 ++10 1 +cfi=(7) +cfn=(12) _dl_sysdep_start +calls=1 88 +* 2209197 +* 1 ++9 1 ++7 1 +-4 1 ++4 1 +570 9 +fi=(3) +128 4 ++3 4 +fe=(2) +543 14 +fi=(4) +76 1 +-1 1 ++2 1 +-2 1 ++2 1 ++2 8 ++25 2 +fi=(5) +466 14 +fi=(4) +105 14 +fi=(5) +466 14 ++1 28 +-2 14 +fi=(4) +104 28 +fi=(5) +467 14 +fi=(4) +104 15 ++5 2 ++11 8 ++2 8 +fi=(5) +288 24 +fi=(4) +120 24 +fi=(5) +296 24 ++4 8 +-4 16 ++4 24 ++6 24 ++1 16 +fi=(4) +117 27 +fi=(3) ++17 4 ++1 4 +fe=(2) +286 67 + +fn=(128) +658 2 ++3 4 +cfi=(34) /build/buildd/eglibc-2.11.1/elf/dl-version.c +cfn=(130) _dl_check_all_versions +calls=1 383 +* 26400 +-1 2 ++4 2 + +fn=(896) +835 1 ++1 1 + +fn=(22) dl_main +886 1 ++19 1 ++7 1 +-26 6 ++32 1 +-32 4 ++27 1 +-5 1 ++10 1 ++3 1 +-16 1 ++7 1 +-4 1 ++5 1 ++8 1 +cfn=(24) process_envvars +calls=1 2494 +* 540 ++7 4 +1090 7 +cfi=(12) +cfn=(28) +calls=1 36 +* 248 ++2 1 +-2 1 ++2 1 ++1 2 ++2 1 ++1 2 +-2 1 ++1 1 ++1 2 ++29 1 +-3 1 ++3 1 +-8 1 ++1 1 ++2 1 ++5 6 ++1 28 +-1 27 ++1 52 ++95 2 ++1 3 +-5 2 ++1 1 +-88 3 ++1 1 ++49 2 ++1 2 +-1 8 ++2 4 ++1 2 ++3 2 ++1 2 +-1 2 ++1 2 ++1 2 ++1 6 ++1 2 +-46 1 ++10 1 +-10 1 ++10 1 +-7 2 +-3 1 ++10 1 ++68 2 +-87 3 ++1 1 ++92 3 ++3 2 ++2 2 ++2 3 ++13 3 ++1 6 +cfi=(16) +cfn=(44) +calls=1 63 +* 7 +-1 2 ++11 1 +-3 1 +-2 1 ++3 1 ++2 2 ++1 2 ++4 2 ++2 2 +fi=(3) +104 1 ++9 2 ++6 1 +-2 1 ++2 2 ++7 1 ++5 1 ++3 1 ++1 1 +-3 1 +-5 2 +-1 16 ++1 9 ++10 3 +-18 9 ++18 1 +-18 3 ++2 54 ++8 23 ++8 23 +-18 69 ++25 3 ++38 3 ++5 2 ++7 2 ++1 4 ++16 3 ++14 3 ++7 2 +fe=(2) +1271 2 +cfi=(6) +cfn=(10) +calls=1 843 +* 29 ++3 2 ++20 4 +fi=(3) +128 4 +fe=(2) +1383 1 +cfi=(17) +cfn=(48) +calls=1 67 +* 92 +* 8 ++5 2 +cfi=(19) +cfn=(52) +calls=1 622 +* 2979 ++3 3 +cfi=(23) +cfn=(68) +calls=1 52 +* 18 ++7 1 +-7 1 ++2 1 ++5 1 ++4 1 ++3 1 +-2 1 ++3 1 +-2 1 +-2 2 ++9 1 +-9 1 ++1 1 ++8 1 ++5 1 ++4 1 +-3 2 ++3 1 ++4 1 +-5 1 ++5 2 ++1 2 ++1 1 +-1 2 ++1 3 ++2 2 ++1 2 ++5 2 ++5 4 +1620 3 ++3 2 ++4 3 ++5 2 ++1 1 +cfi=(23) +cfn=(70) +calls=1 77 +* 1 ++4 3 ++15 3 ++4 4 ++31 3 +cfi=(20) +cfn=(56) +calls=1 82 +* 11 +* 2 ++77 1 ++11 1 +-11 3 ++17 1 ++1 2 +-1 1 ++1 2 +-1 1 ++1 3 +cfi=(29) +cfn=(106) +calls=1 149 +* 65617 ++1 1 ++2 5 ++3 1 +-3 2 ++3 1 +-3 1 ++3 1 +-3 1 ++3 1 ++1 5 +-1 2 ++1 40 +-1 21 ++4 3 ++1 3 ++1 1 ++2 2 ++1 52 +-1 27 +fi=(3) +131 4 ++3 4 ++1 4 +fe=(2) +1797 2 ++13 1 +-1 2 ++1 1 ++2 4 ++5 1 +-5 1 ++4 2 ++12 1 ++2 3 ++1 1 ++1 1 +-1 1 ++1 3 ++11 2 ++2 3 +-2 2 ++1 4 ++1 1 +cfi=(24) +cfn=(126) +calls=1 198 +* 26440 ++10 1 ++1 1 +-1 1 ++1 1 ++3 2 ++3 1 +cfn=(142) +calls=1 848 +* 32 ++2 2 +2093 3 +2239 1 ++2 7 ++6 1 +-6 1 ++6 1 ++9 4 ++1 1 ++5 2 +cfi=(32) +cfn=(164) +calls=1 380 +* 283 ++4 2 ++8 4 ++15 1 ++2 1 ++1 1 +-3 1 ++3 3 +-3 1 ++3 1 +cfi=(36) +cfn=(146) +calls=1 158 +* 9144 ++1 1 ++2 9 ++8 1 +cfi=(7) +cfn=(166) _dl_sysdep_start_cleanup +calls=1 251 +* 1 ++4 3 ++20 3 +cfi=(23) +cfn=(68) +calls=1 52 +* 9 ++1 1 ++1 1 +cfi=(23) +cfn=(70) +calls=1 77 +* 1 ++4 1 +cfi=(31) +cfn=(168) +calls=1 306 +* 15 ++5 8 +2149 2 ++4 4 ++48 2 ++7 1 +-7 1 ++7 1 ++3 45 ++3 4 ++22 11 ++2 22 +-18 22 ++2 22 ++6 33 ++1 70 +cfi=(36) +cfn=(146) +calls=10 158 +* 2097933 ++4 26 ++1 4 +cfi=(32) +cfn=(162) +calls=2 820 +* 40 +* 2 +1828 2 +1412 4 +-11 4 +1857 1 +cfn=(136) init_tls +calls=1 780 +* 687 +* 3 +-89 9 ++4 3 ++1 1 ++1 2 ++1 2 +1663 59 +cfi=(15) +cfn=(42) +calls=1 56 +* 92 +* 1 ++3 4 ++3 3 +cfi=(14) +cfn=(66) +calls=1 320 +* 909 +* 3 +cfi=(14) +cfn=(66) +calls=1 320 +* 9 +* 6 ++1 4 ++3 4 +cfn=(72) do_preload +calls=1 800 +* 2277 +* 2 ++2 1 ++2 12 +2224 1 ++1 1 +-3 2 + +fn=(24) +2494 1 ++8 2 +-8 4 ++23 1 +-23 4 ++8 1 +-8 1 ++8 2 +-7 1 ++6 2 +fi=(160) /build/buildd/eglibc-2.11.1/elf/../sysdeps/unix/sysv/linux/dl-librecon.h +32 1 +fe=(2) +2501 1 +-6 1 +fi=(160) +32 2 +fe=(2) +2504 2 +cfi=(11) /build/buildd/eglibc-2.11.1/elf/dl-environ.c +cfn=(26) _dl_next_ld_env_entry +calls=1 31 +* 54 +* 4 +cfi=(11) +cfn=(26) +calls=2 31 +* 258 +* 9 ++4 6 +-4 2 ++4 38 ++1 19 +-1 57 ++9 12 +2666 1 +-4 1 ++4 1 +-4 1 ++4 1 ++30 2 ++21 8 +2591 17 +-53 5 ++7 12 ++2 2 ++1 1 ++45 2 ++1 1 + +fn=(72) +800 6 ++6 1 ++1 1 ++6 5 +-11 1 ++6 1 ++1 1 ++2 1 ++2 1 +cfi=(24) +cfn=(74) +calls=1 160 +* 2249 ++1 2 ++2 3 ++12 5 + +fn=(76) +794 54 + +fn=(136) +780 1 +-56 1 +-4 1 +-2 1 ++2 1 ++4 1 ++60 3 +-54 1 ++3 4 +cfi=(14) +cfn=(32) +calls=1 111 +* 62 ++12 1 +-12 1 ++7 1 ++1 1 ++4 1 ++2 5 ++2 22 ++4 2 ++2 2 +-2 4 +-5 2 +-1 4 ++1 9 +-1 19 ++10 2 ++3 1 +cfi=(32) +cfn=(138) +calls=1 116 +* 101 ++7 1 +cfi=(32) +cfn=(140) +calls=1 332 +* 418 ++1 1 +-1 1 ++1 1 ++6 1 ++4 1 +-4 1 ++4 6 ++3 1 ++2 1 + +fn=(898) +841 1 ++1 1 + +fl=(30) +fn=(112) +37 8 +-1 8 ++1 8 ++1 48 ++4 2 +-4 24 + +fl=(10) /build/buildd/eglibc-2.11.1/elf/../misc/sbrk.c +fn=(20) sbrk +35 3 ++8 1 +-8 1 ++8 5 ++4 2 ++11 5 + +fl=(22) +fn=(62) +26 36 ++1 36 ++1 36 ++1 36 ++1 36 ++1 36 ++1 36 ++1 36 ++1 36 ++1 36 ++1 36 ++1 36 ++1 36 ++1 36 ++1 36 ++1 36 ++1 36 ++1 36 ++1 36 ++1 36 ++1 36 ++2 29 ++1 29 ++1 29 ++1 29 ++1 29 ++1 29 ++1 29 ++1 29 ++1 29 ++2 36 ++1 36 ++1 1 ++1 1 ++1 1 ++1 1 ++1 35 ++1 36 + +fl=(38) /build/buildd/eglibc-2.11.1/elf/dl-init.c +fn=(174) _dl_init +93 11 ++5 1 +-4 1 ++1 1 ++3 2 ++7 2 ++27 2 ++1 24 ++1 11 +-1 11 ++1 22 +-97 33 ++9 10 +-3 20 ++3 30 ++5 27 ++5 16 ++8 16 ++6 48 +cob=(2) ??? +cfi=(13) ??? +cfn=(460) 0x0000000004e4e288 +calls=1 -70 +* 189433 +cob=(2) +cfi=(13) +cfn=(440) 0x0000000004c26f38 +calls=1 -70 +* 29 +cob=(2) +cfi=(13) +cfn=(420) 0x00000000051210f8 +calls=1 -70 +* 29 +cob=(2) +cfi=(13) +cfn=(400) 0x00000000054e0450 +calls=1 -70 +* 29 +cob=(2) +cfi=(13) +cfn=(264) 0x000000000576fec8 +calls=1 -70 +* 2214 +cob=(2) +cfi=(13) +cfn=(244) 0x0000000005a2fe00 +calls=1 -70 +* 29 +cob=(2) +cfi=(13) +cfn=(224) 0x0000000005cb1a98 +calls=1 -70 +* 29 +cob=(4) +cfi=(40) +cfn=(196) +calls=1 -18 +* 6499 ++4 8 ++1 16 ++65 8 +-88 2 +-6 4 +-9 4 ++9 1 +-3 2 ++3 3 ++5 3 ++5 2 ++8 2 ++6 7 +cob=(2) +cfi=(13) +cfn=(176) 0x0000000004a234c8 +calls=1 -70 +* 29 +* 1 ++4 1 ++1 2 ++26 2 + +fl=(7) +fn=(54) +353 6 ++3 1 +-3 2 ++3 1 +-1 1 ++1 1 ++9 1 +-12 4 ++12 1 ++10 3 ++44 4 +cfi=(20) +cfn=(56) +calls=1 82 +* 11 +* 3 +-2 1 ++17 1 +-17 1 ++17 5 ++3 2 ++22 2 ++8 2 ++2 1 ++1 1 +-1 2 ++1 4 ++8 1 +-4 2 ++1 1 +-1 1 ++4 1 ++3 2 ++4 6 ++1 2 ++18 10 ++1 3 +cfi=(14) +cfn=(36) +calls=1 96 +* 28 ++1 1 +-1 2 ++1 1 ++7 2 ++22 3 ++3 1 +-3 3 ++3 1 ++28 2 +-7 1 ++7 4 ++1 1 +-1 1 ++1 1 +-1 1 ++1 1 +-1 1 ++1 3 +-1 3 ++1 3 +-1 3 ++1 3 +-1 5 ++5 2 +-5 3 ++5 3 ++3 1 +-3 1 ++3 1 +-3 3 ++3 1 +-3 1 ++3 7 ++2 16 +-2 4 ++1 12 +-1 2 ++1 12 +-1 10 ++4 4 ++3 1 ++2 2 +-1 1 +-1 2 ++2 3 ++13 13 ++3 3 +-3 3 ++3 3 ++3 4 ++3 8 +379 3 ++63 4 ++98 5 +cfi=(15) +cfn=(58) +calls=1 56 +* 22 +* 1 ++1 1 +-1 1 ++1 2 +cfi=(15) +cfn=(58) +calls=1 56 +* 22 +* 3 + +fn=(166) +251 1 + +fn=(12) +88 8 ++25 1 +-1 1 ++1 146 ++3 1 +-3 1 ++6 2 +-2 1 +-1 1 ++3 1 +-6 1 ++6 4 ++1 1 +-1 7 ++1 105 ++3 2 +-4 49 +fi=(17) +-83 2 +cfi=(8) +cfn=(14) +calls=1 -7 +* 11 +fi=(5) +226 5 +fe=(7) ++2 2 +cfi=(10) +cfn=(20) +calls=1 35 +* 17 +* 3 ++12 3 ++3 4 +cfi=(2) +cfn=(22) +calls=1 886 +* 2208726 ++2 9 +-67 1 +-59 4 ++34 1 +-34 4 ++43 1 +-43 4 ++40 1 +-40 4 ++37 1 +-37 5 ++13 1 +-13 4 ++10 1 +-10 4 ++7 1 +-7 4 +226 1 +cfi=(9) +cfn=(18) +calls=1 29 +* 39 +* 2 + +fl=(9) +fn=(18) +29 40 ++1 40 ++1 40 ++1 40 ++2 23 ++1 23 ++2 23 ++1 23 +-1 75 ++1 75 ++1 97 ++1 97 ++1 97 ++2 78 ++5 39 ++1 39 ++1 39 ++1 39 ++3 39 +-6 5 ++1 5 ++1 5 ++1 5 ++3 5 ++1 42 ++1 42 ++1 42 ++2 42 ++3 35 ++1 35 ++1 35 ++1 35 ++3 35 ++1 26 ++1 26 ++1 26 ++2 26 ++3 16 ++1 16 ++1 16 ++1 16 ++3 16 ++1 11 ++1 11 ++1 11 ++2 11 ++3 6 ++1 6 ++1 6 ++1 6 ++3 6 ++1 5 ++1 5 ++1 5 ++2 5 ++3 39 ++2 39 ++1 39 ++1 32 ++2 32 ++1 32 ++1 28 ++2 28 ++1 28 ++1 25 ++2 25 ++1 25 ++1 21 ++2 21 ++2 21 ++1 21 ++1 16 ++2 16 ++1 16 ++1 14 ++2 14 ++1 14 ++1 8 ++2 8 ++1 8 +-1 32 ++1 32 + +fl=(1) ??? +fn=(0) 0x0000000000000af0 +0 2 +cfi=(2) +cfn=(2) +calls=1 363 +0 2209962 +0 14 +cfi=(38) +cfn=(174) +calls=1 93 +0 198676 +0 3 +cob=(12) +cfi=(84) +cfn=(1040) 0x00000000004114e0 +calls=1 0 +0 7351905248537 + +fl=(11) +fn=(26) +31 3 ++3 11 ++2 92 ++11 44 +-13 133 ++17 1 +-14 20 ++5 2 +-3 2 ++3 2 ++2 2 + +fl=(34) +fn=(134) match_symbol +82 460 ++9 46 +-8 46 +-1 138 ++1 46 ++8 46 ++6 138 ++15 46 ++1 92 ++2 46 ++5 92 ++14 572 ++12 720 ++4 480 +-30 480 ++19 276 +cfi=(16) +cfn=(44) +calls=46 -76 +* 3816 +* 138 ++34 46 ++1 322 + +fn=(132) _dl_check_map_versions +180 99 ++15 11 +-15 22 ++15 22 ++2 11 ++3 11 +-3 11 ++2 11 ++1 11 ++2 11 +-3 11 ++3 11 ++3 27 ++4 9 +-4 9 ++4 18 ++10 27 ++7 9 +62 9 +226 18 +62 54 +226 11 +62 11 +226 22 +62 106 ++1 163 +-1 326 ++2 549 +cfi=(26) +cfn=(84) +calls=183 301 +* 11316 +* 366 +230 40 ++4 60 ++5 80 ++20 52 +-16 440 +cfn=(134) +calls=9 82 +* 1651 +* 222 +cfn=(134) +calls=37 82 +* 6395 +* 230 ++11 138 ++9 80 ++5 33 ++1 15 ++8 22 ++3 24 ++10 108 +-10 216 ++6 162 +-6 24 ++6 18 ++8 22 ++83 99 +-77 10 +-1 30 +cfi=(14) +cfn=(32) +calls=10 111 +* 370 ++2 10 +-2 20 ++2 10 ++11 10 ++2 10 +-5 10 ++3 20 ++2 10 ++3 45 ++4 18 ++4 54 ++1 36 ++1 27 ++1 27 ++2 27 +-9 22 ++4 66 ++1 44 ++1 33 ++1 33 ++2 33 +-5 22 ++10 22 +-10 66 ++1 33 ++1 33 ++1 33 ++2 33 ++5 30 +-10 90 ++1 45 ++1 45 ++1 45 ++2 45 ++8 60 ++5 33 ++1 11 ++4 20 ++3 30 ++20 108 +-14 54 +-2 54 ++2 60 +-2 6 ++2 6 ++5 108 ++1 54 +-1 270 ++1 54 ++1 54 +-1 108 ++4 186 + +fn=(130) +383 5 ++4 1 +-4 1 ++4 1 +-4 1 ++4 3 ++1 33 +-1 11 ++1 11 +-1 22 ++5 7 +-3 44 +cfn=(132) +calls=11 180 +* 26216 +-1 44 + +fl=(25) +fn=(78) +26 26 ++2 26 ++1 52 ++1 26 ++4 26 ++1 26 ++1 26 ++1 26 ++1 26 ++2 52 ++2 26 ++1 26 ++2 52 ++2 26 ++4 26 ++1 26 + +fl=(55) +fn=(358) +73 388 ++6 776 +-6 388 ++6 388 +-6 1164 ++6 388 ++1 388 +-4 388 ++3 388 +-3 388 ++4 388 ++1 388 +-1 1940 ++6 388 +-5 388 +-1 388 ++6 388 ++4 776 ++4 1164 ++5 2328 ++1 1164 ++8 1552 ++7 776 ++3 3880 +cfi=(6) +cfn=(152) +calls=388 698 +* 503896 +* 388 ++4 1164 ++4 1552 ++6 2716 ++8 388 ++7 1552 ++4 1164 +fi=(5) ++85 388 +fe=(55) +-81 2328 + +ob=(5) /lib/libgcc_s.so.1 +fl=(51) ??? +fn=(232) 0x0000000000002e20 +0 6 + +fn=(226) 0x0000000000002d80 +0 6 + +fn=(238) 0x0000000000013390 +0 11 + +ob=(1) +fl=(55) +fn=(358) +100 210 ++48 7 +cob=(4) +cfi=(150) +cfn=(3458) +calls=1 -86 +* 9 +cob=(4) +cfi=(130) +cfn=(3048) +calls=1 -86 +* 7 +cob=(4) +cfi=(99) +cfn=(1474) +calls=2 29 +* 12 +cob=(4) +cfi=(80) +cfn=(940) +calls=3 32 +* 18 +* 7 + +ob=(2) +fl=(13) +fn=(244) +0 2 +cob=(6) /lib/libm-2.11.1.so +cfi=(52) ??? +cfn=(246) 0x0000000000003ef0 +calls=1 0 +0 6 +0 1 +cob=(6) +cfi=(52) +cfn=(252) 0x0000000000003f90 +calls=1 0 +0 6 +0 1 +cob=(6) +cfi=(52) +cfn=(258) 0x00000000000447c0 +calls=1 0 +0 11 +0 2 + +fn=(460) +0 2 +cob=(11) /home/tclose/Code/MRtrix3/lib/libmrtrix-0_3_4.so +cfi=(60) ??? +cfn=(462) 0x0000000000013ce0 +calls=1 0 +0 6 +0 1 +cob=(11) +cfi=(60) +cfn=(468) 0x0000000000013d80 +calls=1 0 +0 6 +0 1 +cob=(11) +cfi=(60) +cfn=(474) 0x000000000007c360 +calls=1 0 +0 189415 +0 2 + +fn=(1052) 0x00000000004107f8 +0 2 +cob=(12) +cfi=(84) +cfn=(1054) 0x000000000041150c +calls=1 0 +0 6 +0 1 +cob=(12) +cfi=(84) +cfn=(1060) 0x00000000004115a0 +calls=1 0 +0 6 +0 1 +cob=(12) +cfi=(84) +cfn=(1066) 0x0000000000520b60 +calls=1 0 +0 253272 +0 2 + +fn=(264) +0 2 +cob=(7) +cfi=(53) +cfn=(266) +calls=1 0 +0 6 +0 1 +cob=(7) +cfi=(53) +cfn=(272) +calls=1 0 +0 6 +0 1 +cob=(7) +cfi=(53) +cfn=(278) +calls=1 0 +0 2196 +0 2 + +fn=(400) +0 2 +cob=(8) +cfi=(57) +cfn=(402) +calls=1 0 +0 6 +0 1 +cob=(8) +cfi=(57) +cfn=(408) +calls=1 0 +0 6 +0 1 +cob=(8) +cfi=(57) +cfn=(414) +calls=1 0 +0 11 +0 2 + +fn=(176) +0 2 +cob=(3) /usr/lib/valgrind/vgpreload_core-amd64-linux.so +cfi=(39) ??? +cfn=(178) 0x0000000000000510 +calls=1 0 +0 6 +0 1 +cob=(3) +cfi=(39) +cfn=(184) 0x00000000000005b0 +calls=1 0 +0 6 +0 1 +cob=(3) +cfi=(39) +cfn=(190) 0x0000000000000710 +calls=1 0 +0 11 +0 2 + +fn=(420) +0 2 +cob=(9) /usr/lib/libgsl.so.0.14.0 +cfi=(58) ??? +cfn=(422) 0x000000000004ab80 +calls=1 0 +0 6 +0 1 +cob=(9) +cfi=(58) +cfn=(428) 0x000000000004ac20 +calls=1 0 +0 6 +0 1 +cob=(9) +cfi=(58) +cfn=(434) 0x00000000001b6ea0 +calls=1 0 +0 11 +0 2 + +fn=(224) +0 2 +cob=(5) +cfi=(51) +cfn=(226) +calls=1 0 +0 6 +0 1 +cob=(5) +cfi=(51) +cfn=(232) +calls=1 0 +0 6 +0 1 +cob=(5) +cfi=(51) +cfn=(238) +calls=1 0 +0 11 +0 2 + +fn=(440) +0 2 +cob=(10) +cfi=(59) +cfn=(442) +calls=1 0 +0 6 +0 1 +cob=(10) +cfi=(59) +cfn=(448) +calls=1 0 +0 6 +0 1 +cob=(10) +cfi=(59) +cfn=(454) +calls=1 0 +0 11 +0 2 + +ob=(11) +fl=(60) +fn=(918) global constructors keyed to series.cpp +0 3 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 + +fn=(928) global constructors keyed to axis.cpp +0 5 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 5663 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1498 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 + +fn=(972) global constructors keyed to mmap.cpp +0 3 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 + +fn=(992) global constructors keyed to mapper.cpp +0 3 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 + +fn=(1028) global constructors keyed to reslice.cpp +0 3 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 10 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 8 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 + +fn=(1030) global constructors keyed to LU.cpp +0 3 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 + +fn=(1276) std::vector >::_M_insert_aux(__gnu_cxx::__normal_iterator > >, char const* const&) +0 143 +cob=(7) +cfi=(53) +cfn=(880) +calls=5 0 +0 582 +0 75 +cob=(4) +cfi=(90) +cfn=(1282) +calls=5 47 +0 169 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1698 +0 40 +cob=(4) +cfi=(90) +cfn=(1282) +calls=5 47 +0 120 +0 16 +cob=(7) +cfi=(53) +cfn=(1174) +calls=1 0 +0 81 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1307 +0 64 + +fn=(2090) std::_Vector_base >::_M_allocate(unsigned long) +0 20 +cob=(7) +cfi=(53) +cfn=(880) +calls=2 0 +0 220 + +fn=(2148) void std::__introsort_loop<__gnu_cxx::__normal_iterator*, std::vector, std::allocator > > >, long>(__gnu_cxx::__normal_iterator*, std::vector, std::allocator > > >, __gnu_cxx::__normal_iterator*, std::vector, std::allocator > > >, long) +0 42 + +fn=(2482) MR::DataType::parse(std::string const&) +0 54 +cob=(7) +cfi=(53) +cfn=(2256) +calls=3 0 +0 1131 +0 18 +cob=(7) +cfi=(53) +cfn=(1372) +calls=3 0 +0 36 +0 36 +cob=(4) +cfi=(118) +cfn=(2270) +calls=3 47 +0 36 +0 96 +cob=(4) +cfi=(118) +cfn=(2270) +calls=24 47 +0 288 +0 144 +cob=(7) +cfi=(53) +cfn=(1594) +calls=3 0 +0 156 +0 51 +cob=(7) +cfi=(53) +cfn=(1594) +calls=3 0 +0 158 +0 14 +cob=(7) +cfi=(53) +cfn=(1594) +calls=2 0 +0 110 +0 10 +cfn=(3398) bool std::operator==, std::allocator >(std::basic_string, std::allocator > const&, char const*) +calls=2 0 +0 128 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1010 +0 10 +cfn=(3398) +calls=2 0 +0 144 +0 26 +cob=(7) +cfi=(53) +cfn=(1310) +calls=3 0 +0 246 +0 15 + +fn=(2692) std::vector >::_M_fill_insert(__gnu_cxx::__normal_iterator > >, unsigned long, unsigned char* const&) +0 60 +cob=(4) +cfi=(90) +cfn=(1282) +calls=1 47 +0 24 +0 9 +cob=(4) +cfi=(90) +cfn=(1282) +calls=1 47 +0 24 +0 11 +cob=(7) +cfi=(53) +cfn=(880) +calls=1 0 +0 223 +0 7 + +fn=(2698) MR::File::MMap::map() +0 16 +cob=(12) +cfi=(84) +cfn=(2012) std::basic_string, std::allocator > std::operator+, std::allocator >(char const*, std::basic_string, std::allocator > const&) +calls=1 0 +0 494 +0 3 +cob=(7) +cfi=(53) +cfn=(1258) +calls=1 0 +0 20 +0 4 +cob=(7) +cfi=(53) +cfn=(1772) +calls=1 0 +0 326 +0 2 +cfn=(2206) MR::cmdline_debug(std::string const&) +calls=1 0 +0 7 +0 13 +cob=(4) +cfi=(95) +cfn=(1350) +calls=1 37 +0 10 +0 20 +cob=(4) +cfi=(104) +cfn=(1674) +calls=1 82 +0 7 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1697 +0 14 +cob=(4) +cfi=(120) +cfn=(2708) +calls=1 82 +0 6 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1707 +0 14 +cob=(7) +cfi=(53) +cfn=(722) +calls=1 0 +0 97 +0 21 +cob=(7) +cfi=(53) +cfn=(728) +calls=1 0 +0 708 +0 16 +cob=(7) +cfi=(53) +cfn=(492) +calls=1 0 +0 39 +0 10 +cob=(7) +cfi=(53) +cfn=(728) +calls=1 0 +0 708 +0 3 +cob=(7) +cfi=(53) +cfn=(2714) +calls=1 0 +0 2705 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1600 +0 12 +cob=(12) +cfi=(84) +cfn=(2736) char* std::string::_S_construct(char*, char*, std::allocator const&, std::forward_iterator_tag) +calls=1 0 +0 3586 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1414 +0 8 +cob=(7) +cfi=(53) +cfn=(1264) +calls=1 0 +0 28 +0 20 +cob=(7) +cfi=(53) +cfn=(746) +calls=1 0 +0 12 +0 10 +cob=(7) +cfi=(53) +cfn=(1556) +calls=1 0 +0 58 +0 5 +cob=(7) +cfi=(53) +cfn=(722) +calls=1 0 +0 97 +0 18 +cob=(7) +cfi=(53) +cfn=(728) +calls=1 0 +0 708 +0 15 +cob=(7) +cfi=(53) +cfn=(492) +calls=1 0 +0 39 +0 9 +cob=(7) +cfi=(53) +cfn=(728) +calls=1 0 +0 708 +0 3 +cob=(7) +cfi=(53) +cfn=(2750) +calls=1 0 +0 2583 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1682 +0 12 +cob=(12) +cfi=(84) +cfn=(2736) +calls=1 0 +0 200 +0 8 +cob=(7) +cfi=(53) +cfn=(1264) +calls=1 0 +0 28 +0 20 +cob=(7) +cfi=(53) +cfn=(746) +calls=1 0 +0 12 +0 8 +cob=(7) +cfi=(53) +cfn=(1556) +calls=1 0 +0 58 +0 6 +cob=(12) +cfi=(84) +cfn=(2012) +calls=1 0 +0 554 +0 4 +cob=(7) +cfi=(53) +cfn=(1258) +calls=1 0 +0 20 +0 4 +cob=(7) +cfi=(53) +cfn=(1772) +calls=1 0 +0 537 +0 6 +cob=(12) +cfi=(84) +cfn=(1396) std::basic_string, std::allocator > std::operator+, std::allocator >(std::basic_string, std::allocator > const&, std::basic_string, std::allocator > const&) +calls=1 0 +0 336 +0 4 +cob=(7) +cfi=(53) +cfn=(1258) +calls=1 0 +0 20 +0 4 +cob=(7) +cfi=(53) +cfn=(1772) +calls=1 0 +0 370 +0 6 +cob=(12) +cfi=(84) +cfn=(1396) +calls=1 0 +0 392 +0 4 +cob=(7) +cfi=(53) +cfn=(1258) +calls=1 0 +0 20 +0 4 +cob=(7) +cfi=(53) +cfn=(1772) +calls=1 0 +0 526 +0 4 +cob=(7) +cfi=(53) +cfn=(1258) +calls=1 0 +0 20 +0 2 +cob=(4) +cfi=(69) +cfn=(642) +calls=1 26 +0 22 +0 4 +cob=(7) +cfi=(53) +cfn=(1772) +calls=1 0 +0 340 +0 4 +cob=(7) +cfi=(53) +cfn=(1258) +calls=1 0 +0 20 +0 4 +cob=(7) +cfi=(53) +cfn=(1772) +calls=1 0 +0 362 +0 2 +cfn=(2206) +calls=1 0 +0 7 +0 54 +cob=(7) +cfi=(53) +cfn=(1310) +calls=1 0 +0 82 +0 7 +cob=(7) +cfi=(53) +cfn=(1310) +calls=1 0 +0 113 +0 7 +cob=(7) +cfi=(53) +cfn=(1310) +calls=1 0 +0 124 +0 7 +cob=(7) +cfi=(53) +cfn=(1310) +calls=1 0 +0 82 +0 7 +cob=(7) +cfi=(53) +cfn=(1310) +calls=1 0 +0 82 +0 7 +cob=(7) +cfi=(53) +cfn=(1310) +calls=1 0 +0 82 +0 7 +cob=(7) +cfi=(53) +cfn=(1310) +calls=1 0 +0 126 +0 7 +cob=(7) +cfi=(53) +cfn=(1310) +calls=1 0 +0 126 +0 7 +cob=(7) +cfi=(53) +cfn=(1310) +calls=1 0 +0 82 +0 7 +cob=(7) +cfi=(53) +cfn=(1310) +calls=1 0 +0 82 +0 7 +cob=(7) +cfi=(53) +cfn=(1310) +calls=1 0 +0 113 +0 7 +cob=(7) +cfi=(53) +cfn=(1310) +calls=1 0 +0 126 +0 7 +cob=(7) +cfi=(53) +cfn=(1310) +calls=1 0 +0 82 +0 7 +cob=(7) +cfi=(53) +cfn=(1310) +calls=1 0 +0 82 +0 74 + +fn=(468) +0 6 + +fn=(920) global constructors keyed to tree.cpp +0 3 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 + +fn=(974) global constructors keyed to analyse.cpp +0 3 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 + +fn=(994) global constructors keyed to default.cpp +0 3 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 + +fn=(1032) global constructors keyed to study.cpp +0 3 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 + +fn=(1304) std::vector >::_M_insert_aux(__gnu_cxx::__normal_iterator > >, unsigned long const&) +0 112 +cob=(7) +cfi=(53) +cfn=(880) +calls=4 0 +0 610 +0 60 +cob=(4) +cfi=(90) +cfn=(1282) +calls=4 47 +0 96 +0 32 +cob=(4) +cfi=(90) +cfn=(1282) +calls=4 47 +0 96 +0 60 + +fn=(1424) std::vector >::_M_insert_aux(__gnu_cxx::__normal_iterator > >, MR::ArgBase const&) +0 93 +cob=(7) +cfi=(53) +cfn=(880) +calls=5 0 +0 550 +0 133 +cob=(7) +cfi=(53) +cfn=(1174) +calls=1 0 +0 81 +0 89 + +fn=(2030) MR::cmdline_info(std::string const&) +0 21 + +fn=(2046) MR::Image::NameParser::parse(std::string const&, unsigned long) +0 28 +cob=(7) +cfi=(53) +cfn=(1264) +calls=2 0 +0 56 +0 10 +cob=(4) +cfi=(95) +cfn=(1350) +calls=2 37 +0 20 +0 38 +cob=(7) +cfi=(53) +cfn=(1246) +calls=2 0 +0 432 +0 14 +cob=(7) +cfi=(53) +cfn=(1264) +calls=2 0 +0 56 +0 4 +cob=(7) +cfi=(53) +cfn=(1468) +calls=2 0 +0 30 +0 10 +cob=(7) +cfi=(53) +cfn=(1246) +calls=2 0 +0 432 +0 22 +cob=(7) +cfi=(53) +cfn=(1446) +calls=2 0 +0 410 +0 52 +cob=(7) +cfi=(53) +cfn=(2056) +calls=2 0 +0 98 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1466 +0 14 +cfn=(2062) MR::Image::NameParser::insert_str(std::string const&) +calls=2 0 +0 10825 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 911 +0 38 +cob=(7) +cfi=(53) +cfn=(1446) +calls=2 0 +0 438 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1434 +0 14 +cob=(7) +cfi=(53) +cfn=(1468) +calls=2 0 +0 30 +0 2 + +fn=(2102) MR::Image::NameParserItem* std::__uninitialized_move_a >(MR::Image::NameParserItem*, MR::Image::NameParserItem*, MR::Image::NameParserItem*, std::allocator&) +0 84 + +fn=(2336) std::vector >::operator=(std::vector > const&) +0 38 +cob=(7) +cfi=(53) +cfn=(880) +calls=1 0 +0 110 +0 5 +cob=(4) +cfi=(90) +cfn=(1282) +calls=1 47 +0 62 +0 7 + +fn=(2674) MR::DataType::bits() const +0 44 + +fn=(462) +0 6 + +fn=(474) +0 11 +cfn=(478) global constructors keyed to select_cmdline.cpp +calls=1 0 +0 105958 +0 78 +cfn=(1032) +calls=1 0 +0 94 +cfn=(1030) +calls=1 0 +0 94 +cfn=(1028) +calls=1 0 +0 236 +cfn=(1026) global constructors keyed to nifti1_utils.cpp +calls=1 0 +0 94 +cfn=(1024) global constructors keyed to element.cpp +calls=1 0 +0 94 +cfn=(1022) global constructors keyed to confirm.cpp +calls=1 0 +0 94 +cfn=(1020) global constructors keyed to mosaic.cpp +calls=1 0 +0 94 +cfn=(1018) global constructors keyed to xds.cpp +calls=1 0 +0 94 +cfn=(1016) global constructors keyed to dicom.cpp +calls=1 0 +0 94 +cfn=(1014) global constructors keyed to key_value.cpp +calls=1 0 +0 94 +cfn=(1006) global constructors keyed to exec.cpp +calls=1 0 +0 2048 +cfn=(1004) global constructors keyed to image.cpp +calls=1 0 +0 94 +cfn=(1002) global constructors keyed to header.cpp +calls=1 0 +0 94 +cfn=(1000) global constructors keyed to patient.cpp +calls=1 0 +0 94 +cfn=(998) global constructors keyed to nifti1_gz.cpp +calls=1 0 +0 94 +cfn=(996) global constructors keyed to args.cpp +calls=1 0 +0 172 +cfn=(994) +calls=1 0 +0 94 +cfn=(992) +calls=1 0 +0 94 +cfn=(990) global constructors keyed to app.cpp +calls=1 0 +0 291 +cfn=(988) global constructors keyed to progressbar.cpp +calls=1 0 +0 94 +cfn=(976) global constructors keyed to gz.cpp +calls=1 0 +0 1499 +cfn=(974) +calls=1 0 +0 94 +cfn=(972) +calls=1 0 +0 94 +cfn=(970) global constructors keyed to config.cpp +calls=1 0 +0 167 +cfn=(928) +calls=1 0 +0 7332 +cfn=(926) global constructors keyed to mri.cpp +calls=1 0 +0 94 +cfn=(856) global constructors keyed to pipe.cpp +calls=1 0 +0 94 +cfn=(924) global constructors keyed to list.cpp +calls=1 0 +0 663 +cfn=(922) global constructors keyed to nifti1.cpp +calls=1 0 +0 94 +cfn=(920) +calls=1 0 +0 94 +cfn=(918) +calls=1 0 +0 94 +cfn=(916) global constructors keyed to base.cpp +calls=1 0 +0 94 +cfn=(914) global constructors keyed to name_parser.cpp +calls=1 0 +0 94 +cfn=(912) global constructors keyed to data_type.cpp +calls=1 0 +0 94 +cfn=(862) global constructors keyed to dict.cpp +calls=1 0 +0 68016 +cfn=(860) global constructors keyed to mrtrix.cpp +calls=1 0 +0 94 +cfn=(860) +calls=1 0 +0 94 +cfn=(858) global constructors keyed to quick_scan.cpp +calls=1 0 +0 94 +cfn=(856) +calls=1 0 +0 94 +0 124 + +fn=(922) +0 3 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 + +fn=(976) +0 3 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 1467 + +fn=(996) +0 3 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 16 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 + +fn=(1006) +0 5 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(4) +cfi=(83) +cfn=(1012) +calls=1 178 +0 5 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1874 +0 7 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 + +fn=(1014) +0 3 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 + +fn=(2040) MR::Image::ParsedNameList::parse_scan_check(std::string const&, unsigned long) +0 52 +cfn=(2046) +calls=2 0 +0 16884 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 867 +0 6 +cfn=(2114) MR::Image::ParsedNameList::scan(MR::Image::NameParser&) +calls=2 0 +0 9871 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1011 +0 32 +cfn=(2148) +calls=2 0 +0 42 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1728 +0 6 +cfn=(2154) void std::__final_insertion_sort<__gnu_cxx::__normal_iterator*, std::vector, std::allocator > > > >(__gnu_cxx::__normal_iterator*, std::vector, std::allocator > > >, __gnu_cxx::__normal_iterator*, std::vector, std::allocator > > >) +calls=2 0 +0 1754 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1730 +0 6 +cfn=(2166) MR::Image::ParsedNameList::count() const +calls=2 0 +0 58 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 876 +0 16 +cfn=(2172) MR::Image::NameParser::~NameParser() +calls=2 0 +0 672 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 794 +0 18 + +fn=(2096) MR::Image::NameParserItem::NameParserItem(MR::Image::NameParserItem const&) +0 32 +cob=(7) +cfi=(53) +cfn=(1258) +calls=2 0 +0 40 +0 40 +cob=(4) +cfi=(90) +cfn=(1282) +calls=2 47 +0 48 +0 16 + +fn=(2108) MR::Image::NameParserItem::~NameParserItem() +0 16 +cob=(7) +cfi=(53) +cfn=(1468) +calls=2 0 +0 30 + +fn=(2154) +0 22 +cfn=(2160) void std::__insertion_sort<__gnu_cxx::__normal_iterator*, std::vector, std::allocator > > > >(__gnu_cxx::__normal_iterator*, std::vector, std::allocator > > >, __gnu_cxx::__normal_iterator*, std::vector, std::allocator > > >) +calls=2 0 +0 44 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1676 +0 12 + +fn=(2204) MR::File::KeyValue::open(std::string const&, char const*) +0 60 +cob=(7) +cfi=(53) +cfn=(1586) +calls=3 0 +0 114 +0 18 +cob=(12) +cfi=(84) +cfn=(2012) +calls=3 0 +0 1248 +0 9 +cob=(7) +cfi=(53) +cfn=(1258) +calls=3 0 +0 60 +0 12 +cob=(7) +cfi=(53) +cfn=(1772) +calls=3 0 +0 1103 +0 6 +cfn=(2206) +calls=3 0 +0 21 +0 48 +cob=(7) +cfi=(53) +cfn=(1632) +calls=3 0 +0 11197 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 2282 +0 21 +cob=(7) +cfi=(53) +cfn=(1712) +calls=3 0 +0 24 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 2154 +0 60 +cob=(7) +cfi=(53) +cfn=(1730) +calls=3 0 +0 1890 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 2531 +0 18 +cob=(4) +cfi=(69) +cfn=(642) +calls=3 26 +0 66 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1690 +0 15 +cob=(7) +cfi=(53) +cfn=(2232) +calls=3 0 +0 233 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1538 +0 36 +cob=(7) +cfi=(53) +cfn=(1310) +calls=3 0 +0 246 +0 12 +cob=(7) +cfi=(53) +cfn=(1264) +calls=3 0 +0 84 +0 39 +cob=(7) +cfi=(53) +cfn=(1372) +calls=3 0 +0 36 +0 27 +cob=(7) +cfi=(53) +cfn=(1310) +calls=3 0 +0 246 +0 21 +cob=(7) +cfi=(53) +cfn=(1310) +calls=3 0 +0 288 +0 39 + +fn=(2378) std::vector >::operator=(std::vector > const&) +0 38 +cob=(7) +cfi=(53) +cfn=(880) +calls=1 0 +0 110 +0 5 +cob=(4) +cfi=(90) +cfn=(1282) +calls=1 47 +0 62 +0 7 + +fn=(2686) std::vector, std::allocator > >::_M_fill_insert(__gnu_cxx::__normal_iterator*, std::vector, std::allocator > > >, unsigned long, MR::RefPtr const&) +0 84 +cob=(7) +cfi=(53) +cfn=(880) +calls=1 0 +0 126 +0 6 + +fn=(2862) MR::File::MMap::~MMap() +0 17 +cob=(12) +cfi=(84) +cfn=(2012) +calls=1 0 +0 377 +0 4 +cob=(7) +cfi=(53) +cfn=(1258) +calls=1 0 +0 20 +0 4 +cob=(7) +cfi=(53) +cfn=(1772) +calls=1 0 +0 460 +0 2 +cfn=(2206) +calls=1 0 +0 7 +0 12 +cob=(4) +cfi=(120) +cfn=(2868) +calls=1 82 +0 5 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1741 +0 4 +cob=(4) +cfi=(104) +cfn=(2874) +calls=1 82 +0 7 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1673 +0 18 +cob=(7) +cfi=(53) +cfn=(1310) +calls=1 0 +0 82 +0 11 +cob=(7) +cfi=(53) +cfn=(1310) +calls=1 0 +0 113 +0 13 + +fn=(3928) MR::(anonymous namespace)::display_func_cmdline(MR::ProgressInfo&) +0 56 +cob=(4) +cfi=(153) +cfn=(3934) +calls=8 28 +0 13860 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1870 +0 48 + +fn=(2856) MR::Image::Handler::Default::~Default() +0 24 +cfn=(2862) +calls=1 0 +0 4570 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 747 +0 2 +cob=(7) +cfi=(53) +cfn=(1174) +calls=1 0 +0 81 +0 3 +cob=(7) +cfi=(53) +cfn=(1174) +calls=1 0 +0 81 +0 7 +cob=(7) +cfi=(53) +cfn=(1174) +calls=1 0 +0 81 +0 7 +cob=(7) +cfi=(53) +cfn=(1174) +calls=1 0 +0 81 +0 4 +cob=(7) +cfi=(53) +cfn=(1174) +calls=1 0 +0 81 +0 2 +cob=(7) +cfi=(53) +cfn=(1174) +calls=1 0 +0 81 +0 7 + +fn=(924) +0 3 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 9 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 9 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 9 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 9 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 9 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 9 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 9 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 10 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 + +fn=(970) +0 3 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 11 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 + +fn=(1016) +0 3 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 + +fn=(1240) MR::App::App(int, char**, char const**, MR::Argument const*, MR::Option const*, unsigned long const*, char const*, char const*) +0 46 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 318 +0 5 +cob=(7) +cfi=(53) +cfn=(1246) +calls=1 0 +0 2127 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1650 +0 5 +cob=(7) +cfi=(53) +cfn=(1264) +calls=1 0 +0 28 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1506 +0 33 +cfn=(1270) MR::App::sort_arguments(int, char**) +calls=1 0 +0 28851 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 830 +0 2 +cob=(4) +cfi=(91) +cfn=(1326) +calls=1 32 +0 8 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1642 +0 2 +cob=(4) +cfi=(93) +cfn=(1334) +calls=1 211 +0 10226 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1673 +0 1 +cfn=(1344) MR::File::Config::init() +calls=1 0 +0 17122 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 776 +0 10 +cob=(7) +cfi=(53) +cfn=(1258) +calls=1 0 +0 20 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1426 +0 17 + +fn=(2182) MR::Image::Format::MRtrix::read(MR::Image::Header&) const +0 18 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 225 +0 16 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 219 +0 16 +cob=(7) +cfi=(53) +cfn=(1446) +calls=1 0 +0 201 +0 7 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 100 +0 5 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 100 +0 9 +cob=(7) +cfi=(53) +cfn=(1446) +calls=1 0 +0 201 +0 8 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 100 +0 32 +cob=(7) +cfi=(53) +cfn=(722) +calls=1 0 +0 97 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1491 +0 23 +cob=(7) +cfi=(53) +cfn=(728) +calls=1 0 +0 708 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 2322 +0 8 +cob=(7) +cfi=(53) +cfn=(1608) +calls=1 0 +0 265 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1938 +0 5 +cob=(7) +cfi=(53) +cfn=(728) +calls=1 0 +0 708 +0 4 +cfn=(2204) +calls=1 0 +0 21097 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 848 +0 53 +cfn=(2238) MR::File::KeyValue::next() +calls=1 0 +0 8155 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 786 +0 348 +cfn=(2238) +calls=87 0 +0 297572 +0 785 +cob=(7) +cfi=(53) +cfn=(2256) +calls=87 0 +0 24670 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1516 +0 522 +cob=(7) +cfi=(53) +cfn=(1372) +calls=87 0 +0 1044 +0 870 +cob=(4) +cfi=(118) +cfn=(2270) +calls=87 47 +0 1044 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1724 +0 2220 +cob=(4) +cfi=(118) +cfn=(2270) +calls=740 47 +0 8880 +0 3830 +cob=(7) +cfi=(53) +cfn=(1594) +calls=87 0 +0 3908 +0 182 +cfn=(2276) MR::parse_ints(std::string const&, int) +calls=1 0 +0 31607 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 783 +0 3 +cfn=(2336) +calls=1 0 +0 222 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 810 +0 5 +cob=(7) +cfi=(53) +cfn=(1174) +calls=2 0 +0 162 +0 870 +cob=(7) +cfi=(53) +cfn=(1310) +calls=87 0 +0 7134 +0 603 +cob=(7) +cfi=(53) +cfn=(1594) +calls=86 0 +0 3794 +0 178 +cfn=(2342) MR::parse_floats(std::string const&) +calls=1 0 +0 19852 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 776 +0 5 +cfn=(2378) +calls=1 0 +0 222 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 834 +0 513 +cob=(7) +cfi=(53) +cfn=(1594) +calls=85 0 +0 4265 +0 175 +cob=(7) +cfi=(53) +cfn=(1264) +calls=1 0 +0 28 +0 505 +cob=(7) +cfi=(53) +cfn=(1594) +calls=84 0 +0 3776 +0 173 +cob=(7) +cfi=(53) +cfn=(1264) +calls=1 0 +0 28 +0 499 +cob=(7) +cfi=(53) +cfn=(1594) +calls=83 0 +0 4161 +0 171 +cob=(7) +cfi=(53) +cfn=(1264) +calls=1 0 +0 28 +0 493 +cob=(7) +cfi=(53) +cfn=(1594) +calls=82 0 +0 4101 +0 177 +cfn=(2462) MR::Image::Axes::Dim::operator=(unsigned long) +calls=1 0 +0 6131 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 817 +0 589 +cob=(7) +cfi=(53) +cfn=(1594) +calls=82 0 +0 3608 +0 656 +cob=(7) +cfi=(53) +cfn=(1594) +calls=82 0 +0 4112 +0 174 +cfn=(2384) MR::split(std::string const&, char const*, bool, unsigned long) +calls=1 0 +0 2580 +0 4 +cob=(12) +cfi=(84) +cfn=(2402) std::vector >::operator=(std::vector > const&) +calls=1 0 +0 360 +0 4 +cob=(12) +cfi=(84) +cfn=(2410) std::vector >::~vector() +calls=2 0 +0 338 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 854 +0 488 +cob=(7) +cfi=(53) +cfn=(1594) +calls=81 0 +0 3577 +0 172 +cfn=(2384) +calls=1 0 +0 5540 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 749 +0 5 +cob=(12) +cfi=(84) +cfn=(2402) +calls=1 0 +0 320 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 902 +0 2 +cob=(4) +cfi=(100) +cfn=(1476) +calls=1 25 +0 31 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1698 +0 10 +cfn=(2482) +calls=1 0 +0 966 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 785 +0 483 +cob=(7) +cfi=(53) +cfn=(1594) +calls=80 0 +0 4049 +0 622 +cob=(7) +cfi=(53) +cfn=(1594) +calls=77 0 +0 4368 +0 1721 +cfn=(2342) +calls=3 0 +0 48059 +0 24 +cfn=(2450) void std::vector >::_M_range_insert<__gnu_cxx::__normal_iterator > > >(__gnu_cxx::__normal_iterator > >, __gnu_cxx::__normal_iterator > >, __gnu_cxx::__normal_iterator > >, std::forward_iterator_tag) +calls=3 0 +0 1156 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1573 +0 128 +cfn=(2456) std::vector >::~vector() +calls=64 0 +0 5440 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 758 +0 72 +cfn=(2488) MR::Image::Axes::parse(unsigned long, std::string const&) +calls=1 0 +0 13825 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 912 +0 55 +cob=(7) +cfi=(53) +cfn=(1264) +calls=1 0 +0 123 +0 15 +cob=(7) +cfi=(53) +cfn=(1264) +calls=3 0 +0 257 +0 70 +cob=(7) +cfi=(53) +cfn=(1264) +calls=1 0 +0 123 +0 15 +cob=(7) +cfi=(53) +cfn=(1264) +calls=3 0 +0 257 +0 270 +cob=(7) +cfi=(53) +cfn=(1264) +calls=16 0 +0 448 +0 20 +cfn=(2500) T.1670 +calls=1 0 +0 1188 +0 150 +cob=(12) +cfi=(84) +cfn=(2512) MR::Math::Matrix::operator=(MR::Math::Matrix const&) +calls=1 0 +0 1378 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 886 +0 4 +cob=(9) +cfi=(58) +cfn=(2522) gsl_block_float_free +calls=1 0 +0 1807 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 939 +0 14 +cob=(4) +cfi=(100) +cfn=(1476) +calls=1 25 +0 22 +0 9 +cob=(7) +cfi=(53) +cfn=(722) +calls=1 0 +0 97 +0 22 +cob=(7) +cfi=(53) +cfn=(728) +calls=1 0 +0 708 +0 16 +cob=(7) +cfi=(53) +cfn=(492) +calls=1 0 +0 39 +0 9 +cob=(7) +cfi=(53) +cfn=(1812) +calls=1 0 +0 197 +0 6 +cob=(7) +cfi=(53) +cfn=(1528) +calls=1 0 +0 21 +0 3 +cob=(7) +cfi=(53) +cfn=(728) +calls=1 0 +0 708 +0 6 +cob=(7) +cfi=(53) +cfn=(2532) +calls=1 0 +0 1570 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 2395 +0 6 +cob=(7) +cfi=(53) +cfn=(2544) +calls=1 0 +0 2472 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1656 +0 3 +cob=(7) +cfi=(53) +cfn=(1594) +calls=1 0 +0 52 +0 7 +cob=(7) +cfi=(53) +cfn=(1264) +calls=1 0 +0 123 +0 10 +cfn=(2040) +calls=1 0 +0 4064 +0 10 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 15 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 15 +0 20 +cob=(7) +cfi=(53) +cfn=(1258) +calls=1 0 +0 20 +0 3 +cob=(7) +cfi=(53) +cfn=(1258) +calls=1 0 +0 20 +0 9 +cfn=(2558) std::vector >::_M_insert_aux(__gnu_cxx::__normal_iterator > >, MR::File::Entry const&) +calls=1 0 +0 255 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1440 +0 6 +cfn=(2564) MR::Image::ParsedNameList::~ParsedNameList() +calls=1 0 +0 296 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 838 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 15 +0 2 +cob=(7) +cfi=(53) +cfn=(2570) +calls=1 0 +0 201 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 2106 +0 4 +cob=(7) +cfi=(53) +cfn=(1174) +calls=1 0 +0 81 +0 2 +cob=(12) +cfi=(84) +cfn=(2410) +calls=1 0 +0 169 +0 2 +cob=(12) +cfi=(84) +cfn=(2410) +calls=1 0 +0 169 +0 2 +cfn=(2456) +calls=1 0 +0 4 +0 2 +cfn=(2456) +calls=1 0 +0 85 +0 2 +cfn=(2456) +calls=1 0 +0 158 +0 2 +cfn=(2456) +calls=1 0 +0 85 +0 4 +cob=(7) +cfi=(53) +cfn=(1174) +calls=1 0 +0 81 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 15 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 100 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 100 +0 2 +cob=(12) +cfi=(84) +cfn=(2576) MR::File::KeyValue::~KeyValue() +calls=1 0 +0 955 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 790 +0 8 +cob=(7) +cfi=(53) +cfn=(1310) +calls=1 0 +0 82 +0 433 +cob=(7) +cfi=(53) +cfn=(1258) +calls=16 0 +0 3427 +0 64 +cob=(7) +cfi=(53) +cfn=(1258) +calls=16 0 +0 240 +0 64 +cob=(12) +cfi=(84) +cfn=(2416) std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::_M_insert_unique_(std::_Rb_tree_const_iterator >, std::pair const&) +calls=16 0 +0 10533 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 2422 +0 80 +cob=(12) +cfi=(84) +cfn=(2432) std::pair::~pair() +calls=16 0 +0 496 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 766 +0 48 +cob=(7) +cfi=(53) +cfn=(1468) +calls=16 0 +0 112 +0 321 +cfn=(2342) +calls=61 0 +0 1132769 +0 488 +cfn=(2450) +calls=61 0 +0 13979 +0 69 +cfn=(2500) +calls=1 0 +0 411 +0 2210 +cob=(12) +cfi=(84) +cfn=(2512) +calls=1 0 +0 3211 +0 4 +cob=(9) +cfi=(58) +cfn=(2522) +calls=1 0 +0 209 +0 1 + +fn=(2238) +0 4034 +cob=(7) +cfi=(53) +cfn=(1730) +calls=107 0 +0 53515 +0 1070 +cob=(7) +cfi=(53) +cfn=(1788) +calls=107 0 +0 5799 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1474 +0 535 +cob=(7) +cfi=(53) +cfn=(1446) +calls=107 0 +0 25944 +0 535 +cob=(7) +cfi=(53) +cfn=(1794) +calls=107 0 +0 5291 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1722 +0 856 +cob=(7) +cfi=(53) +cfn=(1800) +calls=107 0 +0 5512 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1690 +0 963 +cob=(7) +cfi=(53) +cfn=(1446) +calls=107 0 +0 26900 +0 321 +cob=(7) +cfi=(53) +cfn=(1264) +calls=107 0 +0 13161 +0 1177 +cob=(7) +cfi=(53) +cfn=(1594) +calls=107 0 +0 4738 +0 1046 +cob=(7) +cfi=(53) +cfn=(1788) +calls=104 0 +0 4872 +0 832 +cob=(7) +cfi=(53) +cfn=(1446) +calls=104 0 +0 21379 +0 520 +cob=(7) +cfi=(53) +cfn=(1794) +calls=104 0 +0 5144 +0 832 +cob=(7) +cfi=(53) +cfn=(1800) +calls=104 0 +0 5616 +0 1248 +cob=(7) +cfi=(53) +cfn=(1446) +calls=104 0 +0 22084 +0 312 +cob=(7) +cfi=(53) +cfn=(1264) +calls=104 0 +0 12507 +0 1664 +cob=(7) +cfi=(53) +cfn=(1446) +calls=104 0 +0 25136 +0 520 +cob=(7) +cfi=(53) +cfn=(1794) +calls=104 0 +0 8676 +0 827 +cob=(7) +cfi=(53) +cfn=(1800) +calls=103 0 +0 5273 +0 1133 +cob=(7) +cfi=(53) +cfn=(1446) +calls=103 0 +0 25721 +0 312 +cob=(7) +cfi=(53) +cfn=(1264) +calls=104 0 +0 9797 +0 1151 +cob=(12) +cfi=(84) +cfn=(2012) +calls=1 0 +0 381 +0 3 +cob=(7) +cfi=(53) +cfn=(1258) +calls=1 0 +0 20 +0 4 +cob=(7) +cfi=(53) +cfn=(1772) +calls=1 0 +0 369 +0 6 +cob=(12) +cfi=(84) +cfn=(1396) +calls=1 0 +0 817 +0 4 +cob=(7) +cfi=(53) +cfn=(1258) +calls=1 0 +0 20 +0 4 +cob=(7) +cfi=(53) +cfn=(1772) +calls=1 0 +0 374 +0 2 +cfn=(2030) +calls=1 0 +0 7 +0 1946 +cob=(7) +cfi=(53) +cfn=(1372) +calls=107 0 +0 1284 +0 2014 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 57 +0 13 +cob=(7) +cfi=(53) +cfn=(1712) +calls=3 0 +0 24 +0 648 +cob=(7) +cfi=(53) +cfn=(1310) +calls=107 0 +0 8774 +0 541 +cob=(7) +cfi=(53) +cfn=(1310) +calls=1 0 +0 82 +0 7 +cob=(7) +cfi=(53) +cfn=(1310) +calls=1 0 +0 113 +0 7 +cob=(7) +cfi=(53) +cfn=(1310) +calls=1 0 +0 82 +0 7 +cob=(7) +cfi=(53) +cfn=(1310) +calls=1 0 +0 82 +0 619 +cob=(7) +cfi=(53) +cfn=(1310) +calls=103 0 +0 8446 +0 727 +cob=(7) +cfi=(53) +cfn=(1310) +calls=104 0 +0 8528 +0 110 +cob=(7) +cfi=(53) +cfn=(1310) +calls=1 0 +0 82 +0 3671 +cob=(7) +cfi=(53) +cfn=(1310) +calls=106 0 +0 8692 +0 1068 + +fn=(2276) +0 43 +cob=(7) +cfi=(53) +cfn=(2282) +calls=1 0 +0 88 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1634 +0 15 +cob=(7) +cfi=(53) +cfn=(2282) +calls=3 0 +0 266 +0 48 +cob=(7) +cfi=(53) +cfn=(1446) +calls=4 0 +0 748 +0 20 +cob=(7) +cfi=(53) +cfn=(1794) +calls=4 0 +0 196 +0 32 +cob=(7) +cfi=(53) +cfn=(1800) +calls=4 0 +0 204 +0 36 +cob=(7) +cfi=(53) +cfn=(1446) +calls=4 0 +0 907 +0 40 +cob=(7) +cfi=(53) +cfn=(1372) +calls=4 0 +0 48 +0 26 +cob=(4) +cfi=(118) +cfn=(2270) +calls=5 47 +0 60 +0 86 +cob=(7) +cfi=(53) +cfn=(1594) +calls=4 0 +0 176 +0 125 +cob=(7) +cfi=(53) +cfn=(1446) +calls=4 0 +0 748 +0 8 +cob=(7) +cfi=(53) +cfn=(722) +calls=4 0 +0 388 +0 108 +cob=(7) +cfi=(53) +cfn=(728) +calls=4 0 +0 2832 +0 68 +cob=(7) +cfi=(53) +cfn=(492) +calls=4 0 +0 156 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1459 +0 40 +cob=(7) +cfi=(53) +cfn=(1812) +calls=4 0 +0 754 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1514 +0 28 +cob=(7) +cfi=(53) +cfn=(1528) +calls=4 0 +0 84 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 2194 +0 16 +cob=(7) +cfi=(53) +cfn=(728) +calls=4 0 +0 2832 +0 12 +cob=(7) +cfi=(53) +cfn=(2302) +calls=4 0 +0 4625 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1394 +0 76 +cob=(7) +cfi=(53) +cfn=(746) +calls=4 0 +0 48 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1483 +0 44 +cob=(7) +cfi=(53) +cfn=(1556) +calls=4 0 +0 232 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1515 +0 52 +cob=(7) +cfi=(53) +cfn=(1310) +calls=4 0 +0 328 +0 22 +cob=(12) +cfi=(84) +cfn=(2330) std::vector >::_M_insert_aux(__gnu_cxx::__normal_iterator > >, int const&) +calls=3 0 +0 956 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1654 +0 27 +cob=(7) +cfi=(53) +cfn=(1310) +calls=4 0 +0 328 +0 44 +cob=(7) +cfi=(53) +cfn=(1310) +calls=4 0 +0 328 +0 32 +cob=(7) +cfi=(53) +cfn=(1310) +calls=4 0 +0 328 +0 52 + +fn=(2462) +0 27 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 7 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 7 +0 13 +cob=(4) +cfi=(69) +cfn=(642) +calls=1 26 +0 22 +0 6 +cob=(4) +cfi=(69) +cfn=(642) +calls=2 26 +0 44 +0 12 +cob=(7) +cfi=(53) +cfn=(1574) +calls=3 0 +0 777 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1534 +0 12 +cob=(4) +cfi=(69) +cfn=(642) +calls=3 26 +0 48 +0 12 +cob=(7) +cfi=(53) +cfn=(1574) +calls=3 0 +0 789 +0 59 +cob=(7) +cfi=(53) +cfn=(1586) +calls=1 0 +0 38 +0 6 +cob=(7) +cfi=(53) +cfn=(1586) +calls=1 0 +0 38 +0 21 +cob=(12) +cfi=(84) +cfn=(2468) std::vector >::_M_fill_insert(__gnu_cxx::__normal_iterator > >, unsigned long, MR::Image::Axes::Axis const&) +calls=1 0 +0 570 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 2086 +0 1 + +fn=(2558) +0 19 +cob=(7) +cfi=(53) +cfn=(880) +calls=1 0 +0 166 +0 9 +cob=(7) +cfi=(53) +cfn=(1258) +calls=1 0 +0 20 +0 41 + +fn=(2564) +0 38 +cob=(7) +cfi=(53) +cfn=(1468) +calls=2 0 +0 115 +0 10 +cob=(7) +cfi=(53) +cfn=(1174) +calls=2 0 +0 162 +0 6 +cob=(7) +cfi=(53) +cfn=(1174) +calls=2 0 +0 162 +0 22 +cob=(7) +cfi=(53) +cfn=(1174) +calls=2 0 +0 162 + +fn=(2594) MR::Image::Header::sanitise() +0 18 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 298 +0 2 +cfn=(2206) +calls=1 0 +0 7 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 100 +0 8 +cfn=(2600) void MR::DataSet::Stride::sanitise(MR::Image::Axes&) +calls=1 0 +0 265 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1026 +0 3 +cfn=(2606) std::vector > MR::DataSet::Stride::order(MR::Image::Axes const&) +calls=1 0 +0 352 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1144 +0 62 +cob=(7) +cfi=(53) +cfn=(1174) +calls=1 0 +0 81 +0 16 +cob=(9) +cfi=(58) +cfn=(2616) gsl_permutation_alloc +calls=1 0 +0 212 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 955 +0 3 +cob=(9) +cfi=(58) +cfn=(2622) gsl_permutation_data +calls=1 0 +0 2 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 931 +0 36 +cob=(9) +cfi=(58) +cfn=(2622) +calls=1 0 +0 2 +0 38 +cob=(9) +cfi=(58) +cfn=(2622) +calls=1 0 +0 2 +0 38 +cob=(9) +cfi=(58) +cfn=(2622) +calls=1 0 +0 2 +0 3 +cob=(9) +cfi=(58) +cfn=(2622) +calls=1 0 +0 2 +0 7 +cob=(9) +cfi=(58) +cfn=(2622) +calls=1 0 +0 2 +0 3 +cob=(9) +cfi=(58) +cfn=(2622) +calls=1 0 +0 2 +0 8 +cob=(9) +cfi=(58) +cfn=(2622) +calls=1 0 +0 2 +0 3 +cob=(9) +cfi=(58) +cfn=(2622) +calls=1 0 +0 2 +0 9 +cob=(9) +cfi=(58) +cfn=(2622) +calls=1 0 +0 2 +0 21 +cob=(9) +cfi=(58) +cfn=(2628) gsl_permutation_free +calls=1 0 +0 165 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 931 +0 13 +cob=(9) +cfi=(58) +cfn=(2622) +calls=1 0 +0 2 +0 4 +cob=(9) +cfi=(58) +cfn=(2622) +calls=1 0 +0 2 +0 177 + +fn=(2600) +0 265 + +fn=(2606) +0 22 +cob=(7) +cfi=(53) +cfn=(880) +calls=1 0 +0 110 +0 58 +cfn=(2608) void std::__introsort_loop<__gnu_cxx::__normal_iterator > >, long, MR::DataSet::Stride::(anonymous namespace)::Compare >(__gnu_cxx::__normal_iterator > >, __gnu_cxx::__normal_iterator > >, long, MR::DataSet::Stride::(anonymous namespace)::Compare) +calls=1 0 +0 22 +0 6 +cfn=(2610) void std::__insertion_sort<__gnu_cxx::__normal_iterator > >, MR::DataSet::Stride::(anonymous namespace)::Compare >(__gnu_cxx::__normal_iterator > >, __gnu_cxx::__normal_iterator > >, MR::DataSet::Stride::(anonymous namespace)::Compare) +calls=1 0 +0 127 +0 7 + +fn=(2668) MR::Image::Handler::Default::execute() +0 55 +cfn=(2674) +calls=1 0 +0 22 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 750 +0 5 +cfn=(2674) +calls=1 0 +0 22 +0 19 +cfn=(2680) MR::Image::Handler::Default::map_files() +calls=1 0 +0 32716 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 961 +0 6 + +fn=(2498) MR::Image::Axes::check(std::vector > const&, unsigned long) +0 139 + +fn=(856) +0 3 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 3 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 + +fn=(874) std::tr1::_Hashtable, std::allocator >, std::_Select1st >, std::equal_to, std::tr1::hash, std::tr1::__detail::_Mod_range_hashing, std::tr1::__detail::_Default_ranged_hash, std::tr1::__detail::_Prime_rehash_policy, false, false, true>::_M_allocate_buckets(unsigned long) +0 8 +cob=(7) +cfi=(53) +cfn=(880) +calls=1 0 +0 62514 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1299 +0 56 + +fn=(998) +0 3 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 + +fn=(1018) +0 3 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 + +fn=(1412) MR::App::parse_arguments() +0 85 +cfn=(1418) MR::ArgBase::ArgBase(MR::Argument const&, char const*) +calls=2 0 +0 58 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 866 +0 3105 +cfn=(1418) +calls=3 0 +0 87 +0 42 +cfn=(1424) +calls=3 0 +0 504 +0 34 +cfn=(1424) +calls=2 0 +0 442 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1421 +0 57 +cob=(12) +cfi=(84) +cfn=(1430) std::vector >::_M_insert_aux(__gnu_cxx::__normal_iterator > >, MR::OptBase const&) +calls=3 0 +0 2008 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1926 +0 6 + +fn=(1418) +0 145 + +fn=(2084) std::vector >::_M_check_len(unsigned long, char const*) const +0 40 + +fn=(2120) MR::Image::NameParser::name(std::vector > const&) +0 58 +cob=(7) +cfi=(53) +cfn=(1258) +calls=2 0 +0 40 +0 8 +cfn=(2126) MR::Path::join(std::string const&, std::string const&) +calls=2 0 +0 4171 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 774 +0 4 +cob=(7) +cfi=(53) +cfn=(1468) +calls=2 0 +0 30 +0 2 + +fn=(2126) +0 60 +cob=(7) +cfi=(53) +cfn=(934) +calls=2 0 +0 400 +0 14 +cob=(7) +cfi=(53) +cfn=(1372) +calls=2 0 +0 24 +0 14 +cob=(7) +cfi=(53) +cfn=(1258) +calls=2 0 +0 40 +0 8 +cob=(7) +cfi=(53) +cfn=(1378) +calls=2 0 +0 957 +0 8 +cob=(7) +cfi=(53) +cfn=(1258) +calls=2 0 +0 40 +0 6 +cob=(7) +cfi=(53) +cfn=(1406) +calls=2 0 +0 642 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1548 +0 4 +cob=(7) +cfi=(53) +cfn=(1468) +calls=2 0 +0 200 +0 4 +cob=(7) +cfi=(53) +cfn=(1468) +calls=2 0 +0 200 +0 2 + +fn=(2206) +0 56 + +fn=(2384) +0 42 +cob=(4) +cfi=(69) +cfn=(642) +calls=2 26 +0 32 +0 12 +cob=(4) +cfi=(69) +cfn=(642) +calls=6 26 +0 96 +0 40 +cob=(7) +cfi=(53) +cfn=(2282) +calls=8 0 +0 2196 +0 80 +cob=(7) +cfi=(53) +cfn=(1446) +calls=8 0 +0 1488 +0 32 +cob=(7) +cfi=(53) +cfn=(1258) +calls=2 0 +0 30 +0 150 +cob=(12) +cfi=(84) +cfn=(2390) std::vector >::_M_insert_aux(__gnu_cxx::__normal_iterator > >, std::string const&) +calls=6 0 +0 2158 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1710 +0 54 + +fn=(2680) +0 17 +cob=(12) +cfi=(84) +cfn=(2012) +calls=1 0 +0 498 +0 3 +cob=(7) +cfi=(53) +cfn=(1258) +calls=1 0 +0 20 +0 4 +cob=(7) +cfi=(53) +cfn=(1772) +calls=1 0 +0 383 +0 2 +cfn=(2206) +calls=1 0 +0 7 +0 12 +cob=(7) +cfi=(53) +cfn=(880) +calls=1 0 +0 126 +0 55 +cob=(7) +cfi=(53) +cfn=(880) +calls=1 0 +0 180 +0 10 +cob=(7) +cfi=(53) +cfn=(1258) +calls=1 0 +0 20 +0 7 +cfn=(2698) +calls=1 0 +0 26839 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 741 +0 23 +cfn=(2692) +calls=1 0 +0 358 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1366 +0 7 +cfn=(2686) +calls=1 0 +0 216 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1603 +0 8 +cob=(7) +cfi=(53) +cfn=(1310) +calls=1 0 +0 82 +0 7 +cob=(7) +cfi=(53) +cfn=(1310) +calls=1 0 +0 113 +0 9 + +fn=(858) +0 3 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 + +fn=(862) +0 5 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 78 +cob=(6) +cfi=(70) /build/buildd/eglibc-2.11.1/math/../sysdeps/ieee754/flt-32/s_ceilf.c +cfn=(868) ceilf +calls=1 39 +0 15 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1414 +0 8 +cfn=(874) +calls=1 0 +0 63877 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 2458 +0 8 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 + +fn=(926) +0 3 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 + +fn=(1000) +0 3 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 + +fn=(1020) +0 3 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 + +fn=(1320) std::vector >::_M_insert_aux(__gnu_cxx::__normal_iterator > >, MR::ParsedOption const&) +0 68 +cob=(7) +cfi=(53) +cfn=(880) +calls=3 0 +0 500 +0 99 +cob=(4) +cfi=(90) +cfn=(1282) +calls=3 47 +0 72 +0 86 +cob=(7) +cfi=(53) +cfn=(880) +calls=3 0 +0 415 +0 39 +cob=(4) +cfi=(90) +cfn=(1282) +calls=3 47 +0 219 +0 76 +cob=(7) +cfi=(53) +cfn=(1174) +calls=3 0 +0 243 +0 23 +cob=(7) +cfi=(53) +cfn=(1174) +calls=2 0 +0 162 +0 78 + +fn=(2078) std::vector >::_M_insert_aux(__gnu_cxx::__normal_iterator > >, MR::Image::NameParserItem const&) +0 48 +cfn=(2084) +calls=2 0 +0 40 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1154 +0 16 +cfn=(2090) +calls=2 0 +0 240 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1172 +0 20 +cfn=(2096) +calls=2 0 +0 176 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 874 +0 12 +cfn=(2102) +calls=2 0 +0 42 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1297 +0 12 +cfn=(2102) +calls=2 0 +0 42 +0 28 + +fn=(2174) MR::Image::Format::Pipe::read(MR::Image::Header&) const +0 12 +cob=(7) +cfi=(53) +cfn=(1594) +calls=1 0 +0 44 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1506 +0 11 + +fn=(2582) MR::Image::Header::Header(MR::Image::Header const&) +0 19 +cob=(12) +cfi=(84) +cfn=(2588) std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::_M_copy(std::_Rb_tree_node > const*, std::_Rb_tree_node >*) +calls=1 0 +0 4662 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 2102 +0 269 +cob=(7) +cfi=(53) +cfn=(880) +calls=1 0 +0 168 +0 62 +cob=(7) +cfi=(53) +cfn=(1258) +calls=4 0 +0 75 +0 12 +cob=(7) +cfi=(53) +cfn=(1258) +calls=4 0 +0 75 +0 2777 +cob=(9) +cfi=(58) +cfn=(2506) gsl_block_float_alloc +calls=1 0 +0 212 +0 8 +cob=(9) +cfi=(58) +cfn=(2506) +calls=1 0 +0 262 +0 3 + +fn=(2610) +0 127 + +fn=(2776) void std::__insertion_sort<__gnu_cxx::__normal_iterator > >, MR::DataSet::Stride::(anonymous namespace)::Compare > >(__gnu_cxx::__normal_iterator > >, __gnu_cxx::__normal_iterator > >, MR::DataSet::Stride::(anonymous namespace)::Compare >) +0 120 + +fn=(2500) +0 50 +cob=(9) +cfi=(58) +cfn=(2506) +calls=2 0 +0 594 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 947 +0 8 + +fn=(478) +0 3 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 102531 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1579 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1778 + +fn=(860) +0 3 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 3 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 + +fn=(912) +0 3 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 + +fn=(988) +0 3 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 + +fn=(1002) +0 3 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 + +fn=(1022) +0 3 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 + +fn=(2160) +0 44 + +fn=(2172) +0 12 +cob=(7) +cfi=(53) +cfn=(1468) +calls=2 0 +0 14 +0 4 +cob=(7) +cfi=(53) +cfn=(1468) +calls=2 0 +0 30 +0 4 +cob=(7) +cfi=(53) +cfn=(1468) +calls=2 0 +0 200 +0 26 +cob=(7) +cfi=(53) +cfn=(1468) +calls=2 0 +0 200 +0 20 +cob=(7) +cfi=(53) +cfn=(1174) +calls=2 0 +0 162 + +fn=(2488) +0 22 +cob=(7) +cfi=(53) +cfn=(880) +calls=1 0 +0 110 +0 133 +cob=(7) +cfi=(53) +cfn=(1446) +calls=4 0 +0 784 +0 8 +cob=(7) +cfi=(53) +cfn=(722) +calls=4 0 +0 388 +0 84 +cob=(7) +cfi=(53) +cfn=(728) +calls=4 0 +0 2832 +0 64 +cob=(7) +cfi=(53) +cfn=(492) +calls=4 0 +0 156 +0 36 +cob=(7) +cfi=(53) +cfn=(1812) +calls=4 0 +0 748 +0 24 +cob=(7) +cfi=(53) +cfn=(1528) +calls=4 0 +0 84 +0 12 +cob=(7) +cfi=(53) +cfn=(728) +calls=4 0 +0 2832 +0 12 +cob=(7) +cfi=(53) +cfn=(2308) +calls=4 0 +0 1465 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1664 +0 76 +cob=(7) +cfi=(53) +cfn=(746) +calls=4 0 +0 48 +0 44 +cob=(7) +cfi=(53) +cfn=(1556) +calls=4 0 +0 232 +0 112 +cfn=(2498) +calls=1 0 +0 139 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 955 +0 37 +cob=(7) +cfi=(53) +cfn=(1310) +calls=4 0 +0 328 +0 48 +cob=(7) +cfi=(53) +cfn=(1310) +calls=4 0 +0 328 +0 20 + +fn=(2666) MR::Image::Handler::Base::prepare() +0 23 +cfn=(2668) +calls=1 0 +0 34556 +0 18 +cob=(7) +cfi=(53) +cfn=(880) +calls=1 0 +0 110 +0 63 +cfn=(2772) std::vector >::operator=(std::vector > const&) +calls=1 0 +0 226 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 794 +0 4 +cob=(7) +cfi=(53) +cfn=(1174) +calls=1 0 +0 81 +0 87 +cob=(7) +cfi=(53) +cfn=(1174) +calls=1 0 +0 81 +0 42 +cob=(7) +cfi=(53) +cfn=(722) +calls=1 0 +0 97 +0 23 +cob=(7) +cfi=(53) +cfn=(728) +calls=1 0 +0 708 +0 16 +cob=(7) +cfi=(53) +cfn=(492) +calls=1 0 +0 39 +0 11 +cob=(7) +cfi=(53) +cfn=(728) +calls=1 0 +0 708 +0 4 +cob=(7) +cfi=(53) +cfn=(1506) +calls=1 0 +0 631 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 2456 +0 11 +cob=(7) +cfi=(53) +cfn=(2714) +calls=1 0 +0 290 +0 9 +cob=(7) +cfi=(53) +cfn=(2714) +calls=3 0 +0 850 +0 16 +cob=(7) +cfi=(53) +cfn=(1506) +calls=4 0 +0 492 +0 32 +cob=(7) +cfi=(53) +cfn=(1506) +calls=1 0 +0 123 +0 25 +cob=(7) +cfi=(53) +cfn=(746) +calls=1 0 +0 12 +0 9 +cob=(7) +cfi=(53) +cfn=(1556) +calls=1 0 +0 58 +0 2 +cob=(7) +cfi=(53) +cfn=(722) +calls=1 0 +0 97 +0 19 +cob=(7) +cfi=(53) +cfn=(728) +calls=1 0 +0 708 +0 15 +cob=(7) +cfi=(53) +cfn=(492) +calls=1 0 +0 39 +0 9 +cob=(7) +cfi=(53) +cfn=(728) +calls=1 0 +0 708 +0 3 +cob=(7) +cfi=(53) +cfn=(2786) +calls=1 0 +0 715 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1648 +0 5 +cob=(7) +cfi=(53) +cfn=(1534) +calls=1 0 +0 257 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 2082 +0 16 +cob=(7) +cfi=(53) +cfn=(746) +calls=1 0 +0 12 +0 9 +cob=(7) +cfi=(53) +cfn=(1556) +calls=1 0 +0 58 +0 10 +cob=(7) +cfi=(53) +cfn=(1384) +calls=1 0 +0 180 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1450 +0 4 +cob=(7) +cfi=(53) +cfn=(1772) +calls=1 0 +0 64 +0 3 +cob=(7) +cfi=(53) +cfn=(1406) +calls=1 0 +0 82 +0 4 +cob=(7) +cfi=(53) +cfn=(1258) +calls=1 0 +0 20 +0 4 +cob=(7) +cfi=(53) +cfn=(1772) +calls=1 0 +0 326 +0 5 +cob=(12) +cfi=(84) +cfn=(1396) +calls=1 0 +0 319 +0 4 +cob=(7) +cfi=(53) +cfn=(1258) +calls=1 0 +0 20 +0 4 +cob=(7) +cfi=(53) +cfn=(1772) +calls=1 0 +0 496 +0 5 +cob=(12) +cfi=(84) +cfn=(1396) +calls=1 0 +0 409 +0 2 +cfn=(2030) +calls=1 0 +0 7 +0 34 +cob=(7) +cfi=(53) +cfn=(1310) +calls=1 0 +0 82 +0 7 +cob=(7) +cfi=(53) +cfn=(880) +calls=1 0 +0 110 +0 56 +cfn=(2774) void std::__introsort_loop<__gnu_cxx::__normal_iterator > >, long, MR::DataSet::Stride::(anonymous namespace)::Compare > >(__gnu_cxx::__normal_iterator > >, __gnu_cxx::__normal_iterator > >, long, MR::DataSet::Stride::(anonymous namespace)::Compare >) +calls=1 0 +0 22 +0 6 +cob=(12) +cfi=(84) +cfn=(2736) +calls=1 0 +0 184 +0 7 +cob=(7) +cfi=(53) +cfn=(1264) +calls=1 0 +0 28 +0 12 +cfn=(2776) +calls=1 0 +0 120 +0 12 +cob=(7) +cfi=(53) +cfn=(1310) +calls=1 0 +0 82 +0 15 +cob=(7) +cfi=(53) +cfn=(1310) +calls=1 0 +0 82 +0 7 +cob=(7) +cfi=(53) +cfn=(1310) +calls=1 0 +0 82 +0 15 +cob=(7) +cfi=(53) +cfn=(1310) +calls=1 0 +0 82 +0 7 +cob=(7) +cfi=(53) +cfn=(1310) +calls=1 0 +0 113 +0 15 +cob=(7) +cfi=(53) +cfn=(1310) +calls=1 0 +0 82 +0 11 +cob=(7) +cfi=(53) +cfn=(1310) +calls=1 0 +0 126 +0 11 +cob=(7) +cfi=(53) +cfn=(1310) +calls=1 0 +0 126 +0 5 + +fn=(914) +0 3 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 + +fn=(990) +0 3 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 7 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 66 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 + +fn=(1004) +0 3 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 + +fn=(1024) +0 3 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 + +fn=(2062) +0 36 +cob=(7) +cfi=(53) +cfn=(1586) +calls=2 0 +0 76 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1506 +0 12 +cob=(7) +cfi=(53) +cfn=(1264) +calls=2 0 +0 56 +0 8 +cfn=(2072) std::vector >::insert(__gnu_cxx::__normal_iterator > >, MR::Image::NameParserItem const&) +calls=2 0 +0 6756 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1477 +0 4 +cfn=(2108) +calls=2 0 +0 46 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 838 +0 10 + +fn=(2166) +0 58 + +fn=(2342) +0 6436 +cob=(7) +cfi=(53) +cfn=(1788) +calls=195 0 +0 8277 +0 260 +cob=(7) +cfi=(53) +cfn=(1788) +calls=65 0 +0 3040 +0 2860 +cob=(7) +cfi=(53) +cfn=(1446) +calls=260 0 +0 52580 +0 780 +cob=(7) +cfi=(53) +cfn=(1594) +calls=260 0 +0 11450 +0 2852 +cob=(7) +cfi=(53) +cfn=(1446) +calls=259 0 +0 52390 +0 777 +cob=(7) +cfi=(53) +cfn=(722) +calls=259 0 +0 25123 +0 6734 +cob=(7) +cfi=(53) +cfn=(728) +calls=259 0 +0 183372 +0 4144 +cob=(7) +cfi=(53) +cfn=(492) +calls=259 0 +0 10101 +0 2331 +cob=(7) +cfi=(53) +cfn=(1812) +calls=259 0 +0 50362 +0 1554 +cob=(7) +cfi=(53) +cfn=(1528) +calls=259 0 +0 5439 +0 777 +cob=(7) +cfi=(53) +cfn=(728) +calls=259 0 +0 183372 +0 777 +cob=(7) +cfi=(53) +cfn=(2348) +calls=259 0 +0 420937 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1648 +0 4921 +cob=(7) +cfi=(53) +cfn=(746) +calls=259 0 +0 3108 +0 2590 +cob=(7) +cfi=(53) +cfn=(1556) +calls=259 0 +0 15022 +0 3108 +cob=(7) +cfi=(53) +cfn=(1310) +calls=259 0 +0 21238 +0 1429 +cfn=(2372) std::vector >::_M_insert_aux(__gnu_cxx::__normal_iterator > >, float const&) +calls=195 0 +0 60150 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1243 +0 1755 +cob=(7) +cfi=(53) +cfn=(1310) +calls=260 0 +0 21320 +0 1814 +cob=(7) +cfi=(53) +cfn=(1310) +calls=259 0 +0 21238 +0 3371 + +fn=(2450) +0 2154 +cob=(4) +cfi=(90) +cfn=(1282) +calls=54 47 +0 1296 +0 170 +cob=(7) +cfi=(53) +cfn=(880) +calls=10 0 +0 2687 +0 100 +cob=(4) +cfi=(90) +cfn=(1282) +calls=10 47 +0 835 +0 70 +cob=(4) +cfi=(90) +cfn=(1282) +calls=10 47 +0 620 +0 100 +cob=(4) +cfi=(90) +cfn=(1282) +calls=10 47 +0 240 +0 38 +cob=(7) +cfi=(53) +cfn=(1174) +calls=8 0 +0 725 +0 714 +cob=(4) +cfi=(90) +cfn=(1282) +calls=54 47 +0 3348 +0 324 +cob=(4) +cfi=(90) +cfn=(1282) +calls=54 47 +0 1296 +0 418 + +fn=(2456) +0 271 +cob=(7) +cfi=(53) +cfn=(1174) +calls=67 0 +0 5500 +0 1 + +fn=(2772) +0 38 +cob=(7) +cfi=(53) +cfn=(880) +calls=1 0 +0 110 +0 5 +cob=(4) +cfi=(90) +cfn=(1282) +calls=1 47 +0 66 +0 7 + +fn=(2774) +0 22 + +fn=(916) +0 3 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 + +fn=(1026) +0 3 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 + +fn=(1270) +0 128 +cfn=(1292) MR::App::match_option(char const*) const +calls=4 0 +0 18326 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 804 +0 189 +cob=(4) +cfi=(90) +cfn=(1282) +calls=1 47 +0 24 +0 176 +cfn=(1276) +calls=3 0 +0 672 +0 14 +cfn=(1276) +calls=2 0 +0 3623 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1315 +0 27 +cfn=(1320) +calls=3 0 +0 2080 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1467 +0 6 + +fn=(1292) +0 56 +cob=(7) +cfi=(53) +cfn=(934) +calls=4 0 +0 1068 +0 3492 +cob=(7) +cfi=(53) +cfn=(1298) +calls=216 0 +0 5233 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1562 +0 456 +cfn=(1304) +calls=4 0 +0 1066 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1251 +0 56 +cob=(7) +cfi=(53) +cfn=(1298) +calls=4 0 +0 96 +0 112 +cob=(7) +cfi=(53) +cfn=(1298) +calls=16 0 +0 386 +0 192 +cob=(7) +cfi=(53) +cfn=(1174) +calls=4 0 +0 324 +0 72 +cob=(7) +cfi=(53) +cfn=(1310) +calls=4 0 +0 1198 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1682 +0 24 + +fn=(1344) +0 15 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 315 +0 6 +cob=(4) +cfi=(95) +cfn=(1350) +calls=1 37 +0 14 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1738 +0 3 +cob=(4) +cfi=(96) +cfn=(1356) +calls=1 34 +0 3 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1834 +0 16 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 229 +0 2 +cob=(4) +cfi=(97) +cfn=(1362) +calls=1 36 +0 144 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1708 +0 7 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 229 +0 17 +cob=(4) +cfi=(95) +cfn=(1350) +calls=1 37 +0 14 +0 3 +cob=(4) +cfi=(96) +cfn=(1356) +calls=1 34 +0 3 +0 23 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 285 +0 7 +cob=(7) +cfi=(53) +cfn=(1372) +calls=1 0 +0 12 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1538 +0 7 +cob=(7) +cfi=(53) +cfn=(1258) +calls=1 0 +0 20 +0 4 +cob=(7) +cfi=(53) +cfn=(1378) +calls=1 0 +0 2283 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1458 +0 7 +cob=(12) +cfi=(84) +cfn=(1396) +calls=1 0 +0 3373 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1238 +0 14 +cob=(7) +cfi=(53) +cfn=(1310) +calls=1 0 +0 82 +0 7 +cob=(7) +cfi=(53) +cfn=(1310) +calls=1 0 +0 82 +0 15 +cob=(7) +cfi=(53) +cfn=(1310) +calls=1 0 +0 82 +0 12 +cob=(7) +cfi=(53) +cfn=(1310) +calls=1 0 +0 82 +0 7 +cob=(7) +cfi=(53) +cfn=(1310) +calls=1 0 +0 82 +0 15 +cob=(7) +cfi=(53) +cfn=(1310) +calls=1 0 +0 82 +0 5 + +fn=(2006) MR::Image::Header::open(std::string const&, bool) +0 55 +cob=(12) +cfi=(84) +cfn=(2012) +calls=1 0 +0 5239 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1270 +0 4 +cob=(7) +cfi=(53) +cfn=(1258) +calls=1 0 +0 20 +0 4 +cob=(7) +cfi=(53) +cfn=(1772) +calls=1 0 +0 329 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1508 +0 2 +cfn=(2030) +calls=1 0 +0 7 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 100 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1440 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 100 +0 10 +cfn=(2040) +calls=1 0 +0 32359 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1043 +0 6 +cob=(7) +cfi=(53) +cfn=(1258) +calls=1 0 +0 20 +0 5 +cob=(7) +cfi=(53) +cfn=(1264) +calls=1 0 +0 28 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 15 +0 13 +cfn=(2582) +calls=1 0 +0 10706 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 811 +0 13 +cfn=(2594) +calls=1 0 +0 6965 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 821 +0 5 +cob=(7) +cfi=(53) +cfn=(1264) +calls=1 0 +0 36 +0 2 +cob=(12) +cfi=(84) +cfn=(2634) MR::Image::Header::~Header() +calls=1 0 +0 3775 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 774 +0 5 +cfn=(2564) +calls=1 0 +0 381 +0 26 +cfn=(2182) +calls=1 0 +0 1797277 +cfn=(2180) MR::Image::Format::DICOM::read(MR::Image::Header&) const +calls=1 0 +0 37 +cfn=(2174) +calls=1 0 +0 1573 +0 9 +cob=(7) +cfi=(53) +cfn=(880) +calls=1 0 +0 168 +0 20 + +fn=(2072) +0 36 +cfn=(2078) +calls=2 0 +0 5173 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1523 +0 24 + +fn=(2114) +0 68 +cfn=(2120) +calls=2 0 +0 5087 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 984 +0 4 +cob=(7) +cfi=(53) +cfn=(880) +calls=2 0 +0 220 +0 46 +cob=(4) +cfi=(90) +cfn=(1282) +calls=2 47 +0 48 +0 8 +cob=(7) +cfi=(53) +cfn=(1258) +calls=2 0 +0 40 +0 6 +cob=(7) +cfi=(53) +cfn=(880) +calls=2 0 +0 220 +0 14 +cfn=(2142) MR::RefPtr::~RefPtr() +calls=2 0 +0 20 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 955 +0 4 +cob=(7) +cfi=(53) +cfn=(1468) +calls=2 0 +0 30 +0 10 +cfn=(2136) std::vector, std::allocator > >::_M_insert_aux(__gnu_cxx::__normal_iterator*, std::vector, std::allocator > > >, MR::RefPtr const&) +calls=2 0 +0 406 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1699 +0 2 + +fn=(2136) +0 40 +cob=(7) +cfi=(53) +cfn=(880) +calls=2 0 +0 276 +0 90 + +fn=(2142) +0 20 + +fn=(2180) +0 12 +cob=(4) +cfi=(95) +cfn=(1350) +calls=1 37 +0 10 +0 15 + +fn=(2372) +0 5850 +cob=(7) +cfi=(53) +cfn=(880) +calls=195 0 +0 21540 +0 2925 +cob=(4) +cfi=(90) +cfn=(1282) +calls=195 47 +0 9490 +0 1560 +cob=(4) +cfi=(90) +cfn=(1282) +calls=195 47 +0 4680 +0 715 +cob=(7) +cfi=(53) +cfn=(1174) +calls=130 0 +0 10530 +0 2860 + +fn=(2608) +0 22 + +fn=(3398) +0 8 +cob=(7) +cfi=(53) +cfn=(1594) +calls=4 0 +0 248 +0 16 + +ob=(12) +fl=(84) +fn=(2824) std::vector >::operator=(std::vector > const&) +0 10032 +cob=(7) +cfi=(53) +cfn=(880) +calls=264 0 +0 79524 +0 1320 +cob=(4) +cfi=(90) +cfn=(1282) +calls=264 47 +0 56760 +0 1848 + +fn=(1148) global constructors keyed to state.cpp +0 5 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 + +fn=(1152) global constructors keyed to KCutil.cpp +0 7 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 6 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 330 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 313 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 317 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 + +fn=(1188) global constructors keyed to walker.cpp +0 6 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 304 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 360 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 5 + +fn=(1200) global constructors keyed to KMrand.cpp +0 7 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 6 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 330 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 313 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 317 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 + +fn=(1212) global constructors keyed to midpoint_in_cube.cpp +0 6 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 330 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 313 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 317 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 313 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 8 + +fn=(1214) global constructors keyed to flat_top_quadratic.cpp +0 6 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 330 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 313 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 317 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 328 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 5 + +fn=(1218) global constructors keyed to distribution.cpp +0 3 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 + +fn=(1396) +0 2088 +cob=(7) +cfi=(53) +cfn=(1258) +calls=348 0 +0 6950 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1426 +0 1044 +cob=(7) +cfi=(53) +cfn=(1406) +calls=348 0 +0 92628 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1548 +0 1740 + +fn=(1434) MyApp::execute() +0 18 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 253 +0 7 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 316 +0 4 +cob=(7) +cfi=(53) +cfn=(1258) +calls=1 0 +0 20 +0 4 +cfn=(1436) BTS::File::extension(std::string) +calls=1 0 +0 6478 +0 4 +cob=(7) +cfi=(53) +cfn=(1258) +calls=1 0 +0 20 +0 4 +cfn=(1436) +calls=1 0 +0 448 +0 7 +cob=(4) +cfi=(100) +cfn=(1476) +calls=1 25 +0 27 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1698 +0 4 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 1177 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 15 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 100 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 15 +0 7 +cob=(7) +cfi=(53) +cfn=(1258) +calls=1 0 +0 20 +0 5 +cfn=(1436) +calls=1 0 +0 448 +0 3 +cfn=(1482) T.14247 +calls=1 0 +0 7620 +0 3 +cob=(7) +cfi=(53) +cfn=(1500) +calls=1 0 +0 5442 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 2082 +0 4 +cob=(7) +cfi=(53) +cfn=(1534) +calls=1 0 +0 2330 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 2082 +0 2 +cob=(7) +cfi=(53) +cfn=(1550) +calls=1 0 +0 3791 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 2082 +0 4 +cob=(7) +cfi=(53) +cfn=(1258) +calls=1 0 +0 20 +0 10 +cob=(7) +cfi=(53) +cfn=(1246) +calls=1 0 +0 160 +0 7 +cob=(7) +cfi=(53) +cfn=(1446) +calls=1 0 +0 402 +0 4 +cob=(7) +cfi=(53) +cfn=(1264) +calls=1 0 +0 28 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 15 +0 5 +cfn=(1396) +calls=1 0 +0 425 +0 6 +cfn=(1396) +calls=1 0 +0 431 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 100 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 100 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 15 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 100 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 100 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 15 +0 5 +cob=(7) +cfi=(53) +cfn=(1258) +calls=1 0 +0 20 +0 4 +cfn=(1436) +calls=1 0 +0 448 +0 2 +cfn=(1482) +calls=1 0 +0 2348 +0 3 +cob=(7) +cfi=(53) +cfn=(1500) +calls=1 0 +0 528 +0 4 +cob=(7) +cfi=(53) +cfn=(1534) +calls=1 0 +0 264 +0 2 +cob=(7) +cfi=(53) +cfn=(1550) +calls=1 0 +0 420 +0 4 +cob=(7) +cfi=(53) +cfn=(1258) +calls=1 0 +0 20 +0 8 +cob=(7) +cfi=(53) +cfn=(1246) +calls=1 0 +0 160 +0 7 +cob=(7) +cfi=(53) +cfn=(1446) +calls=1 0 +0 410 +0 4 +cob=(7) +cfi=(53) +cfn=(1264) +calls=1 0 +0 28 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 15 +0 5 +cfn=(1396) +calls=1 0 +0 381 +0 6 +cfn=(1396) +calls=1 0 +0 481 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 100 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 100 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 15 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 100 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 100 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 15 +0 10 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 6 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 225 +0 27 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 228 +0 5 +cfn=(1588) MR::App::get_options(std::string const&) +calls=1 0 +0 2289 +0 5 +cfn=(1596) std::vector >::operator=(std::vector > const&) +calls=1 0 +0 505 +0 2 +cfn=(1598) std::vector >::~vector() +calls=1 0 +0 185 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 100 +0 53 +cob=(7) +cfi=(53) +cfn=(1574) +calls=1 0 +0 418 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 224 +0 5 +cfn=(1588) +calls=1 0 +0 280 +0 3 +cfn=(1596) +calls=1 0 +0 136 +0 2 +cfn=(1598) +calls=1 0 +0 15 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 100 +0 11 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 233 +0 5 +cfn=(1588) +calls=1 0 +0 682 +0 3 +cfn=(1596) +calls=1 0 +0 218 +0 2 +cfn=(1598) +calls=1 0 +0 185 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 100 +0 24 +cob=(7) +cfi=(53) +cfn=(1574) +calls=1 0 +0 108 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 234 +0 5 +cfn=(1588) +calls=1 0 +0 544 +0 3 +cfn=(1596) +calls=1 0 +0 102 +0 2 +cfn=(1598) +calls=1 0 +0 103 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 100 +0 10 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 223 +0 5 +cfn=(1588) +calls=1 0 +0 280 +0 3 +cfn=(1596) +calls=1 0 +0 136 +0 2 +cfn=(1598) +calls=1 0 +0 15 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 100 +0 11 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 5 +cfn=(1588) +calls=1 0 +0 280 +0 3 +cfn=(1596) +calls=1 0 +0 47 +0 2 +cfn=(1598) +calls=1 0 +0 15 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 100 +0 11 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 225 +0 5 +cfn=(1588) +calls=1 0 +0 280 +0 3 +cfn=(1596) +calls=1 0 +0 47 +0 2 +cfn=(1598) +calls=1 0 +0 15 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 100 +0 11 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 234 +0 5 +cfn=(1588) +calls=1 0 +0 280 +0 3 +cfn=(1596) +calls=1 0 +0 47 +0 2 +cfn=(1598) +calls=1 0 +0 15 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 100 +0 9 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 356 +0 15 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 244 +0 5 +cfn=(1588) +calls=1 0 +0 280 +0 3 +cfn=(1596) +calls=1 0 +0 47 +0 2 +cfn=(1598) +calls=1 0 +0 15 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 100 +0 11 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 243 +0 5 +cfn=(1588) +calls=1 0 +0 280 +0 3 +cfn=(1596) +calls=1 0 +0 47 +0 2 +cfn=(1598) +calls=1 0 +0 15 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 100 +0 11 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 234 +0 5 +cfn=(1588) +calls=1 0 +0 280 +0 3 +cfn=(1596) +calls=1 0 +0 47 +0 2 +cfn=(1598) +calls=1 0 +0 15 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 100 +0 10 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 225 +0 5 +cfn=(1588) +calls=1 0 +0 280 +0 3 +cfn=(1596) +calls=1 0 +0 47 +0 2 +cfn=(1598) +calls=1 0 +0 15 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 100 +0 10 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 228 +0 5 +cfn=(1588) +calls=1 0 +0 280 +0 3 +cfn=(1596) +calls=1 0 +0 47 +0 2 +cfn=(1598) +calls=1 0 +0 15 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 100 +0 25 +cfn=(1602) MR::Math::Matrix::load(std::string const&) +calls=1 0 +0 820838 +0 22 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 234 +0 5 +cfn=(1588) +calls=1 0 +0 280 +0 3 +cfn=(1596) +calls=1 0 +0 47 +0 2 +cfn=(1598) +calls=1 0 +0 15 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 100 +0 11 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 234 +0 5 +cfn=(1588) +calls=1 0 +0 280 +0 3 +cfn=(1596) +calls=1 0 +0 47 +0 2 +cfn=(1598) +calls=1 0 +0 15 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 100 +0 11 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 234 +0 5 +cfn=(1588) +calls=1 0 +0 280 +0 3 +cfn=(1596) +calls=1 0 +0 47 +0 2 +cfn=(1598) +calls=1 0 +0 15 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 100 +0 26 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 234 +0 16 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 249 +0 5 +cfn=(1588) +calls=1 0 +0 280 +0 3 +cfn=(1596) +calls=1 0 +0 47 +0 2 +cfn=(1598) +calls=1 0 +0 15 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 100 +0 11 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 239 +0 5 +cfn=(1588) +calls=1 0 +0 280 +0 3 +cfn=(1596) +calls=1 0 +0 47 +0 2 +cfn=(1598) +calls=1 0 +0 15 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 100 +0 11 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 225 +0 5 +cfn=(1588) +calls=1 0 +0 280 +0 3 +cfn=(1596) +calls=1 0 +0 47 +0 2 +cfn=(1598) +calls=1 0 +0 15 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 100 +0 11 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 234 +0 5 +cfn=(1588) +calls=1 0 +0 280 +0 3 +cfn=(1596) +calls=1 0 +0 47 +0 2 +cfn=(1598) +calls=1 0 +0 15 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 100 +0 11 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 235 +0 5 +cfn=(1588) +calls=1 0 +0 280 +0 3 +cfn=(1596) +calls=1 0 +0 47 +0 2 +cfn=(1598) +calls=1 0 +0 15 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 100 +0 10 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 234 +0 5 +cfn=(1588) +calls=1 0 +0 280 +0 3 +cfn=(1596) +calls=1 0 +0 47 +0 2 +cfn=(1598) +calls=1 0 +0 15 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 100 +0 11 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 241 +0 5 +cfn=(1588) +calls=1 0 +0 280 +0 3 +cfn=(1596) +calls=1 0 +0 47 +0 2 +cfn=(1598) +calls=1 0 +0 15 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 100 +0 16 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 225 +0 12 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 225 +0 5 +cfn=(1588) +calls=1 0 +0 280 +0 3 +cfn=(1596) +calls=1 0 +0 47 +0 2 +cfn=(1598) +calls=1 0 +0 15 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 100 +0 11 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 229 +0 5 +cfn=(1588) +calls=1 0 +0 280 +0 3 +cfn=(1596) +calls=1 0 +0 47 +0 2 +cfn=(1598) +calls=1 0 +0 15 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 100 +0 11 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 230 +0 5 +cfn=(1588) +calls=1 0 +0 280 +0 3 +cfn=(1596) +calls=1 0 +0 47 +0 2 +cfn=(1598) +calls=1 0 +0 15 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 100 +0 10 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 235 +0 5 +cfn=(1588) +calls=1 0 +0 280 +0 3 +cfn=(1596) +calls=1 0 +0 47 +0 2 +cfn=(1598) +calls=1 0 +0 15 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 100 +0 14 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 234 +0 5 +cfn=(1588) +calls=1 0 +0 280 +0 3 +cfn=(1596) +calls=1 0 +0 47 +0 2 +cfn=(1598) +calls=1 0 +0 15 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 100 +0 11 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 245 +0 5 +cfn=(1588) +calls=1 0 +0 280 +0 3 +cfn=(1596) +calls=1 0 +0 47 +0 2 +cfn=(1598) +calls=1 0 +0 15 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 100 +0 16 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 230 +0 5 +cfn=(1588) +calls=1 0 +0 280 +0 3 +cfn=(1596) +calls=1 0 +0 47 +0 2 +cfn=(1598) +calls=1 0 +0 15 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 100 +0 17 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 234 +0 5 +cfn=(1588) +calls=1 0 +0 280 +0 3 +cfn=(1596) +calls=1 0 +0 47 +0 2 +cfn=(1598) +calls=1 0 +0 15 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 100 +0 19 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 239 +0 5 +cfn=(1588) +calls=1 0 +0 280 +0 3 +cfn=(1596) +calls=1 0 +0 47 +0 2 +cfn=(1598) +calls=1 0 +0 15 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 100 +0 19 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 234 +0 5 +cfn=(1588) +calls=1 0 +0 280 +0 3 +cfn=(1596) +calls=1 0 +0 47 +0 2 +cfn=(1598) +calls=1 0 +0 15 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 100 +0 19 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 230 +0 5 +cfn=(1588) +calls=1 0 +0 280 +0 3 +cfn=(1596) +calls=1 0 +0 47 +0 2 +cfn=(1598) +calls=1 0 +0 15 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 100 +0 19 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 234 +0 5 +cfn=(1588) +calls=1 0 +0 280 +0 3 +cfn=(1596) +calls=1 0 +0 47 +0 2 +cfn=(1598) +calls=1 0 +0 15 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 100 +0 25 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 223 +0 5 +cfn=(1588) +calls=1 0 +0 280 +0 3 +cfn=(1596) +calls=1 0 +0 47 +0 2 +cfn=(1598) +calls=1 0 +0 15 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 100 +0 17 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 234 +0 5 +cfn=(1588) +calls=1 0 +0 280 +0 3 +cfn=(1596) +calls=1 0 +0 47 +0 2 +cfn=(1598) +calls=1 0 +0 15 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 100 +0 17 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 230 +0 5 +cfn=(1588) +calls=1 0 +0 280 +0 3 +cfn=(1596) +calls=1 0 +0 47 +0 2 +cfn=(1598) +calls=1 0 +0 15 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 100 +0 20 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 238 +0 5 +cfn=(1588) +calls=1 0 +0 280 +0 3 +cfn=(1596) +calls=1 0 +0 47 +0 2 +cfn=(1598) +calls=1 0 +0 15 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 100 +0 17 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 235 +0 5 +cfn=(1588) +calls=1 0 +0 280 +0 3 +cfn=(1596) +calls=1 0 +0 47 +0 2 +cfn=(1598) +calls=1 0 +0 15 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 100 +0 20 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 235 +0 5 +cfn=(1588) +calls=1 0 +0 280 +0 3 +cfn=(1596) +calls=1 0 +0 47 +0 2 +cfn=(1598) +calls=1 0 +0 15 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 100 +0 19 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 240 +0 5 +cfn=(1588) +calls=1 0 +0 280 +0 3 +cfn=(1596) +calls=1 0 +0 47 +0 2 +cfn=(1598) +calls=1 0 +0 15 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 100 +0 21 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 239 +0 5 +cfn=(1588) +calls=1 0 +0 280 +0 3 +cfn=(1596) +calls=1 0 +0 47 +0 2 +cfn=(1598) +calls=1 0 +0 15 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 100 +0 15 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 241 +0 5 +cfn=(1588) +calls=1 0 +0 280 +0 3 +cfn=(1596) +calls=1 0 +0 47 +0 2 +cfn=(1598) +calls=1 0 +0 15 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 100 +0 27 +cob=(4) +cfi=(91) +cfn=(1326) +calls=1 32 +0 8 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1642 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 235 +0 5 +cfn=(1588) +calls=1 0 +0 280 +0 3 +cfn=(1596) +calls=1 0 +0 47 +0 2 +cfn=(1598) +calls=1 0 +0 15 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 100 +0 11 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 245 +0 5 +cfn=(1588) +calls=1 0 +0 280 +0 3 +cfn=(1596) +calls=1 0 +0 47 +0 2 +cfn=(1598) +calls=1 0 +0 15 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 100 +0 11 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 238 +0 5 +cfn=(1588) +calls=1 0 +0 280 +0 3 +cfn=(1596) +calls=1 0 +0 47 +0 2 +cfn=(1598) +calls=1 0 +0 15 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 100 +0 11 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 239 +0 5 +cfn=(1588) +calls=1 0 +0 280 +0 3 +cfn=(1596) +calls=1 0 +0 47 +0 2 +cfn=(1598) +calls=1 0 +0 15 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 100 +0 11 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 240 +0 5 +cfn=(1588) +calls=1 0 +0 280 +0 3 +cfn=(1596) +calls=1 0 +0 47 +0 2 +cfn=(1598) +calls=1 0 +0 15 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 100 +0 11 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 239 +0 5 +cfn=(1588) +calls=1 0 +0 280 +0 3 +cfn=(1596) +calls=1 0 +0 47 +0 2 +cfn=(1598) +calls=1 0 +0 15 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 100 +0 11 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 245 +0 5 +cfn=(1588) +calls=1 0 +0 280 +0 3 +cfn=(1596) +calls=1 0 +0 47 +0 2 +cfn=(1598) +calls=1 0 +0 15 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 100 +0 11 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 234 +0 5 +cfn=(1588) +calls=1 0 +0 280 +0 3 +cfn=(1596) +calls=1 0 +0 47 +0 2 +cfn=(1598) +calls=1 0 +0 15 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 100 +0 12 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 57 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 219 +0 5 +cfn=(1588) +calls=1 0 +0 280 +0 3 +cfn=(1596) +calls=1 0 +0 47 +0 2 +cfn=(1598) +calls=1 0 +0 15 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 100 +0 48 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 229 +0 5 +cfn=(1588) +calls=1 0 +0 680 +0 3 +cfn=(1596) +calls=1 0 +0 218 +0 2 +cfn=(1598) +calls=1 0 +0 185 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 100 +0 55 +cob=(7) +cfi=(53) +cfn=(1574) +calls=1 0 +0 317 +0 7 +cfn=(2000) BTS::Image::Observed::Buffer::load(std::string const&, BTS::Diffusion::Encoding::Set const&) +calls=1 0 +0 2353009 +0 11 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 230 +0 46 +cob=(4) +cfi=(100) +cfn=(1476) +calls=4 25 +0 131 +0 43 +cob=(4) +cfi=(100) +cfn=(1476) +calls=1 25 +0 30 +0 6 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 100 +0 40 +cfn=(2880) BTS::Diffusion::Model::factory(MR::Math::Matrix const&, MR::Math::Matrix const&, double, double, bool) +calls=1 0 +0 7079693 +0 17 +cfn=(3026) BTS::Image::Expected::Buffer::factory(std::string const&, BTS::Triple const&, BTS::Triple const&, BTS::Diffusion::Model const&, unsigned int, unsigned int, double, BTS::Triple const&, bool, double) +calls=1 0 +0 38371 +0 25 +cfn=(3072) BTS::Prob::Likelihood::factory(std::string const&, BTS::Image::Observed::Buffer const&, BTS::Image::Expected::Buffer*, double, bool, double) +calls=1 0 +0 90403 +0 11 +cob=(7) +cfi=(53) +cfn=(1446) +calls=1 0 +0 294 +0 3 +cob=(7) +cfi=(53) +cfn=(1594) +calls=1 0 +0 56 +0 5 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 100 +0 42 +cfn=(3120) BTS::Prob::Test::Peaks::Peaks(double, double) +calls=1 0 +0 11 +0 5 +cfn=(3270) BTS::Prob::Test::Peaks::~Peaks() +calls=1 0 +0 2495 +0 14 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 224 +0 3 +cfn=(3272) std::map, std::allocator > >::operator[](std::string const&) +calls=1 0 +0 437 +0 4 +cob=(7) +cfi=(53) +cfn=(1574) +calls=1 0 +0 314 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 15 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 286 +0 3 +cfn=(3272) +calls=1 0 +0 477 +0 3 +cob=(7) +cfi=(53) +cfn=(1264) +calls=1 0 +0 28 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 15 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 282 +0 3 +cfn=(3272) +calls=1 0 +0 535 +0 3 +cob=(7) +cfi=(53) +cfn=(1264) +calls=1 0 +0 28 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 15 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 292 +0 3 +cfn=(3272) +calls=1 0 +0 568 +0 3 +cob=(7) +cfi=(53) +cfn=(1264) +calls=1 0 +0 28 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 15 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 291 +0 3 +cfn=(3272) +calls=1 0 +0 496 +0 3 +cob=(7) +cfi=(53) +cfn=(1264) +calls=1 0 +0 28 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 15 +0 5 +cfn=(3274) std::string BTS::str(double const&) +calls=1 0 +0 12188 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 438 +0 3 +cfn=(3272) +calls=1 0 +0 501 +0 3 +cob=(7) +cfi=(53) +cfn=(1264) +calls=1 0 +0 28 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 15 +0 3 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 15 +0 4 +cob=(7) +cfi=(53) +cfn=(1594) +calls=1 0 +0 44 +0 6 +cob=(7) +cfi=(53) +cfn=(1594) +calls=1 0 +0 50 +0 11 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 285 +0 4 +cfn=(3272) +calls=1 0 +0 580 +0 4 +cob=(7) +cfi=(53) +cfn=(1264) +calls=1 0 +0 28 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 15 +0 7 +cob=(7) +cfi=(53) +cfn=(1446) +calls=1 0 +0 261 +0 3 +cob=(7) +cfi=(53) +cfn=(1594) +calls=1 0 +0 50 +0 4 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 100 +0 7 +cfn=(3274) +calls=1 0 +0 5693 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 240 +0 3 +cfn=(3272) +calls=1 0 +0 650 +0 3 +cob=(7) +cfi=(53) +cfn=(1264) +calls=1 0 +0 28 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 15 +0 3 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 15 +0 7 +cob=(7) +cfi=(53) +cfn=(1594) +calls=1 0 +0 57 +0 6 +cob=(7) +cfi=(53) +cfn=(1594) +calls=1 0 +0 69 +0 6 +cob=(7) +cfi=(53) +cfn=(1594) +calls=1 0 +0 57 +0 9 +cob=(7) +cfi=(53) +cfn=(1446) +calls=1 0 +0 266 +0 3 +cob=(7) +cfi=(53) +cfn=(1594) +calls=1 0 +0 73 +0 4 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 100 +0 9 +cob=(7) +cfi=(53) +cfn=(1446) +calls=1 0 +0 205 +0 3 +cob=(7) +cfi=(53) +cfn=(1594) +calls=1 0 +0 44 +0 4 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 100 +0 9 +cob=(7) +cfi=(53) +cfn=(1446) +calls=1 0 +0 210 +0 3 +cob=(7) +cfi=(53) +cfn=(1594) +calls=1 0 +0 50 +0 4 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 100 +0 6 +cob=(7) +cfi=(53) +cfn=(1594) +calls=1 0 +0 56 +0 13 +cfn=(3122) BTS::Prob::Test::Peaks::Peaks(unsigned int, double, double, double, double, double, unsigned int) +calls=1 0 +0 53914 +0 10 +cfn=(3266) std::vector >::operator=(std::vector > const&) +calls=1 0 +0 6488 +0 9 +cob=(7) +cfi=(53) +cfn=(1446) +calls=1 0 +0 206 +0 7 +cob=(4) +cfi=(100) +cfn=(1476) +calls=1 25 +0 27 +0 6 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 100 +0 6 +cob=(7) +cfi=(53) +cfn=(880) +calls=1 0 +0 195 +0 81 +cfn=(3102) BTS::Prob::Prior::Tract::factory(double, double&, double, double&, double, double&, double, double, double&, double, double, double&, double, double, double&, double, double, double&, double, unsigned int, unsigned int, double, BTS::Image::Expected::Buffer*, double&, double, double, double&, double, double, double&, double, double, double, double&, double, double&, double, double&, double, double&, double, double, double&, double, std::string const&) +calls=1 0 +0 1948 +0 10 +cob=(7) +cfi=(53) +cfn=(1446) +calls=1 0 +0 206 +0 7 +cob=(4) +cfi=(100) +cfn=(1476) +calls=1 25 +0 36 +0 6 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 100 +0 12 +cob=(7) +cfi=(53) +cfn=(1446) +calls=1 0 +0 206 +0 8 +cob=(4) +cfi=(100) +cfn=(1476) +calls=1 25 +0 18 +0 6 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 100 +0 12 +cfn=(3070) BTS::Image::Expected::Buffer::base_intensity_default(BTS::Image::Observed::Buffer const&, std::string const&, bool) +calls=1 0 +0 747 +0 10 +cob=(7) +cfi=(53) +cfn=(1446) +calls=1 0 +0 206 +0 7 +cob=(4) +cfi=(100) +cfn=(1476) +calls=1 25 +0 18 +0 6 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 100 +0 9 +cfn=(3338) std::string BTS::str(unsigned int const&) +calls=1 0 +0 3617 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 446 +0 3 +cfn=(3272) +calls=1 0 +0 2059 +0 3 +cob=(7) +cfi=(53) +cfn=(1264) +calls=1 0 +0 28 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 15 +0 3 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 15 +0 5 +cfn=(3274) +calls=1 0 +0 5710 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 529 +0 3 +cfn=(3272) +calls=1 0 +0 638 +0 3 +cob=(7) +cfi=(53) +cfn=(1264) +calls=1 0 +0 28 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 15 +0 3 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 15 +0 5 +cfn=(3274) +calls=1 0 +0 5106 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 475 +0 3 +cfn=(3272) +calls=1 0 +0 595 +0 3 +cob=(7) +cfi=(53) +cfn=(1264) +calls=1 0 +0 28 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 15 +0 3 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 15 +0 5 +cfn=(3274) +calls=1 0 +0 5106 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 420 +0 3 +cfn=(3272) +calls=1 0 +0 962 +0 3 +cob=(7) +cfi=(53) +cfn=(1264) +calls=1 0 +0 28 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 15 +0 3 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 15 +0 5 +cfn=(3338) +calls=1 0 +0 4973 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 520 +0 3 +cfn=(3272) +calls=1 0 +0 692 +0 3 +cob=(7) +cfi=(53) +cfn=(1264) +calls=1 0 +0 28 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 15 +0 3 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 15 +0 5 +cob=(7) +cfi=(53) +cfn=(1594) +calls=1 0 +0 74 +0 9 +cob=(7) +cfi=(53) +cfn=(1446) +calls=1 0 +0 252 +0 3 +cob=(7) +cfi=(53) +cfn=(1594) +calls=1 0 +0 50 +0 4 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 100 +0 6 +cob=(7) +cfi=(53) +cfn=(1594) +calls=1 0 +0 100 +0 12 +cfn=(3074) BTS::Prob::Likelihood::ImageDiff::ImageDiff(BTS::Image::Observed::Buffer const&, BTS::Image::Expected::Buffer*, double, bool, double) +calls=1 0 +0 90449 +0 7 +cob=(7) +cfi=(53) +cfn=(1594) +calls=1 0 +0 65 +0 24 +cfn=(3268) std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::_Rb_tree(std::_Rb_tree, std::_Select1st >, std::less, std::allocator > > const&) +calls=1 0 +0 18 +0 28 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 3 +cfn=(3348) std::map, std::allocator > >::operator[](std::string const&) +calls=1 0 +0 403 +0 4 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 15 +0 6 +cfn=(2642) std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::_M_erase(std::_Rb_tree_node >*) +calls=1 0 +0 11 +0 3 +cob=(7) +cfi=(53) +cfn=(3360) +calls=1 0 +0 3056 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1962 +0 17 +cob=(7) +cfi=(53) +cfn=(3360) +calls=1 0 +0 1828 +0 9 +cob=(7) +cfi=(53) +cfn=(3360) +calls=1 0 +0 1828 +0 3 +cfn=(3366) BTS::Fibre::Set::Reader::open(std::string const&) +calls=1 0 +0 89886 +0 3 +cfn=(3468) BTS::Fibre::Set::Reader::next(BTS::Fibre::Set&) +calls=1 0 +0 132468 +0 7 +cfn=(3436) std::basic_string, std::allocator > std::operator+, std::allocator >(std::basic_string, std::allocator > const&, char const*) +calls=1 0 +0 506 +0 6 +cob=(7) +cfi=(53) +cfn=(3550) +calls=1 0 +0 1827 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1970 +0 4 +cfn=(3552) BTS::Fibre::Tensor::Writer2::create(std::string const&, BTS::Fibre::Tract::Set const&) +calls=1 0 +0 869124 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 142 +0 6 +cfn=(3436) +calls=1 0 +0 482 +0 6 +cob=(7) +cfi=(53) +cfn=(3550) +calls=1 0 +0 1827 +0 4 +cfn=(3552) +calls=1 0 +0 864351 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 142 +0 2 +cob=(7) +cfi=(53) +cfn=(3612) +calls=1 0 +0 1937 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 2010 +0 2 +cob=(7) +cfi=(53) +cfn=(3612) +calls=1 0 +0 658 +0 2 +cob=(7) +cfi=(53) +cfn=(3612) +calls=1 0 +0 678 +0 15 +cob=(7) +cfi=(53) +cfn=(1468) +calls=2 0 +0 200 +0 9 +cfn=(3366) +calls=1 0 +0 68642 +0 12 +cfn=(3468) +calls=1 0 +0 116086 +0 4 +cfn=(3620) unsigned int BTS::Fibre::Unzipper::size >(BTS::Fibre::Set const&) +calls=1 0 +0 9507 +0 3 +cfn=(3620) +calls=1 0 +0 9507 +0 4 +cfn=(3626) MR::Math::Matrix::initialize(unsigned long, unsigned long) +calls=1 0 +0 1377 +0 83199 +cfn=(3620) +calls=1 0 +0 9892 +0 3 +cfn=(3620) +calls=1 0 +0 9507 +0 4 +cfn=(3626) +calls=1 0 +0 767 +0 82853 +cfn=(3628) BTS::Analysis::HessianTester::test(double (BTS::Prob::Likelihood::ImageDiff::Gaussian::*)(BTS::Fibre::Tract::Set const&, BTS::Fibre::Tract::Set&, BTS::Fibre::Tract::Set::Tensor&), BTS::Fibre::Tract::Set&, double, BTS::Fibre::Tract::Set::Tensor&, BTS::Fibre::Tract::Set::Tensor&) +calls=1 0 +0 7351891844380 +0 471 +cfn=(2878) BTS::Prob::Prior::Strand::EndOutSphere::radius_default(BTS::Image::Observed::Buffer const&) +calls=1 0 +0 7 +0 5 +cfn=(2876) BTS::Prob::Prior::Strand::EndInSphere::radius_default(BTS::Image::Observed::Buffer const&) +calls=1 0 +0 6 +0 103 +cob=(7) +cfi=(53) +cfn=(1446) +calls=1 0 +0 206 +0 7 +cob=(4) +cfi=(100) +cfn=(1476) +calls=1 25 +0 27 +0 6 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 100 +0 8 +cob=(7) +cfi=(53) +cfn=(1574) +calls=1 0 +0 2412 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1534 +0 8 +cob=(7) +cfi=(53) +cfn=(1446) +calls=1 0 +0 206 +0 8 +cob=(4) +cfi=(100) +cfn=(1476) +calls=1 25 +0 18 +0 6 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 100 +0 4 + +fn=(1482) +0 22 +cob=(7) +cfi=(53) +cfn=(722) +calls=2 0 +0 194 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1491 +0 48 +cob=(7) +cfi=(53) +cfn=(728) +calls=2 0 +0 1416 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 2322 +0 22 +cob=(7) +cfi=(53) +cfn=(728) +calls=2 0 +0 1416 +0 44 +cob=(7) +cfi=(53) +cfn=(492) +calls=2 0 +0 78 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1459 +0 24 +cob=(7) +cfi=(53) +cfn=(728) +calls=2 0 +0 1416 +0 16 + +fn=(1588) +0 1404 +cob=(7) +cfi=(53) +cfn=(1594) +calls=54 0 +0 2396 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1506 +0 810 +cob=(7) +cfi=(53) +cfn=(1594) +calls=162 0 +0 8152 +0 2462 +cfn=(1430) +calls=4 0 +0 1461 +0 4 + +fn=(1596) +0 1722 +cfn=(1600) std::vector >::operator=(std::vector > const&) +calls=1 0 +0 40 +0 121 +cob=(7) +cfi=(53) +cfn=(1174) +calls=2 0 +0 162 +0 767 +cob=(7) +cfi=(53) +cfn=(880) +calls=2 0 +0 220 +0 77 +cob=(7) +cfi=(53) +cfn=(880) +calls=1 0 +0 195 +0 25 +cob=(7) +cfi=(53) +cfn=(880) +calls=1 0 +0 195 +0 47 + +fn=(1714) MR::Math::operator>>(std::istream&, MR::Math::Matrix&) +0 837 +cob=(7) +cfi=(53) +cfn=(1730) +calls=61 0 +0 30267 +0 4 +cob=(7) +cfi=(53) +cfn=(1730) +calls=1 0 +0 9370 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 2531 +0 926 +cob=(7) +cfi=(53) +cfn=(1788) +calls=61 0 +0 3225 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1474 +0 305 +cob=(7) +cfi=(53) +cfn=(1446) +calls=61 0 +0 13797 +0 305 +cob=(7) +cfi=(53) +cfn=(1794) +calls=61 0 +0 2989 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1722 +0 488 +cob=(7) +cfi=(53) +cfn=(1800) +calls=61 0 +0 3111 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1690 +0 549 +cob=(7) +cfi=(53) +cfn=(1446) +calls=61 0 +0 13869 +0 183 +cob=(7) +cfi=(53) +cfn=(1264) +calls=61 0 +0 7503 +0 854 +cob=(7) +cfi=(53) +cfn=(880) +calls=61 0 +0 6726 +0 366 +cob=(7) +cfi=(53) +cfn=(880) +calls=61 0 +0 6879 +0 1333 +cob=(7) +cfi=(53) +cfn=(722) +calls=61 0 +0 5917 +0 1708 +cob=(7) +cfi=(53) +cfn=(728) +calls=61 0 +0 43188 +0 976 +cob=(7) +cfi=(53) +cfn=(492) +calls=61 0 +0 2379 +0 549 +cob=(7) +cfi=(53) +cfn=(1812) +calls=61 0 +0 12966 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1514 +0 366 +cob=(7) +cfi=(53) +cfn=(1528) +calls=61 0 +0 1281 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 2194 +0 183 +cob=(7) +cfi=(53) +cfn=(728) +calls=61 0 +0 43188 +0 732 +cob=(7) +cfi=(53) +cfn=(1822) +calls=61 0 +0 2806 +0 732 +cob=(7) +cfi=(53) +cfn=(1822) +calls=244 0 +0 411557 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1656 +0 2196 +cfn=(1852) std::vector >::_M_insert_aux(__gnu_cxx::__normal_iterator > >, double const&) +calls=183 0 +0 73886 +0 2247 +cob=(7) +cfi=(53) +cfn=(746) +calls=61 0 +0 732 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1483 +0 671 +cob=(7) +cfi=(53) +cfn=(1556) +calls=61 0 +0 3538 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1515 +0 3201 +cob=(7) +cfi=(53) +cfn=(1720) +calls=1 0 +0 1432 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1736 +0 4 +cob=(7) +cfi=(53) +cfn=(1724) +calls=1 0 +0 2 +0 306 +cob=(7) +cfi=(53) +cfn=(1372) +calls=61 0 +0 732 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1538 +0 857 +cob=(7) +cfi=(53) +cfn=(1174) +calls=61 0 +0 4941 +0 122 +cob=(7) +cfi=(53) +cfn=(1174) +calls=61 0 +0 4941 +0 183 +cob=(7) +cfi=(53) +cfn=(1174) +calls=61 0 +0 4941 +0 127 +cob=(7) +cfi=(53) +cfn=(1174) +calls=1 0 +0 114 +0 42 +cfn=(1806) std::vector >, false>, std::allocator >, false> > >::_M_insert_aux(__gnu_cxx::__normal_iterator >, false>*, std::vector >, false>, std::allocator >, false> > > >, MR::RefPtr >, false> const&) +calls=7 0 +0 4066 +0 13 +cob=(9) +cfi=(58) +cfn=(1916) gsl_block_alloc +calls=1 0 +0 2550 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 859 +0 372 +cob=(7) +cfi=(53) +cfn=(1310) +calls=61 0 +0 5002 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1682 +0 1159 +cob=(7) +cfi=(53) +cfn=(1310) +calls=61 0 +0 5002 +0 427 +cob=(7) +cfi=(53) +cfn=(1310) +calls=61 0 +0 5002 +0 549 + +fn=(1806) +0 158 +cob=(7) +cfi=(53) +cfn=(880) +calls=7 0 +0 1707 +0 1496 +cob=(7) +cfi=(53) +cfn=(1174) +calls=6 0 +0 548 +0 157 + +fn=(2390) +0 51019964 +cob=(7) +cfi=(53) +cfn=(880) +calls=2374861 0 +0 263540610 +0 23748610 +cob=(7) +cfi=(53) +cfn=(1258) +calls=2374861 0 +0 47497220 +0 14249166 +cfn=(2392) std::string* std::__uninitialized_move_a >(std::string*, std::string*, std::string*, std::allocator&) +calls=2374861 0 +0 80304329 +0 14249166 +cfn=(2392) +calls=2374861 0 +0 40372637 +0 18946158 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1174248 0 +0 17613720 +0 726 +cob=(7) +cfi=(53) +cfn=(1468) +calls=242 0 +0 3630 +0 9447198 +cob=(7) +cfi=(53) +cfn=(1174) +calls=1174248 0 +0 95114212 +0 52167847 + +fn=(2576) +0 60 +cob=(7) +cfi=(53) +cfn=(1928) +calls=3 0 +0 1908 +0 6 +cob=(7) +cfi=(53) +cfn=(1990) +calls=3 0 +0 51 +0 15 +cob=(7) +cfi=(53) +cfn=(746) +calls=3 0 +0 36 +0 36 +cob=(7) +cfi=(53) +cfn=(1556) +calls=3 0 +0 174 +0 90 +cob=(7) +cfi=(53) +cfn=(1310) +calls=3 0 +0 246 +0 17 +cob=(7) +cfi=(53) +cfn=(1310) +calls=1 0 +0 82 +0 37 + +fn=(2736) +0 45 +cob=(7) +cfi=(53) +cfn=(952) +calls=3 0 +0 419 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1682 +0 24 +cob=(4) +cfi=(81) +cfn=(966) +calls=3 56 +0 62 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1708 +0 30 + +fn=(2816) std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::_M_insert_unique_(std::_Rb_tree_const_iterator >, std::pair const&) +0 442 +cob=(7) +cfi=(53) +cfn=(2834) +calls=20 0 +0 1605 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1979 +0 130 +cfn=(2820) std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::_M_insert_(std::_Rb_tree_node_base const*, std::_Rb_tree_node_base const*, std::pair const&) +calls=6 0 +0 2774 +0 206 +cfn=(2818) std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::_M_insert_unique(std::pair const&) +calls=1 0 +0 273 +0 79 +cfn=(2820) +calls=6 0 +0 2330 +0 216 +cfn=(2820) +calls=14 0 +0 5417 +0 28 + +fn=(3020) std::vector >::vector(std::vector > const&) +0 6900 +cob=(7) +cfi=(53) +cfn=(880) +calls=300 0 +0 33056 +0 3900 +cob=(4) +cfi=(90) +cfn=(1282) +calls=300 47 +0 20400 +0 2100 + +fn=(3026) +0 19 +cob=(7) +cfi=(53) +cfn=(1594) +calls=1 0 +0 44 +0 14 +cob=(7) +cfi=(53) +cfn=(1594) +calls=1 0 +0 50 +0 5 +cob=(7) +cfi=(53) +cfn=(1594) +calls=1 0 +0 64 +0 4 +cob=(7) +cfi=(53) +cfn=(880) +calls=1 0 +0 383 +0 13 +cfn=(3028) BTS::Image::Expected::Quartic::Buffer::Buffer(BTS::Triple const&, BTS::Triple const&, BTS::Diffusion::Model const&, unsigned int, unsigned int, double, BTS::Triple const&, bool) +calls=1 0 +0 37774 +0 1 + +fn=(3072) +0 13 +cob=(7) +cfi=(53) +cfn=(1594) +calls=1 0 +0 65 +0 4 +cob=(7) +cfi=(53) +cfn=(880) +calls=1 0 +0 368 +0 8 +cfn=(3074) +calls=1 0 +0 89935 +0 10 + +fn=(3074) +0 34 +cfn=(3076) BTS::Image::Observed::Buffer::Buffer(BTS::Image::Observed::Buffer const&) +calls=2 0 +0 39832 +0 6 +cfn=(3080) BTS::Image::Expected::Quartic::Buffer::clone() const +calls=2 0 +0 61570 +0 34 +cfn=(3086) BTS::Image::Expected::Buffer::dims_match(BTS::Image::Observed::Buffer const&) +calls=2 0 +0 50 +0 10 +cfn=(3090) BTS::Prob::Likelihood::ImageDiff::set_assumed_snr(double) +calls=2 0 +0 78792 +0 6 +cfn=(3100) BTS::Image::Expected::Quartic::Buffer::zero() +calls=2 0 +0 34 +0 16 + +fn=(3092) BTS::Image::Observed::Buffer::average_b0() const +0 28 +cfn=(3094) BTS::Image::Observed::Voxel::b0() const +calls=2 0 +0 2866 +0 104 +cfn=(3094) +calls=52 0 +0 74516 +0 216 +cob=(7) +cfi=(53) +cfn=(2846) +calls=54 0 +0 834 +0 186 + +fn=(3094) +0 36936 +cfn=(3096) BTS::Image::Observed::Voxel::encoding(unsigned int) const +calls=3294 0 +0 26352 +0 14094 + +fn=(3120) +0 11 + +fn=(3252) BTS::Prob::Test::Peaks::Peak* std::__uninitialized_move_a >(BTS::Prob::Test::Peaks::Peak*, BTS::Prob::Test::Peaks::Peak*, BTS::Prob::Test::Peaks::Peak*, std::allocator&) +0 140 +cfn=(2888) MR::Math::Vector::initialize(unsigned long) +calls=7 0 +0 3032 +0 287 +cfn=(2888) +calls=7 0 +0 2774 +0 390 + +fn=(3258) BTS::MCMC::State::State(BTS::MCMC::State const&) +0 240 +cob=(9) +cfi=(58) +cfn=(1916) +calls=4 0 +0 848 +0 12 + +fn=(3348) +0 103651152 +cob=(7) +cfi=(53) +cfn=(1258) +calls=2835236 0 +0 56704720 +0 14176180 +cfn=(3350) std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::_M_insert_unique_(std::_Rb_tree_const_iterator >, std::pair const&) +calls=2835236 0 +0 876756874 +0 8505708 +cob=(7) +cfi=(53) +cfn=(1468) +calls=2835236 0 +0 42528540 +0 25451240 + +fn=(3372) MR::DWI::Tractography::ROISet::clear() +0 126 + +fn=(3504) BTS::Fibre::Tract::Tract(BTS::Fibre::Tract const&) +0 55385440 +cob=(7) +cfi=(53) +cfn=(880) +calls=1384636 0 +0 234325732 +0 115725404 +cob=(7) +cfi=(53) +cfn=(880) +calls=3595026 0 +0 418411146 +0 245680084 +cob=(7) +cfi=(53) +cfn=(934) +calls=1384636 0 +0 399557083 +0 6923180 +cfn=(3348) +calls=1384636 0 +0 525564832 +0 6923180 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1384636 0 +0 20769540 +0 8307816 +cob=(7) +cfi=(53) +cfn=(934) +calls=1384636 0 +0 400719343 +0 4153908 +cfn=(3348) +calls=1384636 0 +0 579707716 +0 6923180 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1384636 0 +0 20769540 +0 11077088 + +fn=(3544) BTS::Fibre::Properties::Extended::add_row(BTS::Fibre::Properties const&) +0 192 +cob=(7) +cfi=(53) +cfn=(1468) +calls=8 0 +0 56 +0 72 +cfn=(2410) +calls=8 0 +0 120 +0 104 + +fn=(3568) unsigned int BTS::Fibre::Properties::Intrinsic::num_intrinsic_keys() +0 9394848 +cfn=(3496) BTS::Fibre::Tract::Tract() +calls=1174356 0 +0 1795761632 +0 9394848 +cob=(7) +cfi=(53) +cfn=(2846) +calls=2348712 0 +0 35230680 +0 9394848 +cfn=(3508) BTS::Fibre::Tract::~Tract() +calls=1174356 0 +0 648244512 +0 7046136 + +fn=(3622) unsigned int BTS::Fibre::Properties::Intrinsic::num_intrinsic_keys >() +0 1504743 +cob=(7) +cfi=(53) +cfn=(934) +calls=26399 0 +0 6177734 +0 79197 +cfn=(3348) +calls=26399 0 +0 8403112 +0 105596 +cob=(7) +cfi=(53) +cfn=(1468) +calls=26399 0 +0 395985 +0 79197 +cfn=(2642) +calls=26399 0 +0 290389 +0 184793 +cob=(7) +cfi=(53) +cfn=(2846) +calls=26399 0 +0 475182 +0 158394 +cfn=(3624) BTS::Fibre::Set::~Set() +calls=26399 0 +0 8210089 +0 184793 + +fn=(3624) +0 475038 +cfn=(3564) BTS::Fibre::Properties::Extended::~Extended() +calls=52782 0 +0 2955792 +0 211192 +cfn=(3508) +calls=32 0 +0 25536 +0 158450 +cob=(7) +cfi=(53) +cfn=(1174) +calls=8 0 +0 848 +0 158346 +cfn=(2642) +calls=52782 0 +0 580602 +0 316692 +cfn=(3510) std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::_M_erase(std::_Rb_tree_node >*) +calls=52782 0 +0 9106255 +0 211128 + +fn=(3626) +0 1797783 +cob=(9) +cfi=(58) +cfn=(1916) +calls=61991 0 +0 189226503 +0 309955 + +fn=(3628) +0 21 +cfn=(3630) BTS::Fibre::Tract::Set::Set(BTS::Fibre::Tract::Set const&) +calls=1 0 +0 12121 +0 5 +cfn=(3630) +calls=1 0 +0 11725 +0 5 +cfn=(3630) +calls=1 0 +0 11725 +0 948 +cfn=(3620) +calls=1 0 +0 9932 +0 3 +cfn=(3620) +calls=1 0 +0 9507 +0 6 +cfn=(3626) +calls=1 0 +0 745 +0 69510 +cfn=(3620) +calls=1 0 +0 9932 +0 3 +cfn=(3620) +calls=1 0 +0 9507 +0 4 +cfn=(3626) +calls=1 0 +0 612 +0 69511 +cfn=(3634) MR::Math::Matrix::allocate(unsigned long, unsigned long) +calls=1 0 +0 15 +0 181249 +cob=(9) +cfi=(58) +cfn=(2654) gsl_block_free +calls=1 0 +0 205 +0 14 +cfn=(3636) BTS::Prob::Likelihood::ImageDiff::log_prob(BTS::Fibre::Tract::Set const&, BTS::Fibre::Tract::Set&, BTS::Fibre::Tract::Set::Tensor&) +calls=1 0 +0 883781669435 +0 5 +cfn=(3918) MR::Math::Vector BTS::Fibre::Unzipper::unzip >(BTS::Fibre::Set const&) +calls=1 0 +0 28043 +0 6 +cfn=(3626) +calls=1 0 +0 2864 +0 83202 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 263 +0 6 +cfn=(3926) MR::ProgressBar::ProgressBar(std::string const&, unsigned long) +calls=1 0 +0 3754 +0 2 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 15 +0 3874 +cfn=(3946) void BTS::Fibre::Unzipper::zip_intrinsic >(MR::Math::Vector const&, BTS::Fibre::Set&, unsigned int&) +calls=8 0 +0 12768 +0 128 +cfn=(3950) void BTS::Fibre::Unzipper::zip_element(MR::Math::Vector const&, BTS::Fibre::Tract&, unsigned int&) +calls=8 0 +0 30144 +0 168 +cfn=(3950) +calls=24 0 +0 90240 +0 368 +cfn=(3268) +calls=8 0 +0 144 +0 184 +cob=(7) +cfi=(53) +cfn=(880) +calls=8 0 +0 1137 +0 256 +cfn=(3504) +calls=32 0 +0 65522 +0 208 +cfn=(3632) BTS::Fibre::Properties::Extended::Extended(BTS::Fibre::Properties::Extended const&) +calls=8 0 +0 960 +0 32 +cob=(7) +cfi=(53) +cfn=(934) +calls=8 0 +0 1888 +0 32 +cfn=(3348) +calls=8 0 +0 3104 +0 40 +cob=(7) +cfi=(53) +cfn=(1468) +calls=8 0 +0 120 +0 16 +cfn=(3624) +calls=8 0 +0 29040 +0 56 +cfn=(3636) +calls=8 0 +0 6468108997754 +0 70 +cfn=(3918) +calls=7 0 +0 196672 +0 21 +cfn=(3918) +calls=7 0 +0 186788 +0 9100 +cob=(9) +cfi=(58) +cfn=(2654) +calls=7 0 +0 1421 +0 13244 +cfn=(3958) MR::ProgressBar::operator++() +calls=7 0 +0 12455 +0 28 +cob=(9) +cfi=(58) +cfn=(2654) +calls=7 0 +0 1407 +0 91 + +fn=(3642) void BTS::Image::Expected::Buffer_tpl::expected_image(BTS::Fibre::Tract::Set const&, BTS::Image::Container::Buffer::Set&, BTS::Image::Container::Buffer::Set&) +0 1090351 +cfn=(3956) T.6671 +calls=1896 0 +0 5688 +0 3792 +cfn=(3956) +calls=1896 0 +0 5688 +0 41712 +cfn=(3744) BTS::Triple::invalidate() +calls=1896 0 +0 117552 +0 3792 +cfn=(3744) +calls=1896 0 +0 117552 +0 30336 +cfn=(3956) +calls=1896 0 +0 5688 +0 3792 +cfn=(3956) +calls=1896 0 +0 5688 +0 7584 +cob=(7) +cfi=(53) +cfn=(2852) +calls=1896 0 +0 28136 +0 7764 +cfn=(3664) void BTS::Image::Expected::Buffer_tpl::part_image(BTS::Fibre::Tract const&, BTS::Image::Container::Buffer&, BTS::Image::Container::Buffer&) +calls=34 0 +0 7329775575153 +0 582 +cfn=(3644) non-virtual thunk to BTS::Image::Expected::Quartic::Buffer::num_encodings() const +calls=4 0 +0 32 +0 114 +cfn=(3654) std::_Rb_tree >, std::_Select1st > >, std::less, std::allocator > > >::_M_erase(std::_Rb_tree_node > >*) +calls=1 0 +0 19 +0 15 +cfn=(3654) +calls=3 0 +0 57 +0 16 +cfn=(3644) +calls=4 0 +0 32 +0 114 +cfn=(3662) std::_Rb_tree >, std::_Select1st > >, std::less, std::allocator > > >::_M_erase(std::_Rb_tree_node > >*) +calls=1 0 +0 19 +0 15 +cfn=(3662) +calls=3 0 +0 57 +0 170 +cfn=(3644) +calls=30 0 +0 240 +0 330 +cob=(7) +cfi=(53) +cfn=(2852) +calls=30 0 +0 322 +0 8031 +cob=(7) +cfi=(53) +cfn=(2852) +calls=2677 0 +0 39402 +0 5594 +cfn=(3644) +calls=30 0 +0 240 +0 510 +cob=(7) +cfi=(53) +cfn=(2852) +calls=30 0 +0 322 +0 8031 +cob=(7) +cfi=(53) +cfn=(2852) +calls=2677 0 +0 39402 +0 5700 +cfn=(3648) std::vector, std::allocator > >::_M_insert_aux(__gnu_cxx::__normal_iterator*, std::vector, std::allocator > > >, BTS::Image::Container::Buffer const&) +calls=3 0 +0 44967418 +0 24 +cfn=(3656) std::vector, std::allocator > >::_M_insert_aux(__gnu_cxx::__normal_iterator*, std::vector, std::allocator > > >, BTS::Image::Container::Buffer const&) +calls=3 0 +0 2483330722 +0 12 + +fn=(3654) +0 98 +cfn=(3655) std::_Rb_tree >, std::_Select1st > >, std::less, std::allocator > > >::_M_erase(std::_Rb_tree_node > >*)'2 +calls=3 0 +0 4429256 +0 76 +cfn=(3655) +calls=19 0 +0 5413783 +0 2838 +cfn=(3508) +calls=1342 0 +0 1070916 +0 4114 +cob=(7) +cfi=(53) +cfn=(1174) +calls=22 0 +0 2389 +0 66 +cob=(7) +cfi=(53) +cfn=(1174) +calls=22 0 +0 1782 +0 100 + +fn=(3655) +0 3212 +cfn=(3655) +calls=110 0 +0 10582967 +0 360 +cfn=(3655) +calls=90 0 +0 3988017 +0 25800 +cfn=(3508) +calls=12200 0 +0 9735600 +0 37400 +cob=(7) +cfi=(53) +cfn=(1174) +calls=200 0 +0 21691 +0 600 +cob=(7) +cfi=(53) +cfn=(1174) +calls=200 0 +0 16200 +0 2176 + +fn=(3656) +0 71 +cob=(7) +cfi=(53) +cfn=(880) +calls=3 0 +0 16571 +0 27 +cfn=(3658) BTS::Image::Container::Buffer::Buffer(BTS::Image::Container::Buffer const&) +calls=3 0 +0 96 +0 18 +cfn=(3660) BTS::Image::Container::Buffer* std::__uninitialized_move_a*, BTS::Image::Container::Buffer*, std::allocator > >(BTS::Image::Container::Buffer*, BTS::Image::Container::Buffer*, BTS::Image::Container::Buffer*, std::allocator >&) +calls=3 0 +0 2156235276 +0 18 +cfn=(3660) +calls=3 0 +0 51 +0 32 +cfn=(3662) +calls=2 0 +0 206265852 +0 4 +cfn=(3662) +calls=1 0 +0 120812403 +0 19 +cob=(7) +cfi=(53) +cfn=(1174) +calls=2 0 +0 200 +0 84 + +fn=(3662) +0 98 +cfn=(3663) std::_Rb_tree >, std::_Select1st > >, std::less, std::allocator > > >::_M_erase(std::_Rb_tree_node > >*)'2 +calls=3 0 +0 132599453 +0 76 +cfn=(3663) +calls=19 0 +0 162066027 +0 2838 +cfn=(3816) BTS::Fibre::Tract::Tensor::~Tensor() +calls=1342 0 +0 32401313 +0 4114 +cob=(7) +cfi=(53) +cfn=(1174) +calls=22 0 +0 2464 +0 66 +cob=(7) +cfi=(53) +cfn=(1174) +calls=22 0 +0 1782 +0 100 + +fn=(3663) +0 3212 +cfn=(3663) +calls=110 0 +0 316766724 +0 360 +cfn=(3663) +calls=90 0 +0 119341062 +0 25800 +cfn=(3816) +calls=12200 0 +0 294557472 +0 37400 +cob=(7) +cfi=(53) +cfn=(1174) +calls=200 0 +0 22260 +0 600 +cob=(7) +cfi=(53) +cfn=(1174) +calls=200 0 +0 16200 +0 2176 + +fn=(3674) std::_Rb_tree, std::less, std::allocator > > > >, std::_Select1st, std::less, std::allocator > > > > >, std::less, std::allocator, std::less, std::allocator > > > > > >::_M_insert_unique(std::pair, std::less, std::allocator > > > > const&) +0 50 +cfn=(3676) std::_Rb_tree, std::less, std::allocator > > > >, std::_Select1st, std::less, std::allocator > > > > >, std::less, std::allocator, std::less, std::allocator > > > > > >::_M_insert_(std::_Rb_tree_node_base const*, std::_Rb_tree_node_base const*, std::pair, std::less, std::allocator > > > > const&) +calls=2 0 +0 671 +0 4 + +fn=(3678) std::_Rb_tree >, std::_Select1st > >, std::less, std::allocator > > >::_M_erase(std::_Rb_tree_node > >*) +0 44 + +fn=(3680) MR::Math::Matrix::Matrix(MR::Math::Matrix const&) +0 62 + +fn=(3740) BTS::Image::Observed::Voxel::Voxel(unsigned int, BTS::Image::Coord const&) +0 4503 +cob=(7) +cfi=(53) +cfn=(880) +calls=237 0 +0 110141 +0 65175 + +fn=(3742) BTS::Fibre::Strand::Section::Tensor::Tensor() +0 75366 +cfn=(3744) +calls=711 0 +0 44082 +0 68967 +cfn=(3744) +calls=711 0 +0 44082 +0 24174 + +fn=(3802) std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::_M_insert_unique_(std::_Rb_tree_const_iterator >, std::pair const&) +0 1607606 +cob=(7) +cfi=(53) +cfn=(2438) +calls=61831 0 +0 1051127 +0 1360282 +cfn=(3804) std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::_M_insert_unique(std::pair const&) +calls=61831 0 +0 17447221 +0 309155 +cfn=(3806) std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::_M_insert_(std::_Rb_tree_node_base const*, std::_Rb_tree_node_base const*, std::pair const&) +calls=61831 0 +0 15639825 +0 61831 + +fn=(3836) std::vector, std::allocator > >::operator=(std::vector, std::allocator > > const&) +0 3072570 +cob=(7) +cfi=(53) +cfn=(880) +calls=66795 0 +0 11389093 +0 400770 +cfn=(3838) BTS::Coord::Tensor_tpl* std::__uninitialized_copy_a<__gnu_cxx::__normal_iterator const*, std::vector, std::allocator > > >, BTS::Coord::Tensor_tpl*, BTS::Coord::Tensor_tpl >(__gnu_cxx::__normal_iterator const*, std::vector, std::allocator > > >, __gnu_cxx::__normal_iterator const*, std::vector, std::allocator > > >, BTS::Coord::Tensor_tpl*, std::allocator >&) +calls=66795 0 +0 3287595405 +0 801540 + +fn=(3848) BTS::Triple::zero() +0 189123096 +cfn=(3846) T.2790 +calls=11124888 0 +0 33374664 +0 22249776 +cfn=(3846) +calls=11124888 0 +0 33374664 +0 133498656 +cfn=(3846) +calls=11124888 0 +0 33374664 +0 22249776 +cfn=(3846) +calls=11124888 0 +0 33374664 +0 133498656 +cfn=(3846) +calls=11124888 0 +0 33374664 +0 22249776 +cfn=(3846) +calls=11124888 0 +0 33374664 +0 66749328 + +fn=(3870) std::vector >, std::allocator > > >::operator=(std::vector >, std::allocator > > > const&) +0 432 + +fn=(3890) void BTS::Fibre::Flattener::flatten_intrinsic(BTS::Fibre::Tract::Tensor const&, MR::Math::Matrix&, unsigned int&) +0 463112 +cfn=(3892) std::vector > BTS::Fibre::Properties::Intrinsic_tpl::intrinsic_keys() +calls=35624 0 +0 97764208 +0 605608 +cfn=(3894) void std::__introsort_loop<__gnu_cxx::__normal_iterator > >, long>(__gnu_cxx::__normal_iterator > >, __gnu_cxx::__normal_iterator > >, long) +calls=35624 0 +0 748104 +0 106872 +cfn=(3896) void std::__final_insertion_sort<__gnu_cxx::__normal_iterator > > >(__gnu_cxx::__normal_iterator > >, __gnu_cxx::__normal_iterator > >) +calls=35624 0 +0 6626064 +0 249368 +cfn=(3902) BTS::Fibre::Properties::Intrinsic_tpl::intrinsic_property(std::string const&) const +calls=35624 0 +0 4025512 +0 106872 +cfn=(3902) +calls=35624 0 +0 3918640 +0 213744 +cfn=(3904) MR::Math::Vector BTS::Fibre::Unzipper::unzip(BTS::Fibre::Tract const&) +calls=71248 0 +0 451310856 +0 13822112 +cob=(9) +cfi=(58) +cfn=(2654) +calls=71248 0 +0 13537120 +0 284992 +cfn=(2410) +calls=35624 0 +0 10936568 +0 284992 + +fn=(3274) +0 60 +cob=(7) +cfi=(53) +cfn=(722) +calls=5 0 +0 485 +0 120 +cob=(7) +cfi=(53) +cfn=(728) +calls=5 0 +0 3540 +0 60 +cob=(7) +cfi=(53) +cfn=(728) +calls=5 0 +0 3540 +0 110 +cob=(7) +cfi=(53) +cfn=(492) +calls=5 0 +0 195 +0 50 +cob=(7) +cfi=(53) +cfn=(728) +calls=5 0 +0 3540 +0 20 +cob=(7) +cfi=(53) +cfn=(3280) +calls=5 0 +0 17468 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1632 +0 15 +cob=(7) +cfi=(53) +cfn=(1534) +calls=5 0 +0 1745 +0 55 +cob=(7) +cfi=(53) +cfn=(1468) +calls=5 0 +0 668 +0 25 +cob=(7) +cfi=(53) +cfn=(746) +calls=5 0 +0 60 +0 80 +cob=(7) +cfi=(53) +cfn=(1556) +calls=5 0 +0 290 +0 45 + +fn=(1108) global constructors keyed to triple.cpp +0 4 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 51 + +fn=(1126) global constructors keyed to section.cpp +0 6 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 407 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 330 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 313 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 317 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 9 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 315 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 18 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 330 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 313 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 317 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 9 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 12 + +fn=(1134) global constructors keyed to gaussian.cpp +0 5 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 330 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 313 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 317 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 12 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 330 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 313 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 317 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 + +fn=(1156) T.14265 +0 8 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 407 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 330 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 313 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 317 +0 6 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 71 +cfn=(1158) MR::Option::append(MR::Argument const&) +calls=1 0 +0 1577 +0 3 +cfn=(1166) MR::Option::Option(MR::Option const&) +calls=1 0 +0 275 +0 4 +cfn=(1168) MR::Option::~Option() +calls=1 0 +0 3034 +0 23 +cfn=(1158) +calls=1 0 +0 193 +0 3 +cfn=(1166) +calls=1 0 +0 275 +0 4 +cfn=(1168) +calls=1 0 +0 85 +0 23 +cfn=(1158) +calls=1 0 +0 193 +0 3 +cfn=(1166) +calls=1 0 +0 275 +0 4 +cfn=(1168) +calls=1 0 +0 85 +0 37 +cfn=(1158) +calls=1 0 +0 193 +0 3 +cfn=(1166) +calls=1 0 +0 275 +0 4 +cfn=(1168) +calls=1 0 +0 85 +0 23 +cfn=(1158) +calls=1 0 +0 193 +0 3 +cfn=(1166) +calls=1 0 +0 275 +0 4 +cfn=(1168) +calls=1 0 +0 85 +0 25 +cfn=(1158) +calls=1 0 +0 193 +0 3 +cfn=(1166) +calls=1 0 +0 275 +0 4 +cfn=(1168) +calls=1 0 +0 85 +0 25 +cfn=(1158) +calls=1 0 +0 193 +0 3 +cfn=(1166) +calls=1 0 +0 275 +0 4 +cfn=(1168) +calls=1 0 +0 85 +0 23 +cfn=(1158) +calls=1 0 +0 193 +0 3 +cfn=(1166) +calls=1 0 +0 275 +0 4 +cfn=(1168) +calls=1 0 +0 85 +0 23 +cfn=(1158) +calls=1 0 +0 193 +0 3 +cfn=(1166) +calls=1 0 +0 275 +0 4 +cfn=(1168) +calls=1 0 +0 85 +0 40 +cfn=(1158) +calls=1 0 +0 193 +0 3 +cfn=(1166) +calls=1 0 +0 275 +0 4 +cfn=(1168) +calls=1 0 +0 85 +0 28 +cfn=(1158) +calls=1 0 +0 193 +0 3 +cfn=(1166) +calls=1 0 +0 275 +0 4 +cfn=(1168) +calls=1 0 +0 85 +0 27 +cfn=(1158) +calls=1 0 +0 193 +0 3 +cfn=(1166) +calls=1 0 +0 275 +0 4 +cfn=(1168) +calls=1 0 +0 85 +0 28 +cfn=(1158) +calls=1 0 +0 193 +0 3 +cfn=(1166) +calls=1 0 +0 275 +0 4 +cfn=(1168) +calls=1 0 +0 85 +0 24 +cfn=(1158) +calls=1 0 +0 193 +0 3 +cfn=(1166) +calls=1 0 +0 275 +0 4 +cfn=(1168) +calls=1 0 +0 85 +0 27 +cfn=(1158) +calls=1 0 +0 193 +0 3 +cfn=(1166) +calls=1 0 +0 275 +0 4 +cfn=(1168) +calls=1 0 +0 85 +0 27 +cfn=(1158) +calls=1 0 +0 193 +0 3 +cfn=(1166) +calls=1 0 +0 275 +0 4 +cfn=(1168) +calls=1 0 +0 85 +0 25 +cfn=(1158) +calls=1 0 +0 193 +0 3 +cfn=(1166) +calls=1 0 +0 275 +0 4 +cfn=(1168) +calls=1 0 +0 85 +0 28 +cfn=(1158) +calls=1 0 +0 193 +0 3 +cfn=(1166) +calls=1 0 +0 275 +0 4 +cfn=(1168) +calls=1 0 +0 85 +0 40 +cfn=(1158) +calls=1 0 +0 193 +0 3 +cfn=(1166) +calls=1 0 +0 275 +0 4 +cfn=(1168) +calls=1 0 +0 85 +0 25 +cfn=(1158) +calls=1 0 +0 193 +0 3 +cfn=(1166) +calls=1 0 +0 275 +0 4 +cfn=(1168) +calls=1 0 +0 85 +0 28 +cfn=(1158) +calls=1 0 +0 193 +0 3 +cfn=(1166) +calls=1 0 +0 275 +0 4 +cfn=(1168) +calls=1 0 +0 85 +0 25 +cfn=(1158) +calls=1 0 +0 193 +0 3 +cfn=(1166) +calls=1 0 +0 275 +0 4 +cfn=(1168) +calls=1 0 +0 85 +0 40 +cfn=(1158) +calls=1 0 +0 193 +0 3 +cfn=(1166) +calls=1 0 +0 275 +0 4 +cfn=(1168) +calls=1 0 +0 85 +0 28 +cfn=(1158) +calls=1 0 +0 193 +0 3 +cfn=(1166) +calls=1 0 +0 275 +0 4 +cfn=(1168) +calls=1 0 +0 85 +0 63 +cfn=(1158) +calls=1 0 +0 193 +0 3 +cfn=(1158) +calls=1 0 +0 397 +0 3 +cfn=(1166) +calls=1 0 +0 293 +0 4 +cfn=(1168) +calls=1 0 +0 85 +0 50 +cfn=(1158) +calls=1 0 +0 193 +0 3 +cfn=(1158) +calls=1 0 +0 312 +0 3 +cfn=(1166) +calls=1 0 +0 293 +0 4 +cfn=(1168) +calls=1 0 +0 85 +0 62 +cfn=(1158) +calls=1 0 +0 193 +0 3 +cfn=(1158) +calls=1 0 +0 312 +0 3 +cfn=(1158) +calls=1 0 +0 407 +0 3 +cfn=(1166) +calls=1 0 +0 303 +0 4 +cfn=(1168) +calls=1 0 +0 116 +0 56 +cfn=(1158) +calls=1 0 +0 193 +0 3 +cfn=(1158) +calls=1 0 +0 312 +0 3 +cfn=(1158) +calls=1 0 +0 362 +0 3 +cfn=(1166) +calls=1 0 +0 303 +0 4 +cfn=(1168) +calls=1 0 +0 116 +0 60 +cfn=(1158) +calls=1 0 +0 193 +0 3 +cfn=(1158) +calls=1 0 +0 312 +0 3 +cfn=(1158) +calls=1 0 +0 362 +0 3 +cfn=(1166) +calls=1 0 +0 303 +0 4 +cfn=(1168) +calls=1 0 +0 116 +0 60 +cfn=(1158) +calls=1 0 +0 193 +0 3 +cfn=(1158) +calls=1 0 +0 312 +0 3 +cfn=(1158) +calls=1 0 +0 362 +0 3 +cfn=(1166) +calls=1 0 +0 303 +0 4 +cfn=(1168) +calls=1 0 +0 116 +0 87 +cfn=(1158) +calls=1 0 +0 193 +0 3 +cfn=(1158) +calls=1 0 +0 312 +0 3 +cfn=(1158) +calls=1 0 +0 362 +0 3 +cfn=(1158) +calls=1 0 +0 25 +0 3 +cfn=(1158) +calls=1 0 +0 474 +0 3 +cfn=(1166) +calls=1 0 +0 382 +0 4 +cfn=(1168) +calls=1 0 +0 116 +0 50 +cfn=(1158) +calls=1 0 +0 193 +0 3 +cfn=(1158) +calls=1 0 +0 312 +0 3 +cfn=(1166) +calls=1 0 +0 369 +0 4 +cfn=(1168) +calls=1 0 +0 85 +0 50 +cfn=(1158) +calls=1 0 +0 193 +0 3 +cfn=(1158) +calls=1 0 +0 312 +0 3 +cfn=(1166) +calls=1 0 +0 442 +0 4 +cfn=(1168) +calls=1 0 +0 85 +0 63 +cfn=(1158) +calls=1 0 +0 193 +0 3 +cfn=(1158) +calls=1 0 +0 312 +0 3 +cfn=(1158) +calls=1 0 +0 378 +0 3 +cfn=(1166) +calls=1 0 +0 434 +0 4 +cfn=(1168) +calls=1 0 +0 127 +0 50 +cfn=(1158) +calls=1 0 +0 193 +0 3 +cfn=(1158) +calls=1 0 +0 312 +0 3 +cfn=(1166) +calls=1 0 +0 394 +0 4 +cfn=(1168) +calls=1 0 +0 85 +0 63 +cfn=(1158) +calls=1 0 +0 193 +0 3 +cfn=(1158) +calls=1 0 +0 312 +0 3 +cfn=(1158) +calls=1 0 +0 488 +0 3 +cfn=(1166) +calls=1 0 +0 288 +0 4 +cfn=(1168) +calls=1 0 +0 280 +0 61 +cfn=(1158) +calls=1 0 +0 230 +0 3 +cfn=(1158) +calls=1 0 +0 352 +0 3 +cfn=(1158) +calls=1 0 +0 407 +0 3 +cfn=(1166) +calls=1 0 +0 319 +0 4 +cfn=(1168) +calls=1 0 +0 116 +0 75 +cfn=(1158) +calls=1 0 +0 193 +0 3 +cfn=(1158) +calls=1 0 +0 312 +0 3 +cfn=(1158) +calls=1 0 +0 362 +0 3 +cfn=(1158) +calls=1 0 +0 25 +0 3 +cfn=(1166) +calls=1 0 +0 321 +0 3 +cfn=(1168) +calls=1 0 +0 116 +0 49 +cfn=(1158) +calls=1 0 +0 193 +0 3 +cfn=(1158) +calls=1 0 +0 312 +0 3 +cfn=(1166) +calls=1 0 +0 369 +0 4 +cfn=(1168) +calls=1 0 +0 85 +0 21 +cfn=(1158) +calls=1 0 +0 193 +0 3 +cfn=(1166) +calls=1 0 +0 344 +0 4 +cfn=(1168) +calls=1 0 +0 85 +0 23 +cfn=(1158) +calls=1 0 +0 193 +0 3 +cfn=(1166) +calls=1 0 +0 333 +0 4 +cfn=(1168) +calls=1 0 +0 85 +0 26 +cfn=(1158) +calls=1 0 +0 193 +0 3 +cfn=(1166) +calls=1 0 +0 387 +0 4 +cfn=(1168) +calls=1 0 +0 85 +0 26 +cfn=(1158) +calls=1 0 +0 193 +0 3 +cfn=(1166) +calls=1 0 +0 275 +0 4 +cfn=(1168) +calls=1 0 +0 85 +0 26 +cfn=(1158) +calls=1 0 +0 193 +0 3 +cfn=(1166) +calls=1 0 +0 275 +0 4 +cfn=(1168) +calls=1 0 +0 85 +0 26 +cfn=(1158) +calls=1 0 +0 193 +0 3 +cfn=(1166) +calls=1 0 +0 275 +0 4 +cfn=(1168) +calls=1 0 +0 85 +0 26 +cfn=(1158) +calls=1 0 +0 193 +0 3 +cfn=(1166) +calls=1 0 +0 275 +0 4 +cfn=(1168) +calls=1 0 +0 85 +0 23 +cfn=(1158) +calls=1 0 +0 193 +0 3 +cfn=(1166) +calls=1 0 +0 275 +0 4 +cfn=(1168) +calls=1 0 +0 85 +0 23 +cfn=(1158) +calls=1 0 +0 193 +0 3 +cfn=(1166) +calls=1 0 +0 275 +0 4 +cfn=(1168) +calls=1 0 +0 85 +0 23 +cfn=(1158) +calls=1 0 +0 193 +0 3 +cfn=(1166) +calls=1 0 +0 275 +0 3 +cfn=(1168) +calls=1 0 +0 85 +0 3 +cfn=(1166) +calls=1 0 +0 44 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 130 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 315 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 7 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 312 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 7 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 312 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 7 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 312 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 7 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 312 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 7 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 312 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 1 + +fn=(1186) global constructors keyed to writer.cpp +0 5 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 342 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 + +fn=(1216) global constructors keyed to end_in_sphere.cpp +0 6 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 330 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 313 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 317 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 312 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 8 + +fn=(2012) +0 90 +cob=(4) +cfi=(69) +cfn=(642) +calls=9 26 +0 222 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1690 +0 81 +cob=(7) +cfi=(53) +cfn=(1384) +calls=9 0 +0 2326 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1450 +0 36 +cob=(7) +cfi=(53) +cfn=(1772) +calls=9 0 +0 599 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1508 +0 27 +cob=(7) +cfi=(53) +cfn=(1406) +calls=9 0 +0 699 +0 63 + +fn=(2392) +0 56892414 +cob=(7) +cfi=(53) +cfn=(1258) +calls=1174490 0 +0 23489800 +0 40294752 + +fn=(2402) +0 692 +cfn=(3618) std::string* std::__uninitialized_copy_a(std::string*, std::string*, std::string*, std::allocator&) +calls=1 0 +0 81 +0 324 +cob=(7) +cfi=(53) +cfn=(880) +calls=6 0 +0 1073 +0 36 +cfn=(2404) std::string* std::__uninitialized_copy_a<__gnu_cxx::__normal_iterator > >, std::string*, std::string>(__gnu_cxx::__normal_iterator > >, __gnu_cxx::__normal_iterator > >, std::string*, std::allocator&) +calls=6 0 +0 7466 +0 101 +cob=(7) +cfi=(53) +cfn=(1264) +calls=1 0 +0 123 +0 56 + +fn=(2472) MR::Image::Axes::Axis* std::__uninitialized_move_a >(MR::Image::Axes::Axis*, MR::Image::Axes::Axis*, MR::Image::Axes::Axis*, std::allocator&) +0 42 + +fn=(2588) +0 36 +cob=(7) +cfi=(53) +cfn=(880) +calls=3 0 +0 346 +0 21 +cob=(7) +cfi=(53) +cfn=(1258) +calls=3 0 +0 60 +0 9 +cob=(7) +cfi=(53) +cfn=(1258) +calls=3 0 +0 60 +0 33 +cfn=(2589) std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::_M_copy(std::_Rb_tree_node > const*, std::_Rb_tree_node >*)'2 +calls=3 0 +0 4362 +0 24 +cob=(7) +cfi=(53) +cfn=(880) +calls=3 0 +0 720 +0 2 +cob=(7) +cfi=(53) +cfn=(880) +calls=1 0 +0 168 +0 28 +cob=(7) +cfi=(53) +cfn=(1258) +calls=4 0 +0 80 +0 12 +cob=(7) +cfi=(53) +cfn=(1258) +calls=4 0 +0 80 +0 36 +cfn=(2589) +calls=1 0 +0 249 +0 44 + +fn=(2589) +0 144 +cob=(7) +cfi=(53) +cfn=(880) +calls=12 0 +0 2457 +0 84 +cob=(7) +cfi=(53) +cfn=(1258) +calls=12 0 +0 240 +0 36 +cob=(7) +cfi=(53) +cfn=(1258) +calls=12 0 +0 240 +0 108 +cfn=(2589) +calls=6 0 +0 5412 +0 54 +cob=(7) +cfi=(53) +cfn=(880) +calls=3 0 +0 498 +0 4 +cob=(7) +cfi=(53) +cfn=(880) +calls=2 0 +0 318 +0 35 +cob=(7) +cfi=(53) +cfn=(1258) +calls=5 0 +0 100 +0 15 +cob=(7) +cfi=(53) +cfn=(1258) +calls=5 0 +0 100 +0 48 +cfn=(2589) +calls=2 0 +0 494 +0 130 + +fn=(2640) MR::Image::Axes::Axis::~Axis() +0 40 +cob=(7) +cfi=(53) +cfn=(1468) +calls=8 0 +0 359 +0 32 +cob=(7) +cfi=(53) +cfn=(1468) +calls=8 0 +0 359 + +fn=(2880) +0 23 +cob=(7) +cfi=(53) +cfn=(1174) +calls=1 0 +0 114 +0 15 +cfn=(2882) BTS::Diffusion::Model::Model(MR::Math::Matrix const&, double, double, bool) +calls=1 0 +0 7036515 +0 3 +cfn=(3024) std::vector >::operator=(std::vector > const&) +calls=1 0 +0 32524 +0 249 +cob=(9) +cfi=(58) +cfn=(2654) +calls=61 0 +0 10065 +0 185 + +fn=(2888) +0 25441392 +cob=(9) +cfi=(58) +cfn=(1916) +calls=1060058 0 +0 243525329 +0 4240232 + +fn=(3004) BTS::Diffusion::Model::SH_to_coeffs(MR::Math::Vector, bool) +0 7680 +cob=(6) +cfi=(126) /build/buildd/eglibc-2.11.1/math/w_pow.c +cfn=(3010) pow +calls=300 29 +0 75780 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1382 +0 2640 +cob=(7) +cfi=(53) +cfn=(1174) +calls=60 0 +0 4860 +0 300 +cob=(7) +cfi=(53) +cfn=(880) +calls=60 0 +0 6600 +0 1320 +cob=(7) +cfi=(53) +cfn=(1174) +calls=60 0 +0 4860 +0 300 +cob=(7) +cfi=(53) +cfn=(880) +calls=60 0 +0 6600 +0 1320 +cob=(7) +cfi=(53) +cfn=(1174) +calls=60 0 +0 4860 +0 300 +cob=(7) +cfi=(53) +cfn=(880) +calls=60 0 +0 6600 +0 1380 +cfn=(3020) +calls=60 0 +0 13260 +0 420 +cob=(7) +cfi=(53) +cfn=(1174) +calls=60 0 +0 4860 +0 300 +cob=(7) +cfi=(53) +cfn=(880) +calls=60 0 +0 6600 +0 1320 +cob=(7) +cfi=(53) +cfn=(1174) +calls=60 0 +0 4860 +0 13740 +cfn=(2888) +calls=60 0 +0 14400 +0 17160 +cob=(7) +cfi=(53) +cfn=(1174) +calls=300 0 +0 24300 +0 1140 +cob=(7) +cfi=(53) +cfn=(1174) +calls=60 0 +0 7061 +0 1020 +cob=(7) +cfi=(53) +cfn=(880) +calls=60 0 +0 6600 +0 1260 +cfn=(3018) std::vector >, std::allocator > > >::_M_insert_aux(__gnu_cxx::__normal_iterator >*, std::vector >, std::allocator > > > >, std::vector > const&) +calls=60 0 +0 71066 +0 420 +cfn=(3018) +calls=60 0 +0 51263 +0 420 +cfn=(3018) +calls=60 0 +0 119365 +0 420 +cfn=(3018) +calls=60 0 +0 27105 +0 60 + +fn=(3086) +0 8 +cfn=(3088) BTS::Image::Expected::Quartic::Buffer::dims() const +calls=2 0 +0 4 +0 38 + +fn=(3254) BTS::Prob::Test::Peaks::Peak::~Peak() +0 95 +cfn=(3256) BTS::MCMC::State::~State() +calls=19 0 +0 3572 +0 76 +cfn=(3256) +calls=19 0 +0 3572 + +fn=(3270) +0 16 +cfn=(3254) +calls=1 0 +0 385 +0 10 +cfn=(3254) +calls=5 0 +0 1925 +0 22 +cob=(7) +cfi=(53) +cfn=(1174) +calls=1 0 +0 127 +0 10 + +fn=(3468) +0 22 +cfn=(3470) BTS::Fibre::Base::Reader >::next(BTS::Fibre::Set&, BTS::Fibre::Properties&) +calls=2 0 +0 122250 +0 60 +cfn=(3474) std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::_M_erase(std::_Rb_tree_node >*) +calls=2 0 +0 22 +0 40 +cfn=(3524) BTS::Fibre::Set::Reader::extended_elem_header() const +calls=2 0 +0 4906 +0 18 +cfn=(3528) std::vector >::vector(unsigned long, std::string const&, std::allocator const&) +calls=2 0 +0 58 +0 8 +cfn=(3524) +calls=2 0 +0 5092 +0 12 +cfn=(3530) BTS::Fibre::Properties::Extended::add_properties(BTS::Fibre::Properties::Header const&, std::vector > const&) +calls=2 0 +0 66 +0 4 +cfn=(3462) BTS::Fibre::Properties::Header::~Header() +calls=2 0 +0 192 +0 4 +cfn=(2410) +calls=2 0 +0 30 +0 4 +cfn=(3462) +calls=2 0 +0 192 +0 4 +cob=(7) +cfi=(53) +cfn=(1468) +calls=2 0 +0 14 +0 36 +cob=(7) +cfi=(53) +cfn=(1730) +calls=2 0 +0 910 +0 26 +cfn=(3532) BTS::Fibre::Set::Reader::is_row_seperator(std::string const&) +calls=2 0 +0 38 +0 16 +cfn=(3532) +calls=8 0 +0 1450 +0 100 +cfn=(3512) BTS::Fibre::Properties::Extended::parse_line(std::string const&) +calls=8 0 +0 33846 +0 168 +cfn=(3272) +calls=8 0 +0 3032 +0 48 +cfn=(3272) +calls=8 0 +0 3352 +0 48 +cob=(7) +cfi=(53) +cfn=(1264) +calls=16 0 +0 448 +0 184 +cfn=(3534) BTS::Fibre::Tract::set_intrinsic_properties(BTS::Fibre::Properties&) +calls=8 0 +0 65653 +0 24 +cfn=(3544) +calls=8 0 +0 544 +0 104 +cob=(7) +cfi=(53) +cfn=(1730) +calls=8 0 +0 2689 +0 56 +cfn=(2642) +calls=8 0 +0 88 +0 16 +cfn=(2410) +calls=8 0 +0 2456 +0 20 +cob=(7) +cfi=(53) +cfn=(1468) +calls=2 0 +0 200 +0 4 + +fn=(3500) std::vector, std::allocator > >::_M_insert_aux(__gnu_cxx::__normal_iterator*, std::vector, std::allocator > > >, BTS::Triple const&) +0 89577585900 +cob=(7) +cfi=(53) +cfn=(880) +calls=4071708450 0 +0 447888135171 +0 190013061000 +cob=(7) +cfi=(53) +cfn=(1174) +calls=2714472300 0 +0 219872256300 +0 84148641300 + +fn=(3562) BTS::Fibre::Tract::Set::~Set() +0 237186 +cfn=(3564) +calls=26354 0 +0 1475824 +0 316232 +cfn=(3508) +calls=105408 0 +0 84115584 +0 421638 +cob=(7) +cfi=(53) +cfn=(1174) +calls=26352 0 +0 2797778 +0 79062 +cfn=(2642) +calls=26354 0 +0 289894 +0 158124 +cfn=(3510) +calls=26354 0 +0 5666110 +0 105416 + +fn=(3682) std::_Rb_tree >, std::_Select1st > >, std::less, std::allocator > > >::_M_insert_unique_(std::_Rb_tree_const_iterator > >, std::pair > const&) +0 40 +cfn=(3684) std::_Rb_tree >, std::_Select1st > >, std::less, std::allocator > > >::_M_insert_unique(std::pair > const&) +calls=2 0 +0 615 +0 2 + +fn=(3706) BTS::Diffusion::Response::weighting(BTS::Triple const&, BTS::Triple&, BTS::Coord::Tensor&) +0 9683526662 +cfn=(3708) BTS::Triple::outer(BTS::Triple const&) const +calls=125155080 0 +0 4881048120 +0 1752171120 +cfn=(3708) +calls=41718360 0 +0 1627016040 +0 6174317280 +cfn=(3708) +calls=166873440 0 +0 6508064160 +0 667493760 +cfn=(3708) +calls=166873440 0 +0 6508064160 +0 7175557920 +cfn=(3708) +calls=166873440 0 +0 6508064160 +0 15734079474 + +fn=(3726) std::_Rb_tree, std::less, std::allocator >::_M_erase(std::_Rb_tree_node*) +0 7651619 +cfn=(3727) std::_Rb_tree, std::less, std::allocator >::_M_erase(std::_Rb_tree_node*)'2 +calls=695407 0 +0 212817709 +0 4978365 +cfn=(3727) +calls=1659455 0 +0 139600196 +0 7064586 +cob=(7) +cfi=(53) +cfn=(1174) +calls=2354862 0 +0 190743822 +0 9847438 + +fn=(3727) +0 48809308 +cfn=(3727) +calls=2466629 0 +0 130538577 +0 2225295 +cfn=(3727) +calls=741765 0 +0 17185089 +0 9625182 +cob=(7) +cfi=(53) +cfn=(1174) +calls=3208394 0 +0 259879914 +0 31878206 + +fn=(3756) std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::_M_insert_unique(std::pair const&) +0 14 +cfn=(3758) std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::_M_insert_(std::_Rb_tree_node_base const*, std::_Rb_tree_node_base const*, std::pair const&) +calls=1 0 +0 815 +0 12 + +fn=(3758) +0 2886 +cob=(7) +cfi=(53) +cfn=(880) +calls=93 0 +0 44801 +0 288 +cob=(7) +cfi=(53) +cfn=(880) +calls=144 0 +0 60104 +0 2370 +cfn=(3752) BTS::Image::Expected::Voxel::Voxel(BTS::Image::Expected::Voxel const&) +calls=237 0 +0 123714 +0 2370 +cob=(7) +cfi=(53) +cfn=(2426) +calls=237 0 +0 17587 +0 4304 + +fn=(3772) BTS::Image::Container::Buffer::new_voxel(BTS::Image::Coord const&) +0 5110 +cfn=(3496) +calls=365 0 +0 536908 +0 3650 +cob=(7) +cfi=(53) +cfn=(880) +calls=365 0 +0 6550572 +0 114245 +cfn=(3504) +calls=22265 0 +0 41304464 +0 90520 +cfn=(3508) +calls=365 0 +0 201480 +0 4745 + +fn=(3810) BTS::Image::Container::Buffer::new_voxel(BTS::Image::Coord const&) +0 1460 +cfn=(3812) BTS::Image::Voxel::Voxel(unsigned int) +calls=365 0 +0 127344424 +0 2555 + +fn=(3812) +0 8395 +cfn=(3496) +calls=365 0 +0 526695 +0 1095 +cfn=(3496) +calls=365 0 +0 526695 +0 2920 +cob=(7) +cfi=(53) +cfn=(880) +calls=365 0 +0 40150 +0 38690 +cfn=(3800) BTS::Fibre::Tract::Tensor_tpl::init() +calls=365 0 +0 433985 +0 3650 +cob=(7) +cfi=(53) +cfn=(880) +calls=365 0 +0 2949731 +0 114975 +cfn=(3814) BTS::Fibre::Tract::Tensor::Tensor(BTS::Fibre::Tract::Tensor const&) +calls=22265 0 +0 121995548 +0 91250 +cfn=(3816) +calls=365 0 +0 607725 +0 2920 + +fn=(3816) +0 1802078 +cfn=(3508) +calls=152424 0 +0 121634352 +0 457272 +cfn=(3508) +calls=152424 0 +0 121634352 +0 304848 +cfn=(3508) +calls=152424 0 +0 121634352 +0 864174 +cob=(7) +cfi=(53) +cfn=(1174) +calls=50808 0 +0 5400087 +0 514358 +cob=(7) +cfi=(53) +cfn=(1174) +calls=39566 0 +0 3204846 +0 79132 +cfn=(3508) +calls=39566 0 +0 26006688 +0 79132 +cfn=(3508) +calls=39566 0 +0 26006688 +0 118698 +cfn=(3818) std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::_M_erase(std::_Rb_tree_node >*) +calls=39566 0 +0 16538588 +0 316528 + +fn=(3824) std::_Rb_tree >, std::_Select1st > >, std::less, std::allocator > > >::_M_insert_unique(std::pair > const&) +0 56 +cfn=(3826) std::_Rb_tree >, std::_Select1st > >, std::less, std::allocator > > >::_M_insert_(std::_Rb_tree_node_base const*, std::_Rb_tree_node_base const*, std::pair > const&) +calls=4 0 +0 1158 +0 48 + +fn=(3844) BTS::Triple::norm(BTS::Triple&, BTS::Coord::Tensor&) const +0 344871528 + +fn=(3856) BTS::Fibre::BasicStrand::operator+=(BTS::Fibre::BasicStrand const&) +0 442798285977 + +fn=(3858) std::vector, std::allocator > >::vector(std::vector, std::allocator > > const&) +0 15608215449 +cob=(7) +cfi=(53) +cfn=(880) +calls=678618063 0 +0 74647986930 +0 41395701843 + +fn=(3864) BTS::Fibre::Tract::Section::~Section() +0 10276200 + +fn=(3868) std::_Rb_tree >, std::_Select1st > >, std::less, std::allocator > > >::_M_copy(std::_Rb_tree_node > > const*, std::_Rb_tree_node > >*) +0 36 +cob=(7) +cfi=(53) +cfn=(880) +calls=3 0 +0 415 +0 81 +cob=(7) +cfi=(53) +cfn=(880) +calls=3 0 +0 4646970 +0 954 +cfn=(3814) +calls=183 0 +0 28335603 +0 978 +cfn=(3869) std::_Rb_tree >, std::_Select1st > >, std::less, std::allocator > > >::_M_copy(std::_Rb_tree_node > > const*, std::_Rb_tree_node > >*)'2 +calls=3 0 +0 870861248 +0 30 +cob=(7) +cfi=(53) +cfn=(880) +calls=3 0 +0 585 +0 32 +cob=(7) +cfi=(53) +cfn=(880) +calls=16 0 +0 3120 +0 570 +cob=(7) +cfi=(53) +cfn=(880) +calls=19 0 +0 24340 +0 6023 +cfn=(3814) +calls=1159 0 +0 184417920 +0 6121 +cfn=(3869) +calls=15 0 +0 1067929787 +0 118 + +fn=(3869) +0 1320 +cob=(7) +cfi=(53) +cfn=(880) +calls=110 0 +0 20917 +0 2970 +cob=(7) +cfi=(53) +cfn=(880) +calls=110 0 +0 142883 +0 34980 +cfn=(3814) +calls=6710 0 +0 1064826984 +0 35632 +cfn=(3869) +calls=53 0 +0 2081090932 +0 706 +cob=(7) +cfi=(53) +cfn=(880) +calls=54 0 +0 10503 +0 72 +cob=(7) +cfi=(53) +cfn=(880) +calls=36 0 +0 7020 +0 2700 +cob=(7) +cfi=(53) +cfn=(880) +calls=90 0 +0 115253 +0 28530 +cfn=(3814) +calls=5490 0 +0 873530310 +0 28866 +cfn=(3869) +calls=39 0 +0 786381398 +0 1389 + +fn=(3888) BTS::Fibre::Flattener::length(BTS::Fibre::Tract::Tensor const&) +0 106872 +cfn=(3568) +calls=35624 0 +0 75314723 +0 1959320 + +fn=(3924) MR::Math::Matrix BTS::Math::outer(MR::Math::Vector const&, MR::Math::Vector const&) +0 144936 +cfn=(3626) +calls=13176 0 +0 52737481 +0 1652771088 + +fn=(2822) BTS::Image::Observed::Voxel::~Voxel() +0 513 +cob=(7) +cfi=(53) +cfn=(1174) +calls=27 0 +0 3035 +0 54 + +fn=(1070) global constructors keyed to end_out_sphere.cpp +0 6 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1579 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1778 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1498 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 407 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 330 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 313 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 317 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 37 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 5 + +fn=(1096) global constructors keyed to common.cpp +0 3 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 5 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 330 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 313 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 317 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 407 +0 4 + +fn=(1140) global constructors keyed to prior.cpp +0 5 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 330 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 313 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 317 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 + +fn=(1154) global constructors keyed to test_gradient.cpp +0 1 +cfn=(1156) +calls=1 0 +0 49975 + +fn=(1184) global constructors keyed to tensor.cpp +0 5 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 407 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 330 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 313 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 317 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 8 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 6 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 3 + +fn=(1190) global constructors keyed to KMlocal.cpp +0 7 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 6 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 330 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 313 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 317 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 + +fn=(1192) global constructors keyed to KMeans.cpp +0 5 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 330 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 313 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 317 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 + +fn=(1204) global constructors keyed to model.cpp +0 5 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 330 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 313 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 317 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 407 +0 4 + +fn=(1210) global constructors keyed to KMdata.cpp +0 7 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 6 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 330 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 313 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 317 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 + +fn=(1436) +0 56 +cob=(7) +cfi=(53) +cfn=(1246) +calls=4 0 +0 640 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1650 +0 56 +cob=(7) +cfi=(53) +cfn=(1446) +calls=4 0 +0 824 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1434 +0 12 +cob=(7) +cfi=(53) +cfn=(1264) +calls=4 0 +0 112 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1506 +0 8 +cob=(7) +cfi=(53) +cfn=(1468) +calls=4 0 +0 60 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1440 +0 24 + +fn=(1602) +0 16 +cob=(7) +cfi=(53) +cfn=(722) +calls=1 0 +0 97 +0 22 +cob=(7) +cfi=(53) +cfn=(728) +calls=1 0 +0 708 +0 7 +cob=(7) +cfi=(53) +cfn=(1608) +calls=1 0 +0 4123 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1938 +0 3 +cob=(7) +cfi=(53) +cfn=(728) +calls=1 0 +0 708 +0 4 +cob=(7) +cfi=(53) +cfn=(1632) +calls=1 0 +0 11631 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 2282 +0 7 +cob=(7) +cfi=(53) +cfn=(1712) +calls=1 0 +0 8 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 2154 +0 5 +cfn=(1714) +calls=1 0 +0 783365 +0 9 +cob=(7) +cfi=(53) +cfn=(1928) +calls=1 0 +0 10007 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 2010 +0 2 +cob=(7) +cfi=(53) +cfn=(1990) +calls=1 0 +0 17 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1619 +0 5 +cob=(7) +cfi=(53) +cfn=(746) +calls=1 0 +0 12 +0 9 +cob=(7) +cfi=(53) +cfn=(1556) +calls=1 0 +0 58 +0 12 + +fn=(1852) +0 5490 +cob=(7) +cfi=(53) +cfn=(880) +calls=183 0 +0 35161 +0 2745 +cob=(4) +cfi=(90) +cfn=(1282) +calls=183 47 +0 9699 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1698 +0 1464 +cob=(4) +cfi=(90) +cfn=(1282) +calls=183 47 +0 4392 +0 671 +cob=(7) +cfi=(53) +cfn=(1174) +calls=122 0 +0 9882 +0 2684 + +fn=(2432) +0 80 +cob=(7) +cfi=(53) +cfn=(1468) +calls=16 0 +0 112 +0 64 +cob=(7) +cfi=(53) +cfn=(1468) +calls=16 0 +0 240 + +fn=(2470) void std::__uninitialized_fill_n_a(MR::Image::Axes::Axis*, unsigned long, MR::Image::Axes::Axis const&, std::allocator&) +0 65 +cob=(7) +cfi=(53) +cfn=(1258) +calls=4 0 +0 60 +0 12 +cob=(7) +cfi=(53) +cfn=(1258) +calls=4 0 +0 60 +0 24 + +fn=(2884) MR::Math::Matrix::Matrix(unsigned long, unsigned long) +0 7105 +cob=(9) +cfi=(58) +cfn=(1916) +calls=245 0 +0 98433 +0 1225 + +fn=(2886) BTS::Diffusion::Model::tensor_m0_SH(double, double, double) +0 549 +cfn=(2888) +calls=61 0 +0 14672 +0 488 +cfn=(2890) MR::Math::Vector& MR::Math::SH::FA2SH(MR::Math::Vector&, double, double, double, int, int) +calls=61 0 +0 6294369 +0 244 + +fn=(3032) BTS::Diffusion::Model::Model(BTS::Diffusion::Model const&) +0 84 +cob=(7) +cfi=(53) +cfn=(880) +calls=3 0 +0 6546 +0 19716 +cob=(9) +cfi=(58) +cfn=(1916) +calls=183 0 +0 68332 +0 549 + +fn=(3080) +0 12 +cob=(7) +cfi=(53) +cfn=(880) +calls=2 0 +0 374 +0 8 +cfn=(3082) BTS::Image::Expected::Quartic::Buffer::Buffer(BTS::Image::Expected::Quartic::Buffer const&) +calls=2 0 +0 61166 +0 10 + +fn=(3082) +0 22 +cfn=(3084) BTS::Image::Expected::Buffer_tpl::Buffer_tpl(BTS::Image::Expected::Buffer_tpl const&) +calls=2 0 +0 61006 +0 14 +cfn=(3042) BTS::Image::Expected::Quartic::Buffer::init() +calls=2 0 +0 116 +0 8 + +fn=(3098) BTS::Image::Observed::Buffer::encoding(unsigned int) const +0 13176 + +fn=(3104) covariant return thunk to BTS::Prob::Uniform::clone() const +0 2 +cfn=(3105) covariant return thunk to BTS::Prob::Uniform::clone() const'2 +calls=1 0 +0 216 + +fn=(3105) +0 2 +cfn=(3106) BTS::Prob::Uniform::clone() const +calls=1 0 +0 207 +0 7 + +fn=(3106) +0 3 +cob=(7) +cfi=(53) +cfn=(880) +calls=1 0 +0 195 +0 9 + +fn=(3108) non-virtual thunk to BTS::Prob::Uniform::~Uniform() +0 2 +cfn=(3110) BTS::Prob::Uniform::~Uniform() +calls=1 0 +0 91 + +fn=(3116) std::vector >::_M_insert_aux(__gnu_cxx::__normal_iterator > >, BTS::Prob::StrandComponent* const&) +0 59 +cob=(7) +cfi=(53) +cfn=(880) +calls=2 0 +0 305 +0 30 +cob=(4) +cfi=(90) +cfn=(1282) +calls=2 47 +0 97 +0 16 +cob=(4) +cfi=(90) +cfn=(1282) +calls=2 47 +0 48 +0 7 +cob=(7) +cfi=(53) +cfn=(1174) +calls=1 0 +0 81 +0 28 + +fn=(3246) BTS::Prob::Test::Peaks::Peak::Peak(BTS::MCMC::State const&, BTS::MCMC::State const&, double, unsigned int) +0 696 +cob=(9) +cfi=(58) +cfn=(1916) +calls=6 0 +0 1442 +0 30 +cob=(9) +cfi=(58) +cfn=(1916) +calls=6 0 +0 1442 +0 18 + +fn=(3366) +0 22 +cfn=(3368) BTS::Fibre::Base::Reader >::open(std::string const&) +calls=2 0 +0 140732 +0 8 +cfn=(3436) +calls=2 0 +0 698 +0 6 +cob=(7) +cfi=(53) +cfn=(1258) +calls=2 0 +0 40 +0 4 +cfn=(3438) BTS::File::is_file(std::string) +calls=2 0 +0 60 +0 6 +cob=(7) +cfi=(53) +cfn=(1468) +calls=2 0 +0 30 +0 14 +cob=(7) +cfi=(53) +cfn=(1632) +calls=2 0 +0 3150 +0 14 +cob=(7) +cfi=(53) +cfn=(1712) +calls=2 0 +0 16 +0 6 +cfn=(3444) BTS::Fibre::Properties::Extended::read_header(std::basic_ifstream >&) +calls=2 0 +0 12693 +0 6 +cfn=(2402) +calls=2 0 +0 525 +0 4 +cfn=(3462) +calls=2 0 +0 274 +0 6 +cob=(7) +cfi=(53) +cfn=(1468) +calls=2 0 +0 200 +0 14 + +fn=(3444) +0 44 +cfn=(3446) BTS::Fibre::Properties::Extended::read_preamble(std::basic_ifstream >&) +calls=4 0 +0 7627 +0 92 +cob=(7) +cfi=(53) +cfn=(1730) +calls=4 0 +0 2137 +0 28 +cob=(7) +cfi=(53) +cfn=(722) +calls=4 0 +0 388 +0 100 +cob=(7) +cfi=(53) +cfn=(728) +calls=4 0 +0 2832 +0 64 +cob=(7) +cfi=(53) +cfn=(492) +calls=4 0 +0 156 +0 36 +cob=(7) +cfi=(53) +cfn=(1812) +calls=4 0 +0 1125 +0 24 +cob=(7) +cfi=(53) +cfn=(1528) +calls=4 0 +0 84 +0 12 +cob=(7) +cfi=(53) +cfn=(728) +calls=4 0 +0 2832 +0 56 +cob=(7) +cfi=(53) +cfn=(1730) +calls=4 0 +0 1977 +0 24 +cob=(7) +cfi=(53) +cfn=(1730) +calls=6 0 +0 3227 +0 48 +cob=(7) +cfi=(53) +cfn=(1468) +calls=4 0 +0 400 +0 40 +cob=(7) +cfi=(53) +cfn=(1468) +calls=4 0 +0 400 +0 20 +cob=(7) +cfi=(53) +cfn=(746) +calls=4 0 +0 48 +0 44 +cob=(7) +cfi=(53) +cfn=(1556) +calls=4 0 +0 232 +0 8 +cob=(7) +cfi=(53) +cfn=(1468) +calls=4 0 +0 400 +0 78 +cfn=(2390) +calls=6 0 +0 1941 +0 6 + +fn=(3464) MR::DWI::Tractography::Properties::~Properties() +0 14 +cfn=(2642) +calls=2 0 +0 22 +0 4 +cfn=(2410) +calls=2 0 +0 30 +0 4 +cfn=(3466) MR::DWI::Tractography::ROISet::~ROISet() +calls=2 0 +0 40 +0 4 +cfn=(3466) +calls=2 0 +0 40 +0 4 +cfn=(3466) +calls=2 0 +0 40 +0 4 +cfn=(3466) +calls=2 0 +0 40 +0 6 +cfn=(2642) +calls=2 0 +0 1108 +0 8 + +fn=(3512) +0 120 +cob=(7) +cfi=(53) +cfn=(722) +calls=10 0 +0 970 +0 220 +cob=(7) +cfi=(53) +cfn=(728) +calls=10 0 +0 7080 +0 160 +cob=(7) +cfi=(53) +cfn=(492) +calls=10 0 +0 390 +0 90 +cob=(7) +cfi=(53) +cfn=(1812) +calls=10 0 +0 1968 +0 60 +cob=(7) +cfi=(53) +cfn=(1528) +calls=10 0 +0 210 +0 30 +cob=(7) +cfi=(53) +cfn=(728) +calls=10 0 +0 7080 +0 120 +cob=(7) +cfi=(53) +cfn=(1730) +calls=10 0 +0 4339 +0 72 +cob=(7) +cfi=(53) +cfn=(1730) +calls=18 0 +0 8708 +0 132 +cob=(7) +cfi=(53) +cfn=(1468) +calls=10 0 +0 1000 +0 90 +cob=(7) +cfi=(53) +cfn=(1468) +calls=10 0 +0 1000 +0 50 +cob=(7) +cfi=(53) +cfn=(746) +calls=10 0 +0 120 +0 90 +cob=(7) +cfi=(53) +cfn=(1556) +calls=10 0 +0 580 +0 216 +cfn=(2390) +calls=18 0 +0 5370 +0 18 + +fn=(3554) BTS::Fibre::Properties::Header BTS::Fibre::Unzipper::header(BTS::Fibre::Tract::Set const&) +0 36 +cob=(7) +cfi=(53) +cfn=(934) +calls=2 0 +0 114 +0 18 +cob=(7) +cfi=(53) +cfn=(1468) +calls=2 0 +0 30 +0 4 +cob=(7) +cfi=(53) +cfn=(1468) +calls=2 0 +0 200 +0 4 +cob=(7) +cfi=(53) +cfn=(2846) +calls=2 0 +0 36 +0 14 +cfn=(1396) +calls=2 0 +0 564 +0 8 +cfn=(3436) +calls=2 0 +0 664 +0 14 +cfn=(2390) +calls=2 0 +0 482 +0 38 +cfn=(3338) +calls=2 0 +0 6978 +0 18 +cfn=(3338) +calls=6 0 +0 20730 +0 32 +cfn=(3436) +calls=8 0 +0 2360 +0 32 +cfn=(1396) +calls=8 0 +0 2328 +0 32 +cfn=(3436) +calls=8 0 +0 2552 +0 56 +cfn=(3556) void BTS::Fibre::Unzipper::header_element(BTS::Fibre::Tract const&, BTS::Fibre::Properties::Header&, std::string const&) +calls=8 0 +0 1560323 +0 16 +cob=(7) +cfi=(53) +cfn=(1468) +calls=8 0 +0 800 +0 16 +cob=(7) +cfi=(53) +cfn=(1468) +calls=8 0 +0 800 +0 16 +cob=(7) +cfi=(53) +cfn=(1468) +calls=8 0 +0 800 +0 16 +cob=(7) +cfi=(53) +cfn=(1468) +calls=8 0 +0 800 +0 84 +cob=(7) +cfi=(53) +cfn=(1468) +calls=2 0 +0 14 +0 18 + +fn=(3630) +0 632592 +cob=(7) +cfi=(53) +cfn=(880) +calls=13179 0 +0 5624539 +0 461265 +cfn=(3504) +calls=52716 0 +0 121817684 +0 355833 +cfn=(3632) +calls=13179 0 +0 1581480 +0 65895 +cob=(7) +cfi=(53) +cfn=(934) +calls=13179 0 +0 4375389 +0 39537 +cfn=(3348) +calls=13179 0 +0 5706417 +0 52716 +cob=(7) +cfi=(53) +cfn=(1468) +calls=13179 0 +0 197685 +0 144969 + +fn=(3632) +0 1582440 + +fn=(3652) BTS::Image::Container::Buffer* std::__uninitialized_move_a*, BTS::Image::Container::Buffer*, std::allocator > >(BTS::Image::Container::Buffer*, BTS::Image::Container::Buffer*, BTS::Image::Container::Buffer*, std::allocator >&) +0 124 +cfn=(3866) std::_Rb_tree >, std::_Select1st > >, std::less, std::allocator > > >::_M_copy(std::_Rb_tree_node > > const*, std::_Rb_tree_node > >*) +calls=3 0 +0 34035767 +0 272 + +fn=(3666) BTS::Fibre::Tract::sections(unsigned int, unsigned int, BTS::Triple const&, BTS::Triple const&) const +0 986 +cfn=(3668) std::vector >::reserve(unsigned long) +calls=34 0 +0 131699604 +0 1028 +cfn=(3672) std::_Rb_tree, std::less, std::allocator > > > >, std::_Select1st, std::less, std::allocator > > > > >, std::less, std::allocator, std::less, std::allocator > > > > > >::_M_insert_unique_(std::_Rb_tree_const_iterator, std::less, std::allocator > > > > >, std::pair, std::less, std::allocator > > > > const&) +calls=1 0 +0 316 +0 5 +cfn=(3678) +calls=1 0 +0 11 +0 3 +cfn=(3678) +calls=1 0 +0 11 +0 615 +cfn=(3680) +calls=1 0 +0 31 +0 4 +cfn=(3682) +calls=1 0 +0 343 +0 183 +cfn=(3688) BTS::Fibre::Strand::create_position_matrix(unsigned int, unsigned int, bool) +calls=1 0 +0 9291 +0 3 +cfn=(3696) MR::Math::Matrix::operator=(MR::Math::Matrix const&) +calls=1 0 +0 1425 +0 5 +cob=(9) +cfi=(58) +cfn=(2654) +calls=1 0 +0 196 +0 926 +cfn=(3672) +calls=1 0 +0 451 +0 4 +cfn=(3678) +calls=1 0 +0 11 +0 3 +cfn=(3678) +calls=1 0 +0 11 +0 682 +cfn=(3680) +calls=1 0 +0 31 +0 4 +cfn=(3682) +calls=1 0 +0 314 +0 424742667 +cfn=(3698) BTS::Fibre::Strand::create_tangent_matrix(unsigned int, unsigned int, bool) +calls=1 0 +0 9639 +0 3 +cfn=(3696) +calls=1 0 +0 1425 +0 5 +cob=(9) +cfi=(58) +cfn=(2654) +calls=1 0 +0 196 +0 307 + +fn=(3672) +0 40 +cfn=(3674) +calls=2 0 +0 725 +0 2 + +fn=(3732) non-virtual thunk to BTS::Image::Expected::Quartic::Buffer::new_voxel(BTS::Image::Coord const&) +0 474 +cfn=(3734) BTS::Image::Expected::Quartic::Buffer::new_voxel(BTS::Image::Coord const&) +calls=237 0 +0 3577119 + +fn=(3764) BTS::Image::Expected::Voxel::operator=(BTS::Image::Expected::Voxel const&) +0 2607 +cfn=(2824) +calls=237 0 +0 136808 +0 353841 +cfn=(3748) std::vector >::_M_insert_aux(__gnu_cxx::__normal_iterator > >, BTS::Image::Expected::Direction const&) +calls=1659 0 +0 848822 +0 5214 + +fn=(3820) BTS::Image::Container::Voxel::Voxel(BTS::Image::Container::Voxel const&) +0 16425 + +fn=(3830) std::vector >::operator=(std::vector > const&) +0 16425 +cob=(7) +cfi=(53) +cfn=(880) +calls=365 0 +0 438546 +0 2190 +cfn=(3832) BTS::Fibre::Tract::Tensor* std::__uninitialized_copy_a<__gnu_cxx::__normal_iterator > >, BTS::Fibre::Tract::Tensor*, BTS::Fibre::Tract::Tensor>(__gnu_cxx::__normal_iterator > >, __gnu_cxx::__normal_iterator > >, BTS::Fibre::Tract::Tensor*, std::allocator&) +calls=365 0 +0 121600119 +0 4745 + +fn=(3892) +0 12916420 +cfn=(3496) +calls=1174220 0 +0 1762285787 +0 9393760 +cob=(7) +cfi=(53) +cfn=(2846) +calls=2348440 0 +0 35226600 +0 25832840 +cfn=(2390) +calls=2348440 0 +0 722092540 +0 4696880 +cfn=(3508) +calls=1174220 0 +0 448552040 +0 8219540 + +fn=(3894) +0 25212495 + +fn=(3952) void BTS::Fibre::Unzipper::zip_intrinsic(MR::Math::Vector const&, BTS::Fibre::Tract&, unsigned int&) +0 384 +cfn=(3892) +calls=32 0 +0 80704 +0 512 +cfn=(3894) +calls=32 0 +0 672 +0 96 +cfn=(3896) +calls=32 0 +0 5952 +0 224 +cfn=(3948) BTS::Fibre::Properties::Intrinsic_tpl::intrinsic_property(std::string const&) +calls=32 0 +0 3616 +0 96 +cfn=(3948) +calls=32 0 +0 3520 +0 832 +cfn=(2410) +calls=32 0 +0 9824 +0 256 + +fn=(2826) double MR::Image::(anonymous namespace)::__getLE(void const*, unsigned long) +0 4941 + +fn=(2828) void MR::DataSet::Loop::next_impl >(unsigned long, MR::Image::Voxel&) +0 25297 + +fn=(1106) global constructors keyed to buffer.cpp +0 6 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 330 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 313 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 317 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 313 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 13 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 330 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 313 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 317 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 10 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 330 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 313 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 317 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 308 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 14 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 351 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 330 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 313 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 317 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 310 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 14 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 245 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 313 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 317 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 13 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 11 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 407 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 330 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 313 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 317 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 8 + +fn=(1116) global constructors keyed to all_in_cube.cpp +0 6 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 407 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 330 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 313 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 317 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 14 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 407 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 330 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 313 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 317 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 8 + +fn=(1150) global constructors keyed to momentum.cpp +0 5 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 359 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 + +fn=(2404) +0 1303 +cob=(7) +cfi=(53) +cfn=(1258) +calls=245 0 +0 4890 +0 1273 + +fn=(2468) +0 38 +cob=(7) +cfi=(53) +cfn=(880) +calls=1 0 +0 213 +0 11 +cfn=(2470) +calls=1 0 +0 221 +0 6 +cfn=(2472) +calls=1 0 +0 21 +0 8 +cfn=(2472) +calls=1 0 +0 21 +0 31 + +fn=(2660) MR::Image::Voxel::Voxel(MR::Image::Header const&) +0 24 +cob=(7) +cfi=(53) +cfn=(880) +calls=1 0 +0 126 +0 26 +cob=(11) +cfi=(60) +cfn=(2666) +calls=1 0 +0 54066 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1144 +0 24 + +fn=(2808) BTS::Image::Observed::Buffer::new_voxel(BTS::Image::Coord const&) +0 81 +cfn=(2810) BTS::Image::Observed::Voxel::Voxel(BTS::Image::Observed::Buffer&, BTS::Image::Coord const&) +calls=27 0 +0 12812 +0 81 + +fn=(2814) BTS::Image::Observed::Voxel::Voxel(BTS::Image::Observed::Voxel const&) +0 864 +cob=(4) +cfi=(90) +cfn=(1282) +calls=27 47 +0 648 +0 594 + +fn=(2876) +0 6 + +fn=(3042) +0 15 +cob=(4) +cfi=(130) +cfn=(3050) +calls=3 81 +0 159 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1699 + +fn=(3100) +0 34 + +fn=(3112) BTS::Prob::Prior::Tract::add_component(BTS::Prob::StrandComponent const&) +0 12 +cfn=(3118) BTS::Prob::Prior::Strand::EndOutSphere::clone() const +calls=1 0 +0 210 +cfn=(3114) BTS::Prob::Prior::Strand::EndInSphere::clone() const +calls=1 0 +0 125 +0 20 +cfn=(3116) +calls=2 0 +0 671 +0 2 + +fn=(3272) +0 1854 +cob=(7) +cfi=(53) +cfn=(1258) +calls=31 0 +0 620 +0 124 +cob=(7) +cfi=(53) +cfn=(1258) +calls=31 0 +0 465 +0 124 +cfn=(2416) +calls=31 0 +0 11736 +0 93 +cob=(7) +cfi=(53) +cfn=(1468) +calls=31 0 +0 217 +0 62 +cob=(7) +cfi=(53) +cfn=(1468) +calls=31 0 +0 465 +0 62 +cob=(7) +cfi=(53) +cfn=(1468) +calls=31 0 +0 217 +0 293 + +fn=(3352) std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::_M_insert_unique(std::pair const&) +0 7917692983 +cfn=(3354) std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::_M_insert_(std::_Rb_tree_node_base const*, std::_Rb_tree_node_base const*, std::pair const&) +calls=344247521 0 +0 68599248650 +0 1376990084 + +fn=(3476) BTS::Fibre::Base::Reader >::read_triple() +0 3286 +cob=(7) +cfi=(53) +cfn=(3482) +calls=106 0 +0 18995 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1434 +0 106 + +fn=(3496) +0 110644288 +cob=(7) +cfi=(53) +cfn=(880) +calls=3457634 0 +0 383389196 +0 383797374 +cfn=(3498) BTS::Fibre::Tract::init() +calls=3457634 0 +0 4269168660 +0 27661072 + +fn=(3498) +0 4798733310 +cob=(7) +cfi=(53) +cfn=(934) +calls=342766665 0 +0 78498284610 +0 4113199980 +cob=(7) +cfi=(53) +cfn=(1468) +calls=342766665 0 +0 5141499975 +0 2056599990 +cob=(7) +cfi=(53) +cfn=(934) +calls=342766665 0 +0 78841112460 +0 3427666650 +cob=(7) +cfi=(53) +cfn=(2438) +calls=342766665 0 +0 5827033305 +0 2742133320 +cob=(7) +cfi=(53) +cfn=(2438) +calls=342766665 0 +0 5827033305 +0 2056599990 +cob=(7) +cfi=(53) +cfn=(1468) +calls=342766665 0 +0 5141499975 +0 4455966645 +cob=(7) +cfi=(53) +cfn=(1258) +calls=342766665 0 +0 6855333300 +0 1713833325 +cfn=(3350) +calls=342766665 0 +0 85356028383 +0 1028299995 +cob=(7) +cfi=(53) +cfn=(1468) +calls=342766665 0 +0 5141499975 +0 1713833325 +cob=(7) +cfi=(53) +cfn=(1258) +calls=342766665 0 +0 6855333300 +0 1713833325 +cfn=(3350) +calls=342766665 0 +0 84829101904 +0 1028299995 +cob=(7) +cfi=(53) +cfn=(1468) +calls=342766665 0 +0 5141499975 +0 1028299995 + +fn=(3528) +0 58 + +fn=(3560) unsigned int BTS::Fibre::Properties::Intrinsic::num_intrinsic_keys() +0 114 +cob=(7) +cfi=(53) +cfn=(934) +calls=2 0 +0 468 +0 6 +cfn=(3348) +calls=2 0 +0 636 +0 8 +cob=(7) +cfi=(53) +cfn=(1468) +calls=2 0 +0 30 +0 12 +cfn=(2642) +calls=2 0 +0 22 +0 14 +cob=(7) +cfi=(53) +cfn=(2846) +calls=2 0 +0 36 +0 12 +cfn=(3562) +calls=2 0 +0 622 +0 14 + +fn=(3636) +0 9 +cfn=(3638) double BTS::Prob::Likelihood::ImageDiff::log_prob_tpl(BTS::Fibre::Tract::Set const&, BTS::Fibre::Tract::Set&, BTS::Fibre::Tract::Set::Tensor&) +calls=9 0 +0 7351890667180 + +fn=(3640) BTS::Image::Expected::Quartic::Buffer::expected_image(BTS::Fibre::Tract::Set const&, std::vector, std::allocator > >&, std::vector, std::allocator > >&) +0 36 +cfn=(3642) +calls=9 0 +0 7332305457810 +0 24 + +fn=(3664) +0 612 +cfn=(3666) +calls=34 0 +0 556470739 +0 216240606 +cfn=(3706) +calls=42413666 0 +0 67219402856 +0 222497920 +cfn=(3710) BTS::Image::Expected::Buffer_tpl::get_neighbourhood(BTS::Triple) +calls=695306 0 +0 184953441 +0 10429590 +cfn=(3768) std::_Rb_tree, std::less, std::allocator >::_M_copy(std::_Rb_tree_node const*, std::_Rb_tree_node*) +calls=695306 0 +0 773754894 +0 15893525 +cfn=(3864) +calls=685080 0 +0 10276200 +0 1370292 +cob=(7) +cfi=(53) +cfn=(1174) +calls=33 0 +0 440749 +0 507843779 +cfn=(3770) BTS::Image::Buffer_tpl >::operator()(BTS::Image::Coord const&) +calls=3029 0 +0 102704407 +0 15186772 +cfn=(3504) +calls=365 0 +0 714648 +0 191260 +cfn=(3788) std::vector >::operator=(std::vector > const&) +calls=22265 0 +0 18772000 +0 270465 +cfn=(3508) +calls=365 0 +0 291270 +0 16687332 +cfn=(3770) +calls=5562444 0 +0 697946372 +0 451867726 +cfn=(3504) +calls=3029 0 +0 5931593 +0 12116 +cfn=(3504) +calls=3029 0 +0 6008317 +0 15145 +cfn=(3792) BTS::Fibre::BasicStrand::Tensor_tpl::Tensor_tpl(int, BTS::Fibre::Tract const&) +calls=3029 0 +0 196513459 +0 15145 +cfn=(3796) T.6673 +calls=3029 0 +0 407795773 +0 6058 +cfn=(3798) BTS::Fibre::BasicStrand::Tensor_tpl::~Tensor_tpl() +calls=3029 0 +0 22254116 +0 6058 +cfn=(3800) +calls=3029 0 +0 3601481 +0 9087 +cfn=(3808) BTS::Image::Buffer_tpl >::operator()(BTS::Image::Coord const&) +calls=3029 0 +0 287234438 +0 409029733 +cfn=(3834) std::vector, std::allocator > >::operator=(std::vector, std::allocator > > const&) +calls=22265 0 +0 3305129638 +0 66795 +cfn=(3788) +calls=22265 0 +0 14984345 +0 155855 +cfn=(3788) +calls=22265 0 +0 14984345 +0 293095 +cfn=(3816) +calls=365 0 +0 8824455 +0 6058 +cfn=(3816) +calls=3029 0 +0 73133983 +0 16687332 +cfn=(3808) +calls=5562444 0 +0 697946372 +0 61186884 +cfn=(3840) BTS::Image::Expected::Quartic::Voxel::interpolate(BTS::Fibre::Strand::Section const&, BTS::Fibre::Strand::Section&, BTS::Fibre::Strand::Section::Tensor&) +calls=5562444 0 +0 3231779964 +0 77874216 +cfn=(3644) +calls=5562444 0 +0 44499552 +0 1357236124 +cfn=(3644) +calls=339309031 0 +0 2714472248 +0 19012430678 +cfn=(3850) BTS::Coord::Tensor_tpl::Tensor_tpl() +calls=339309032 0 +0 55307372216 +0 1017927096 +cfn=(3850) +calls=339309032 0 +0 55307372216 +0 31895049008 +cfn=(3852) BTS::Image::Expected::Direction::signal_hessian(BTS::Fibre::Strand::Section const&, BTS::Fibre::Strand::Section::Tensor&, double, double, BTS::Triple const&, BTS::Fibre::Strand::Section const&, BTS::Coord::Tensor const&, BTS::Fibre::Strand::Section::Tensor const&) +calls=339309032 0 +0 132330522480 +0 7804107736 +cfn=(3854) BTS::Fibre::Tract::add_section_gradient(BTS::Fibre::Tract::Section const&, BTS::Fibre::Tract::Section const&) +calls=339309032 0 +0 1293446127936 +0 39359847596 +cob=(7) +cfi=(53) +cfn=(880) +calls=339309031 0 +0 37323993410 +0 11197198023 +cob=(7) +cfi=(53) +cfn=(880) +calls=339309031 0 +0 37323993410 +0 21715777984 +cob=(7) +cfi=(53) +cfn=(880) +calls=1017927093 0 +0 111971982614 +0 52932208836 +cob=(7) +cfi=(53) +cfn=(1174) +calls=339309031 0 +0 27484031511 +0 678618062 +cfn=(3498) +calls=339309031 0 +0 401063391652 +0 1357236124 +cfn=(3854) +calls=339309031 0 +0 1293446133280 +0 4750326434 +cfn=(3856) +calls=339309031 0 +0 29519885697 +0 3393090310 +cfn=(3856) +calls=678618062 0 +0 59039771394 +0 3192219363648 +cfn=(3508) +calls=339309031 0 +0 270768606738 +0 2035854186 +cfn=(3762) BTS::Fibre::Strand::Section::~Section() +calls=339309031 0 +0 5089635465 +0 1357236124 +cfn=(3762) +calls=339309031 0 +0 5089635465 +0 1357236124 +cfn=(3762) +calls=339309031 0 +0 5089635465 +0 1357236124 +cfn=(3762) +calls=339309031 0 +0 5089635465 +0 1357236124 +cfn=(3762) +calls=339309031 0 +0 5089635465 +0 1357236124 +cfn=(3762) +calls=339309031 0 +0 5089635465 +0 1017927093 +cfn=(3762) +calls=339309031 0 +0 5089635465 +0 7475923579 +cob=(7) +cfi=(53) +cfn=(2846) +calls=5562443 0 +0 80389007 +0 11126346 +cfn=(3814) +calls=365 0 +0 51268704 +0 232281554 +cfn=(3726) +calls=695305 0 +0 572616360 +0 236292125 + +fn=(3686) std::_Rb_tree >, std::_Select1st > >, std::less, std::allocator > > >::_M_insert_(std::_Rb_tree_node_base const*, std::_Rb_tree_node_base const*, std::pair > const&) +0 30 +cob=(7) +cfi=(53) +cfn=(880) +calls=2 0 +0 361 +0 24 +cfn=(3626) +calls=2 0 +0 44 +0 16 +cob=(7) +cfi=(53) +cfn=(2426) +calls=2 0 +0 60 +0 26 + +fn=(3708) +0 65731413384 + +fn=(3748) +0 68256 +cob=(7) +cfi=(53) +cfn=(880) +calls=3318 0 +0 2949889 +0 397686 +cob=(7) +cfi=(53) +cfn=(1174) +calls=2844 0 +0 268364 +0 67782 + +fn=(3770) +0 441769042 +cfn=(3772) +calls=365 0 +0 48811694 +0 261162590 +cfn=(3774) BTS::Image::Container::Voxel::Voxel(BTS::Image::Container::Voxel const&) +calls=365 0 +0 16425 +0 1460 +cfn=(3776) std::_Rb_tree >, std::_Select1st > >, std::less, std::allocator > > >::_M_insert_unique_(std::_Rb_tree_const_iterator > >, std::pair > const&) +calls=365 0 +0 136842 +0 1095 +cfn=(3782) BTS::Image::Container::Voxel::~Voxel() +calls=365 0 +0 6570 +0 730 +cfn=(3782) +calls=365 0 +0 6570 +0 1095 +cfn=(3784) std::vector >::operator=(std::vector > const&) +calls=365 0 +0 40851985 +0 2190 +cfn=(3782) +calls=365 0 +0 12448002 +0 2169 + +fn=(3776) +0 6497 +cob=(7) +cfi=(53) +cfn=(2834) +calls=297 0 +0 4822 +0 2430 +cfn=(3780) std::_Rb_tree >, std::_Select1st > >, std::less, std::allocator > > >::_M_insert_(std::_Rb_tree_node_base const*, std::_Rb_tree_node_base const*, std::pair > const&) +calls=189 0 +0 58794 +0 3178 +cfn=(3778) std::_Rb_tree >, std::_Select1st > >, std::less, std::allocator > > >::_M_insert_unique(std::pair > const&) +calls=4 0 +0 1352 +0 272 +cfn=(3780) +calls=20 0 +0 6066 +0 2716 +cfn=(3780) +calls=152 0 +0 50507 +0 208 + +fn=(3788) +0 48572240 +cfn=(3790) std::vector, std::allocator > >::operator=(std::vector, std::allocator > > const&) +calls=1214306 0 +0 316358015 +0 12143060 +cfn=(3790) +calls=2428612 0 +0 633154078 +0 31571956 + +fn=(3822) std::_Rb_tree >, std::_Select1st > >, std::less, std::allocator > > >::_M_insert_unique_(std::_Rb_tree_const_iterator > >, std::pair > const&) +0 6497 +cob=(7) +cfi=(53) +cfn=(2834) +calls=297 0 +0 4822 +0 2430 +cfn=(3826) +calls=189 0 +0 59987 +0 3178 +cfn=(3824) +calls=4 0 +0 1262 +0 272 +cfn=(3826) +calls=20 0 +0 6597 +0 2716 +cfn=(3826) +calls=152 0 +0 51180 +0 208 + +fn=(3854) +0 57682535355 +cfn=(3500) +calls=2035854189 0 +0 515749840362 +0 10857889008 +cfn=(3856) +calls=678618063 0 +0 59039771481 +0 16286833512 +cob=(7) +cfi=(53) +cfn=(880) +calls=678618063 0 +0 74647987042 +0 78041077245 +cfn=(3856) +calls=678618063 0 +0 59039771481 +0 4071708378 +cob=(7) +cfi=(53) +cfn=(1174) +calls=678618063 0 +0 54968063103 +0 16286833512 +cob=(7) +cfi=(53) +cfn=(880) +calls=678618063 0 +0 74647986930 +0 78041077245 +cfn=(3856) +calls=678618063 0 +0 59039771481 +0 4071708378 +cob=(7) +cfi=(53) +cfn=(1174) +calls=678618063 0 +0 54968063103 +0 55646681166 +cfn=(3500) +calls=2035854189 0 +0 515749820523 +0 10857889008 +cfn=(3856) +calls=678618063 0 +0 59039771481 +0 16286833512 +cob=(7) +cfi=(53) +cfn=(880) +calls=678618063 0 +0 74647986930 +0 78041077245 +cfn=(3856) +calls=678618063 0 +0 59039771481 +0 4071708378 +cob=(7) +cfi=(53) +cfn=(1174) +calls=678618063 0 +0 54968063103 +0 6107562567 +cfn=(3858) +calls=678618063 0 +0 131651904222 +0 39359847654 +cfn=(3856) +calls=678618063 0 +0 59039771481 +0 4071708378 +cob=(7) +cfi=(53) +cfn=(1174) +calls=678618063 0 +0 54968063103 +0 10857889007 +cob=(7) +cfi=(53) +cfn=(1174) +calls=678618062 0 +0 54968063022 +0 4071708372 +cob=(7) +cfi=(53) +cfn=(1174) +calls=678618062 0 +0 54968063022 +0 21037159945 + +fn=(3884) BTS::Prob::Likelihood::ImageDiff::Gaussian::log_prob(double, double&, double&) +0 92232 + +fn=(2512) +0 2879 +cob=(9) +cfi=(58) +cfn=(2506) +calls=2 0 +0 753 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 947 +0 10 + +fn=(1060) +0 6 + +fn=(1100) global constructors keyed to peaks.cpp +0 5 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 330 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 313 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 317 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 7 + +fn=(1110) global constructors keyed to flatness.cpp +0 6 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 330 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 313 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 317 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 8 + +fn=(1118) global constructors keyed to midpoint_in_sphere.cpp +0 6 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 330 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 313 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 317 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 318 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 8 + +fn=(1128) global constructors keyed to voxel.cpp +0 5 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 330 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 313 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 317 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 9 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 330 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 313 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 317 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 12 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 330 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 313 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 582 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 340 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 9 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 330 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 313 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 317 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 12 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 407 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 330 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 313 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 317 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 12 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 330 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 313 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 317 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 7 + +fn=(1130) global constructors keyed to base_width.cpp +0 6 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 407 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 330 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 313 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 317 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 315 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 8 + +fn=(1136) global constructors keyed to spread.cpp +0 6 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 330 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 313 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 317 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 308 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 8 + +fn=(1144) global constructors keyed to log.cpp +0 6 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 407 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 330 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 313 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 317 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 323 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 5 + +fn=(1220) global constructors keyed to KMcenters.cpp +0 7 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 6 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 407 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 330 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 313 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 317 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 + +fn=(1432) MR::OptBase* std::__uninitialized_copy_a(MR::OptBase*, MR::OptBase*, MR::OptBase*, std::allocator&) +0 230 +cob=(7) +cfi=(53) +cfn=(880) +calls=3 0 +0 585 +0 227 + +fn=(1600) +0 40 + +fn=(2330) +0 90 +cob=(7) +cfi=(53) +cfn=(880) +calls=3 0 +0 362 +0 45 +cob=(4) +cfi=(90) +cfn=(1282) +calls=3 47 +0 146 +0 24 +cob=(4) +cfi=(90) +cfn=(1282) +calls=3 47 +0 72 +0 11 +cob=(7) +cfi=(53) +cfn=(1174) +calls=2 0 +0 162 +0 44 + +fn=(2410) +0 40533099 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1200609 0 +0 120060390 +0 2348480 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1174240 0 +0 117422948 +0 25776210 +cob=(7) +cfi=(53) +cfn=(1174) +calls=1200609 0 +0 97249329 +0 13663200 + +fn=(2416) +0 1000 +cob=(7) +cfi=(53) +cfn=(2834) +calls=6 0 +0 107 +0 156 +cfn=(2420) std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::_M_insert_(std::_Rb_tree_node_base const*, std::_Rb_tree_node_base const*, std::pair const&) +calls=6 0 +0 3563 +0 605 +cfn=(2418) std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::_M_insert_unique(std::pair const&) +calls=15 0 +0 6005 +0 211 +cob=(7) +cfi=(53) +cfn=(2438) +calls=49 0 +0 939 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1532 +0 343 +cfn=(2420) +calls=49 0 +0 16767 +0 54 +cfn=(2420) +calls=1 0 +0 292 +0 1 + +fn=(2642) +0 1016327 +cfn=(2643) std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::_M_erase(std::_Rb_tree_node >*)'2 +calls=15 0 +0 4575 +0 21 +cfn=(2643) +calls=7 0 +0 349 +0 66 +cob=(7) +cfi=(53) +cfn=(1468) +calls=22 0 +0 670 +0 44 +cob=(7) +cfi=(53) +cfn=(1468) +calls=22 0 +0 500 +0 66 +cob=(7) +cfi=(53) +cfn=(1174) +calls=22 0 +0 1782 +0 580768 + +fn=(2643) +0 466 +cfn=(2643) +calls=22 0 +0 4892 +0 30 +cfn=(2643) +calls=10 0 +0 654 +0 96 +cob=(7) +cfi=(53) +cfn=(1468) +calls=32 0 +0 650 +0 64 +cob=(7) +cfi=(53) +cfn=(1468) +calls=32 0 +0 650 +0 96 +cob=(7) +cfi=(53) +cfn=(1174) +calls=32 0 +0 2592 +0 280 + +fn=(2806) BTS::Image::Buffer_tpl::operator()(BTS::Image::Coord const&) +0 1275068 +cfn=(2808) +calls=27 0 +0 12974 +0 587449 +cfn=(2814) +calls=27 0 +0 2106 +0 108 +cfn=(2816) +calls=27 0 +0 15479 +0 81 +cfn=(2822) +calls=27 0 +0 189 +0 54 +cfn=(2822) +calls=27 0 +0 189 +0 81 +cfn=(2824) +calls=27 0 +0 12676 +0 486 +cfn=(2822) +calls=27 0 +0 3224 +0 102 + +fn=(2812) BTS::Image::Observed::Buffer::num_encodings() const +0 108 + +fn=(2882) +0 20 +cfn=(2884) +calls=1 0 +0 2912 +0 14 +cfn=(2886) +calls=1 0 +0 109382 +0 420 +cfn=(2886) +calls=60 0 +0 6200940 +0 2806 +cob=(9) +cfi=(58) +cfn=(2654) +calls=61 0 +0 10065 +0 369 +cfn=(2998) BTS::Diffusion::Model::init(MR::Math::Matrix const&, MR::Math::Matrix const&, bool) +calls=1 0 +0 709349 +0 4 +cob=(9) +cfi=(58) +cfn=(2654) +calls=1 0 +0 226 +0 8 + +fn=(3024) +0 48 +cob=(7) +cfi=(53) +cfn=(880) +calls=1 0 +0 1534 +0 921 +cfn=(2888) +calls=61 0 +0 24679 +0 5342 + +fn=(3030) BTS::Image::Expected::Buffer_tpl::Buffer_tpl(BTS::Triple const&, BTS::Triple const&, BTS::Diffusion::Model const&, unsigned int, unsigned int, double, BTS::Triple const&, bool) +0 56 +cfn=(3032) +calls=1 0 +0 34449 +0 16 +cob=(6) +cfi=(129) /build/buildd/eglibc-2.11.1/math/../sysdeps/ieee754/dbl-64/s_ceil.c +cfn=(3038) ceil +calls=1 44 +0 24 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1398 +0 5 +cfn=(3040) std::_Rb_tree, std::allocator > >, std::_Select1st, std::allocator > > >, std::less, std::allocator, std::allocator > > > >::_M_erase(std::_Rb_tree_node, std::allocator > > >*) +calls=1 0 +0 11 +0 33 + +fn=(3076) +0 46 +cfn=(3078) std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::_M_copy(std::_Rb_tree_node > const*, std::_Rb_tree_node >*) +calls=2 0 +0 37145 +0 176 +cob=(7) +cfi=(53) +cfn=(880) +calls=2 0 +0 717 +0 1748 + +fn=(3078) +0 24 +cob=(7) +cfi=(53) +cfn=(880) +calls=2 0 +0 439 +0 52 +cob=(7) +cfi=(53) +cfn=(880) +calls=2 0 +0 436 +0 26 +cob=(4) +cfi=(90) +cfn=(1282) +calls=2 47 +0 430 +0 54 +cfn=(3079) std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::_M_copy(std::_Rb_tree_node > const*, std::_Rb_tree_node >*)'2 +calls=2 0 +0 23552 +0 16 +cob=(7) +cfi=(53) +cfn=(880) +calls=2 0 +0 390 +0 8 +cob=(7) +cfi=(53) +cfn=(880) +calls=4 0 +0 780 +0 156 +cob=(7) +cfi=(53) +cfn=(880) +calls=6 0 +0 1080 +0 78 +cob=(4) +cfi=(90) +cfn=(1282) +calls=6 47 +0 1290 +0 172 +cfn=(3079) +calls=4 0 +0 8116 +0 46 + +fn=(3079) +0 408 +cob=(7) +cfi=(53) +cfn=(880) +calls=34 0 +0 6890 +0 884 +cob=(7) +cfi=(53) +cfn=(880) +calls=34 0 +0 6300 +0 442 +cob=(4) +cfi=(90) +cfn=(1282) +calls=34 47 +0 7310 +0 846 +cfn=(3079) +calls=16 0 +0 30712 +0 158 +cob=(7) +cfi=(53) +cfn=(880) +calls=10 0 +0 2102 +0 4 +cob=(7) +cfi=(53) +cfn=(880) +calls=2 0 +0 390 +0 312 +cob=(7) +cfi=(53) +cfn=(880) +calls=12 0 +0 2160 +0 156 +cob=(4) +cfi=(90) +cfn=(1282) +calls=12 47 +0 2580 +0 360 +cfn=(3079) +calls=12 0 +0 13524 +0 366 + +fn=(3114) +0 4 +cob=(7) +cfi=(53) +cfn=(880) +calls=1 0 +0 110 +0 11 + +fn=(3118) +0 4 +cob=(7) +cfi=(53) +cfn=(880) +calls=1 0 +0 195 +0 11 + +fn=(3268) +0 475020 + +fn=(3470) +0 26 +cfn=(2642) +calls=2 0 +0 22 +0 16 +cfn=(3472) BTS::Fibre::Base::Reader >::next_basic(BTS::Fibre::Set&) +calls=2 0 +0 104228 +0 52 +cob=(7) +cfi=(53) +cfn=(1730) +calls=2 0 +0 878 +0 18 +cfn=(3512) +calls=2 0 +0 6437 +0 30 +cfn=(3272) +calls=2 0 +0 758 +0 6 +cob=(7) +cfi=(53) +cfn=(1264) +calls=2 0 +0 56 +0 20 +cfn=(2410) +calls=2 0 +0 234 +0 4 +cob=(7) +cfi=(53) +cfn=(1468) +calls=2 0 +0 200 +0 8 +cfn=(3514) BTS::Fibre::Properties::Intrinsic::set_intrinsic_properties(BTS::Fibre::Properties&) +calls=2 0 +0 9239 +0 18 + +fn=(3510) +0 3779375061 +cfn=(3511) std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::_M_erase(std::_Rb_tree_node >*)'2 +calls=343579551 0 +0 3779375061 +0 1030501245 +cfn=(3511) +calls=343500415 0 +0 3778504565 +0 2061239898 +cob=(7) +cfi=(53) +cfn=(1468) +calls=687079966 0 +0 68506137325 +0 2061239898 +cob=(7) +cfi=(53) +cfn=(1174) +calls=687079966 0 +0 55653477246 +0 2748478136 + +fn=(3511) +0 7557879626 + +fn=(3620) +0 211192 +cfn=(3622) +calls=26399 0 +0 26249204 +0 422384 +cfn=(3566) unsigned int BTS::Fibre::Unzipper::size(BTS::Fibre::Tract const&) +calls=26399 0 +0 55692826 +0 475182 +cfn=(3566) +calls=79197 0 +0 167062986 +0 1029561 + +fn=(3658) +0 96 + +fn=(3660) +0 124 +cfn=(3868) +calls=3 0 +0 2156234931 +0 272 + +fn=(3698) +0 14 +cfn=(3626) +calls=1 0 +0 361 +0 215 +cob=(6) +cfi=(151) /build/buildd/eglibc-2.11.1/math/../sysdeps/ieee754/dbl-64/s_sin.c +cfn=(3704) sin +calls=2 90 +0 94 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1416 +0 290 +cob=(6) +cfi=(151) +cfn=(3704) +calls=58 90 +0 6746 +0 503 + +fn=(3718) std::map, std::allocator >, std::less, std::allocator, std::allocator > > > >::operator[](BTS::Image::Coord const&) +0 70237640 +cfn=(3720) std::_Rb_tree, std::allocator > >, std::_Select1st, std::allocator > > >, std::less, std::allocator, std::allocator > > > >::_M_insert_unique_(std::_Rb_tree_const_iterator, std::allocator > > >, std::pair, std::allocator > > const&) +calls=102 0 +0 29156 +0 408 +cfn=(3726) +calls=102 0 +0 1122 +0 306 +cfn=(3726) +calls=102 0 +0 1122 +0 2781974 + +fn=(3728) BTS::Image::Expected::Buffer_tpl::create_neighbourhood(BTS::Image::Coord const&) +0 14178 +cfn=(3730) BTS::Image::Buffer_tpl::operator()(BTS::Image::Coord const&) +calls=816 0 +0 5720740 +0 29328 +cob=(7) +cfi=(53) +cfn=(2840) +calls=132 0 +0 2162 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 2037 +0 4476 +cfn=(3766) std::_Rb_tree, std::less, std::allocator >::_M_insert_(std::_Rb_tree_node_base const*, std::_Rb_tree_node_base const*, BTS::Image::Expected::Quartic::Voxel* const&) +calls=816 0 +0 177920 +0 1734 + +fn=(3730) +0 1287779 +cfn=(3732) +calls=237 0 +0 3577593 +0 736529 +cfn=(3750) BTS::Image::Expected::Quartic::Voxel::Voxel() +calls=237 0 +0 101673 +0 1896 +cfn=(3752) +calls=237 0 +0 123714 +0 2133 +cfn=(3754) std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::_M_insert_unique_(std::_Rb_tree_const_iterator >, std::pair const&) +calls=237 0 +0 272081 +0 711 +cfn=(3760) BTS::Image::Expected::Quartic::Voxel::~Voxel() +calls=237 0 +0 37920 +0 474 +cfn=(3760) +calls=237 0 +0 37920 +0 948 +cfn=(3764) +calls=237 0 +0 1347292 +0 1185 +cfn=(3760) +calls=237 0 +0 95550 +0 1634 + +fn=(3752) +0 16590 +cob=(4) +cfi=(90) +cfn=(1282) +calls=474 47 +0 11376 +0 41712 +cfn=(3742) +calls=474 0 +0 171114 +0 6636 + +fn=(3754) +0 4339 +cob=(7) +cfi=(53) +cfn=(2834) +calls=208 0 +0 3317 +0 1500 +cfn=(3758) +calls=92 0 +0 103061 +0 2148 +cfn=(3756) +calls=1 0 +0 841 +0 41 +cfn=(3758) +calls=3 0 +0 2589 +0 2138 +cfn=(3758) +calls=141 0 +0 151959 +0 148 + +fn=(3760) +0 19197 +cfn=(3762) +calls=711 0 +0 10665 +0 2844 +cfn=(3762) +calls=711 0 +0 10665 +0 2133 +cfn=(3762) +calls=711 0 +0 10665 +0 2844 +cfn=(3762) +calls=711 0 +0 10665 +0 2844 +cfn=(3762) +calls=711 0 +0 10665 +0 2133 +cfn=(3762) +calls=711 0 +0 10665 +0 8769 +cob=(7) +cfi=(53) +cfn=(1174) +calls=237 0 +0 27642 +0 5925 +cob=(7) +cfi=(53) +cfn=(1174) +calls=237 0 +0 29751 +0 3318 + +fn=(3782) +0 13140 +cfn=(3508) +calls=365 0 +0 201480 +0 43800 +cfn=(3508) +calls=21900 0 +0 12088800 +0 71540 +cob=(7) +cfi=(53) +cfn=(1174) +calls=365 0 +0 39462 +0 2920 + +fn=(3796) +0 42406 +cob=(7) +cfi=(53) +cfn=(880) +calls=3029 0 +0 333190 +0 221117 +cob=(7) +cfi=(53) +cfn=(880) +calls=9087 0 +0 1883200 +0 245349 +cfn=(3794) BTS::Coord::Tensor_tpl::Tensor_tpl(BTS::Coord::Tensor_tpl const&) +calls=27261 0 +0 404828191 +0 242320 + +fn=(3800) +0 865634 +cob=(7) +cfi=(53) +cfn=(934) +calls=61831 0 +0 17314984 +0 741972 +cob=(7) +cfi=(53) +cfn=(1468) +calls=61831 0 +0 927465 +0 370986 +cob=(7) +cfi=(53) +cfn=(934) +calls=61831 0 +0 17379723 +0 618310 +cob=(7) +cfi=(53) +cfn=(2438) +calls=61831 0 +0 1051127 +0 494648 +cob=(7) +cfi=(53) +cfn=(2438) +calls=61831 0 +0 1051127 +0 370986 +cob=(7) +cfi=(53) +cfn=(1468) +calls=61831 0 +0 927465 +0 803803 +cob=(7) +cfi=(53) +cfn=(1258) +calls=61831 0 +0 1236620 +0 309155 +cfn=(3802) +calls=61831 0 +0 18869334 +0 185493 +cob=(7) +cfi=(53) +cfn=(1468) +calls=61831 0 +0 927465 +0 309155 +cob=(7) +cfi=(53) +cfn=(1258) +calls=61831 0 +0 1236620 +0 309155 +cfn=(3802) +calls=61831 0 +0 18607713 +0 185493 +cob=(7) +cfi=(53) +cfn=(1468) +calls=61831 0 +0 927465 +0 185493 + +fn=(3806) +0 1731268 +cob=(7) +cfi=(53) +cfn=(880) +calls=123662 0 +0 19978874 +0 741972 +cob=(7) +cfi=(53) +cfn=(1258) +calls=123662 0 +0 2473240 +0 865634 +cob=(7) +cfi=(53) +cfn=(2426) +calls=123662 0 +0 4019015 +0 1298451 + +fn=(3834) +0 1068720 +cfn=(3836) +calls=22265 0 +0 1106458720 +0 222650 +cfn=(3836) +calls=44530 0 +0 2196800658 +0 578890 + +fn=(3838) +0 1870260 +cfn=(3794) +calls=200385 0 +0 3284188860 +0 1536285 + +fn=(3842) BTS::Image::Expected::Quartic::Voxel::interpolate(BTS::Triple const&, BTS::Triple&, BTS::Coord::Tensor&) +0 800991936 + +fn=(3852) +0 40377774808 +cfn=(3708) +calls=339309032 0 +0 13233052248 +0 1696545160 +cfn=(3708) +calls=339309032 0 +0 13233052248 +0 32234358040 +cfn=(3708) +calls=339309032 0 +0 13233052248 +0 18322687728 + +fn=(3866) +0 36 +cob=(7) +cfi=(53) +cfn=(880) +calls=3 0 +0 460 +0 81 +cob=(7) +cfi=(53) +cfn=(880) +calls=3 0 +0 24348 +0 954 +cfn=(3504) +calls=183 0 +0 451590 +0 978 +cfn=(3867) std::_Rb_tree >, std::_Select1st > >, std::less, std::allocator > > >::_M_copy(std::_Rb_tree_node > > const*, std::_Rb_tree_node > >*)'2 +calls=3 0 +0 13786107 +0 30 +cob=(7) +cfi=(53) +cfn=(880) +calls=3 0 +0 531 +0 32 +cob=(7) +cfi=(53) +cfn=(880) +calls=16 0 +0 2850 +0 589 +cob=(7) +cfi=(53) +cfn=(880) +calls=19 0 +0 6001 +0 6023 +cfn=(3504) +calls=1159 0 +0 2901997 +0 6121 +cfn=(3867) +calls=15 0 +0 16846921 +0 118 + +fn=(3867) +0 1320 +cob=(7) +cfi=(53) +cfn=(880) +calls=110 0 +0 19255 +0 2970 +cob=(7) +cfi=(53) +cfn=(880) +calls=110 0 +0 36187 +0 34980 +cfn=(3504) +calls=6710 0 +0 16728867 +0 35632 +cfn=(3867) +calls=53 0 +0 32834478 +0 706 +cob=(7) +cfi=(53) +cfn=(880) +calls=54 0 +0 9504 +0 72 +cob=(7) +cfi=(53) +cfn=(880) +calls=36 0 +0 6345 +0 2790 +cob=(7) +cfi=(53) +cfn=(880) +calls=90 0 +0 29799 +0 28530 +cfn=(3504) +calls=5490 0 +0 13665816 +0 28866 +cfn=(3867) +calls=39 0 +0 12392259 +0 1389 + +fn=(3882) BTS::Image::Expected::Quartic::Buffer::operator()(int, int, int) +0 92232 +cfn=(3730) +calls=13176 0 +0 1906292 +0 26352 + +fn=(3886) BTS::Fibre::Flattener::flatten(BTS::Fibre::Tract::Tensor const&) +0 427488 +cfn=(3888) +calls=35624 0 +0 77380915 +0 142496 +cfn=(3626) +calls=35624 0 +0 114420732 +0 178120 +cfn=(3890) +calls=35624 0 +0 605004744 +0 2600552 +cfn=(3916) BTS::Fibre::Flattener::flatten_element(BTS::Fibre::Tract const&, MR::Math::Matrix&, unsigned int&) +calls=106872 0 +0 717752158 +0 1709952 +cfn=(3916) +calls=213744 0 +0 1429143519 +0 1282464 +cfn=(3916) +calls=320616 0 +0 2145988465 +0 1282464 +cfn=(3916) +calls=320616 0 +0 2142340546 +0 4061136 + +fn=(3900) void std::__unguarded_linear_insert<__gnu_cxx::__normal_iterator > >, std::string>(__gnu_cxx::__normal_iterator > >, std::string) +0 34052380 +cob=(7) +cfi=(53) +cfn=(1264) +calls=1174220 0 +0 12916420 +0 2348440 + +fn=(3908) void BTS::Fibre::Unzipper::unzip_intrinsic(BTS::Fibre::Tract const&, MR::Math::Vector&, unsigned int&) +0 13662768 +cfn=(3892) +calls=1138564 0 +0 2931371495 +0 18217024 +cfn=(3894) +calls=1138564 0 +0 23909844 +0 3415692 +cfn=(3896) +calls=1138564 0 +0 211772904 +0 15939896 +cfn=(3910) BTS::Fibre::Properties::Intrinsic_tpl::intrinsic_property(std::string const&) const +calls=1138564 0 +0 128657732 +0 11385640 +cfn=(3910) +calls=1138564 0 +0 125242040 +0 13662768 +cfn=(2410) +calls=1138564 0 +0 349539148 +0 9108512 + +fn=(3950) +0 288 +cfn=(3952) +calls=32 0 +0 106688 +0 480 +cfn=(3954) void BTS::Fibre::Unzipper::zip_element(MR::Math::Vector const&, BTS::Fibre::BasicStrand&, unsigned int&) +calls=32 0 +0 3904 +0 448 +cfn=(3954) +calls=64 0 +0 7808 +0 768 + +fn=(1054) +0 6 + +fn=(1066) +0 11 +cfn=(1070) +calls=1 0 +0 8523 +0 156 +cfn=(1132) global constructors keyed to strand.cpp +calls=1 0 +0 2835 +cfn=(1116) +calls=1 0 +0 3572 +cfn=(1112) global constructors keyed to set.cpp +calls=1 0 +0 3616 +cfn=(1222) global constructors keyed to KCtree.cpp +calls=1 0 +0 2453 +cfn=(1128) +calls=1 0 +0 2832 +cfn=(1220) +calls=1 0 +0 2706 +cfn=(1112) +calls=1 0 +0 2832 +cfn=(1092) global constructors keyed to sheer.cpp +calls=1 0 +0 3223 +cfn=(1096) +calls=1 0 +0 94 +cfn=(1106) +calls=1 0 +0 3221 +cfn=(1124) global constructors keyed to tract.cpp +calls=1 0 +0 3180 +cfn=(1218) +calls=1 0 +0 94 +cfn=(1216) +calls=1 0 +0 3220 +cfn=(1214) +calls=1 0 +0 3233 +cfn=(1112) +calls=1 0 +0 3970 +cfn=(1212) +calls=1 0 +0 3221 +cfn=(1210) +calls=1 0 +0 2361 +cfn=(1208) global constructors keyed to KMfilterCenters.cpp +calls=1 0 +0 2361 +cfn=(1206) global constructors keyed to roi.cpp +calls=1 0 +0 94 +cfn=(1106) +calls=1 0 +0 2832 +cfn=(1204) +calls=1 0 +0 3177 +cfn=(1202) global constructors keyed to extended.cpp +calls=1 0 +0 521 +cfn=(1200) +calls=1 0 +0 2361 +cfn=(1106) +calls=1 0 +0 3216 +cfn=(1184) +calls=1 0 +0 3177 +cfn=(1198) global constructors keyed to uniform.cpp +calls=1 0 +0 3227 +cfn=(1196) global constructors keyed to KM_ANN.cpp +calls=1 0 +0 2361 +cfn=(1128) +calls=1 0 +0 2835 +cfn=(1194) global constructors keyed to curvature.cpp +calls=1 0 +0 3557 +cfn=(1192) +calls=1 0 +0 2453 +cfn=(1184) +calls=1 0 +0 477 +cfn=(1190) +calls=1 0 +0 2361 +cfn=(1188) +calls=1 0 +0 909 +cfn=(1106) +calls=1 0 +0 3260 +cfn=(1186) +calls=1 0 +0 513 +cfn=(1184) +calls=1 0 +0 94 +cfn=(1128) +calls=1 0 +0 3375 +cfn=(1106) +calls=1 0 +0 3137 +cfn=(1184) +calls=1 0 +0 477 +cfn=(1154) +calls=1 0 +0 49976 +cfn=(1152) +calls=1 0 +0 2361 +cfn=(1150) +calls=1 0 +0 530 +cfn=(1148) +calls=1 0 +0 480 +cfn=(1146) global constructors keyed to peak.cpp +calls=1 0 +0 2835 +cfn=(1128) +calls=1 0 +0 2835 +cfn=(1144) +calls=1 0 +0 3573 +cfn=(1142) global constructors keyed to width.cpp +calls=1 0 +0 3219 +cfn=(1140) +calls=1 0 +0 2832 +cfn=(1134) +calls=1 0 +0 2835 +cfn=(1128) +calls=1 0 +0 3180 +cfn=(1138) global constructors keyed to likelihood.cpp +calls=1 0 +0 3047 +cfn=(1136) +calls=1 0 +0 3216 +cfn=(1126) +calls=1 0 +0 3576 +cfn=(1134) +calls=1 0 +0 2832 +cfn=(1132) +calls=1 0 +0 4580 +cfn=(1130) +calls=1 0 +0 3568 +cfn=(1128) +calls=1 0 +0 2835 +cfn=(1126) +calls=1 0 +0 3225 +cfn=(1124) +calls=1 0 +0 3221 +cfn=(1122) global constructors keyed to image_diff.cpp +calls=1 0 +0 3180 +cfn=(1120) global constructors keyed to track.cpp +calls=1 0 +0 4366 +cfn=(1094) global constructors keyed to file.cpp +calls=1 0 +0 477 +cfn=(1118) +calls=1 0 +0 3226 +cfn=(1116) +calls=1 0 +0 3572 +cfn=(1114) global constructors keyed to dummy_intrinsic_properties.cpp +calls=1 0 +0 94 +cfn=(1112) +calls=1 0 +0 3236 +cfn=(1110) +calls=1 0 +0 3217 +cfn=(1108) +calls=1 0 +0 526 +cfn=(1106) +calls=1 0 +0 3572 +cfn=(1104) global constructors keyed to base_intensity.cpp +calls=1 0 +0 2832 +cfn=(1102) global constructors keyed to KMterm.cpp +calls=1 0 +0 2361 +cfn=(1100) +calls=1 0 +0 2835 +cfn=(1098) global constructors keyed to gaussian_intensity.cpp +calls=1 0 +0 3222 +cfn=(1096) +calls=1 0 +0 3177 +cfn=(1094) +calls=1 0 +0 94 +cfn=(1092) +calls=1 0 +0 3227 +cfn=(1090) global constructors keyed to properties.cpp +calls=1 0 +0 94 +cfn=(1088) global constructors keyed to basic_strand.cpp +calls=1 0 +0 2839 +0 241 + +fn=(1090) +0 3 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 + +fn=(1112) +0 6 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 330 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 313 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 317 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 315 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 16 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 330 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 313 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 317 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 10 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 407 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 330 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 313 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 317 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 318 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 33 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 330 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 313 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 317 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 27 + +fn=(1114) +0 3 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 + +fn=(1122) +0 5 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 407 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 330 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 313 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 317 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 7 + +fn=(1124) +0 5 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 407 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 330 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 313 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 317 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 13 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 330 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 313 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 317 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 12 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 5 + +fn=(1132) +0 5 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 330 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 313 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 317 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 13 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 330 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 313 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 317 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 318 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 314 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 304 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 11 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 10 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 10 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 5 + +fn=(1160) std::vector >::_M_insert_aux(__gnu_cxx::__normal_iterator > >, MR::Argument const&) +0 1555 +cob=(7) +cfi=(53) +cfn=(880) +calls=74 0 +0 8984 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1299 +0 3359 +cob=(7) +cfi=(53) +cfn=(1174) +calls=25 0 +0 2056 +0 1432 + +fn=(1194) +0 6 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 407 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 330 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 313 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 317 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 304 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 8 + +fn=(1198) +0 6 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 330 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 313 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 317 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 8 + +fn=(1208) +0 7 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 6 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 330 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 313 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 317 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 + +fn=(2648) std::vector >::_M_insert_aux(__gnu_cxx::__normal_iterator > >, BTS::Diffusion::Encoding const&) +0 144 +cob=(7) +cfi=(53) +cfn=(880) +calls=7 0 +0 2186 +0 1119 +cob=(7) +cfi=(53) +cfn=(1174) +calls=6 0 +0 636 +0 143 + +fn=(3028) +0 14 +cfn=(3030) +calls=1 0 +0 35992 +0 7 +cfn=(3042) +calls=1 0 +0 1757 +0 4 + +fn=(3096) +0 13176 +cfn=(3098) +calls=3294 0 +0 13176 + +fn=(3250) BTS::Prob::Test::Peaks::Peak::Peak(BTS::Prob::Test::Peaks::Peak const&) +0 36 +cfn=(2888) +calls=4 0 +0 1474 +0 156 +cfn=(2888) +calls=4 0 +0 1485 +0 176 + +fn=(3340) T.4663 +0 3220 +cob=(7) +cfi=(53) +cfn=(722) +calls=322 0 +0 31234 +0 7084 +cob=(7) +cfi=(53) +cfn=(728) +calls=322 0 +0 227976 +0 3220 +cob=(7) +cfi=(53) +cfn=(728) +calls=322 0 +0 227976 +0 7406 +cob=(7) +cfi=(53) +cfn=(492) +calls=322 0 +0 12558 +0 3220 +cob=(7) +cfi=(53) +cfn=(728) +calls=322 0 +0 227976 +0 2254 + +fn=(3350) +0 17209289590 +cfn=(3354) +calls=344168381 0 +0 69431255513 +0 6195901398 +cfn=(3352) +calls=344247521 0 +0 77893931717 +0 344247521 + +fn=(3446) +0 148 +cob=(7) +cfi=(53) +cfn=(3452) +calls=4 0 +0 3912 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1434 +0 12 +cob=(4) +cfi=(98) +cfn=(3460) +calls=4 90 +0 368 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1701 +0 52 + +fn=(3472) +0 34 +cfn=(3508) +calls=1 0 +0 798 +0 9 +cfn=(3508) +calls=3 0 +0 2394 +0 16 +cfn=(2642) +calls=2 0 +0 22 +0 46 +cfn=(3474) +calls=2 0 +0 22 +0 20 +cfn=(3476) +calls=2 0 +0 3437 +0 18 +cfn=(3494) void BTS::Fibre::Base::Reader >::read >(BTS::Fibre::Set&, BTS::Triple const&) +calls=2 0 +0 97396 +0 16 + +fn=(3502) std::vector >::_M_insert_aux(__gnu_cxx::__normal_iterator > >, BTS::Fibre::Tract const&) +0 108 +cob=(7) +cfi=(53) +cfn=(880) +calls=3 0 +0 484 +0 27 +cfn=(3504) +calls=3 0 +0 6976 +0 18 +cfn=(3506) BTS::Fibre::Tract* std::__uninitialized_move_a >(BTS::Fibre::Tract*, BTS::Fibre::Tract*, BTS::Fibre::Tract*, std::allocator&) +calls=3 0 +0 7915 +0 18 +cfn=(3506) +calls=3 0 +0 51 +0 121 +cob=(7) +cfi=(53) +cfn=(1174) +calls=9 0 +0 729 +0 48 +cob=(7) +cfi=(53) +cfn=(1174) +calls=3 0 +0 243 +0 12 +cfn=(3510) +calls=3 0 +0 1254 +0 19 +cob=(7) +cfi=(53) +cfn=(1174) +calls=2 0 +0 193 +0 54 + +fn=(3516) double BTS::to(std::string const&) +0 198 +cob=(7) +cfi=(53) +cfn=(722) +calls=18 0 +0 1746 +0 396 +cob=(7) +cfi=(53) +cfn=(728) +calls=18 0 +0 12744 +0 288 +cob=(7) +cfi=(53) +cfn=(492) +calls=18 0 +0 702 +0 162 +cob=(7) +cfi=(53) +cfn=(1812) +calls=18 0 +0 3292 +0 108 +cob=(7) +cfi=(53) +cfn=(1528) +calls=18 0 +0 378 +0 54 +cob=(7) +cfi=(53) +cfn=(728) +calls=18 0 +0 12744 +0 54 +cob=(7) +cfi=(53) +cfn=(1822) +calls=18 0 +0 24308 +0 180 +cob=(7) +cfi=(53) +cfn=(1468) +calls=18 0 +0 1800 +0 90 +cob=(7) +cfi=(53) +cfn=(746) +calls=18 0 +0 216 +0 162 +cob=(7) +cfi=(53) +cfn=(1556) +calls=18 0 +0 1044 +0 162 + +fn=(3526) __gnu_cxx::__normal_iterator > > std::__find<__gnu_cxx::__normal_iterator > >, std::string>(__gnu_cxx::__normal_iterator > >, __gnu_cxx::__normal_iterator > >, std::string const&, std::random_access_iterator_tag) +0 296 + +fn=(3532) +0 202 +cob=(7) +cfi=(53) +cfn=(1446) +calls=2 0 +0 402 +0 34 +cob=(7) +cfi=(53) +cfn=(1468) +calls=2 0 +0 200 +0 22 +cob=(7) +cfi=(53) +cfn=(1446) +calls=2 0 +0 402 +0 24 +cob=(7) +cfi=(53) +cfn=(1468) +calls=2 0 +0 200 +0 2 + +fn=(3534) +0 48 +cfn=(3514) +calls=8 0 +0 64629 +0 16 +cfn=(3542) BTS::Fibre::Tract::normalize_base_width() +calls=8 0 +0 920 +0 40 + +fn=(3564) +0 633088 +cob=(7) +cfi=(53) +cfn=(1468) +calls=79136 0 +0 553952 +0 237408 +cfn=(3474) +calls=79136 0 +0 870496 +0 2136672 + +fn=(3638) +0 162 +cfn=(3640) +calls=9 0 +0 7332305457870 +0 80 +cfn=(2642) +calls=8 0 +0 88 +0 160 +cfn=(3784) +calls=8 0 +0 10632 +0 40 +cfn=(2402) +calls=8 0 +0 376 +0 40 +cfn=(2402) +calls=8 0 +0 376 +0 40 +cfn=(3870) +calls=8 0 +0 432 +0 80 +cfn=(3474) +calls=8 0 +0 88 +0 160 +cob=(7) +cfi=(53) +cfn=(934) +calls=8 0 +0 3392 +0 32 +cfn=(3348) +calls=8 0 +0 816 +0 40 +cob=(7) +cfi=(53) +cfn=(1468) +calls=8 0 +0 800 +0 16 +cfn=(3620) +calls=8 0 +0 87803 +0 24 +cfn=(3620) +calls=8 0 +0 76056 +0 32 +cfn=(3626) +calls=8 0 +0 27643 +0 774136 +cfn=(3634) +calls=8 0 +0 120 +0 1214072 +cob=(9) +cfi=(58) +cfn=(2654) +calls=8 0 +0 1728 +0 776944 +cfn=(3620) +calls=8 0 +0 76696 +0 280 +cfn=(3566) +calls=8 0 +0 16864 +0 144 +cfn=(3566) +calls=24 0 +0 50592 +0 656 +cfn=(3872) std::vector >::_M_insert_aux(__gnu_cxx::__normal_iterator > >, unsigned int const&) +calls=24 0 +0 8584 +0 96 +cfn=(3872) +calls=24 0 +0 8584 +0 184 +cfn=(3880) BTS::Image::Expected::Quartic::Buffer::dim(unsigned int) const +calls=8 0 +0 24 +0 120 +cfn=(3880) +calls=24 0 +0 72 +0 232 +cfn=(3880) +calls=24 0 +0 72 +0 360 +cfn=(3880) +calls=72 0 +0 216 +0 624 +cfn=(3880) +calls=72 0 +0 216 +0 1080 +cfn=(3880) +calls=216 0 +0 648 +0 1656 +cfn=(3646) BTS::Image::Expected::Quartic::Buffer::num_encodings() const +calls=216 0 +0 1296 +0 52704 +cfn=(3646) +calls=13176 0 +0 79056 +0 119016 +cfn=(3882) +calls=13176 0 +0 2024876 +0 184464 +cfn=(2806) +calls=13176 0 +0 1654320 +0 131760 +cfn=(3884) +calls=13176 0 +0 92232 +0 487512 +cfn=(3496) +calls=13176 0 +0 19013048 +0 118584 +cob=(7) +cfi=(53) +cfn=(880) +calls=13176 0 +0 21421547 +0 355752 +cfn=(3504) +calls=52704 0 +0 82777401 +0 263520 +cfn=(3508) +calls=13176 0 +0 7273152 +0 329400 +cob=(7) +cfi=(53) +cfn=(934) +calls=13176 0 +0 3083184 +0 210816 +cob=(7) +cfi=(53) +cfn=(1468) +calls=13176 0 +0 197640 +0 79056 +cfn=(2642) +calls=13176 0 +0 144936 +0 52704 +cfn=(3626) +calls=13176 0 +0 24141283 +0 1279072888 +cfn=(3770) +calls=35624 0 +0 4567680 +0 356240 +cfn=(3788) +calls=35624 0 +0 24373160 +0 926224 +cfn=(3808) +calls=35624 0 +0 4567680 +0 178120 +cfn=(3886) +calls=35624 0 +0 7243715751 +0 646439448 +cob=(9) +cfi=(58) +cfn=(2654) +calls=35624 0 +0 7775060 +0 527040 +cfn=(3918) +calls=13176 0 +0 351561512 +0 52704 +cfn=(3918) +calls=13176 0 +0 351249732 +0 52704 +cfn=(3924) +calls=13176 0 +0 1705653505 +0 52704 +cob=(9) +cfi=(58) +cfn=(2654) +calls=13176 0 +0 2671434 +0 52704 +cob=(9) +cfi=(58) +cfn=(2654) +calls=13176 0 +0 2630259 +0 7429195368 +cfn=(3630) +calls=13176 0 +0 141020430 +0 33374808 +cfn=(3562) +calls=13176 0 +0 47828880 +0 52704 +cob=(9) +cfi=(58) +cfn=(2654) +calls=13176 0 +0 19384092 +0 52704 +cob=(9) +cfi=(58) +cfn=(2654) +calls=13176 0 +0 4611600 +0 26352 +cfn=(3562) +calls=13176 0 +0 47833346 +0 813496 +cob=(7) +cfi=(53) +cfn=(880) +calls=17080 0 +0 1956880 +0 546560 +cob=(7) +cfi=(53) +cfn=(880) +calls=17080 0 +0 1956880 +0 1093120 +cob=(7) +cfi=(53) +cfn=(880) +calls=51240 0 +0 5870640 +0 2664480 +cob=(7) +cfi=(53) +cfn=(1174) +calls=17080 0 +0 1383480 +0 85400 +cob=(7) +cfi=(53) +cfn=(934) +calls=17080 0 +0 3989400 +0 170800 +cob=(7) +cfi=(53) +cfn=(1258) +calls=17080 0 +0 341600 +0 102480 +cfn=(3350) +calls=17080 0 +0 4341011 +0 51240 +cob=(7) +cfi=(53) +cfn=(1468) +calls=17080 0 +0 256200 +0 85400 +cob=(7) +cfi=(53) +cfn=(1468) +calls=17080 0 +0 256200 +0 85400 +cob=(7) +cfi=(53) +cfn=(934) +calls=17080 0 +0 4006480 +0 802760 +cob=(7) +cfi=(53) +cfn=(1258) +calls=17080 0 +0 341600 +0 102480 +cfn=(3350) +calls=17080 0 +0 5116743 +0 51240 +cob=(7) +cfi=(53) +cfn=(1468) +calls=17080 0 +0 256200 +0 85400 +cob=(7) +cfi=(53) +cfn=(1468) +calls=17080 0 +0 256200 +0 102480 +cfn=(3788) +calls=17080 0 +0 11729032 +0 102480 +cfn=(3508) +calls=17080 0 +0 13629840 +0 189344 +cob=(7) +cfi=(53) +cfn=(1258) +calls=13176 0 +0 263520 +0 79056 +cfn=(3350) +calls=13176 0 +0 3280824 +0 39528 +cob=(7) +cfi=(53) +cfn=(1468) +calls=13176 0 +0 197640 +0 1233296 +cob=(7) +cfi=(53) +cfn=(1174) +calls=8 0 +0 648 +0 48 +cob=(7) +cfi=(53) +cfn=(1174) +calls=8 0 +0 648 +0 656 + +fn=(3648) +0 71 +cob=(7) +cfi=(53) +cfn=(880) +calls=3 0 +0 5357 +0 27 +cfn=(3650) BTS::Image::Container::Buffer::Buffer(BTS::Image::Container::Buffer const&) +calls=3 0 +0 96 +0 18 +cfn=(3652) +calls=3 0 +0 34036112 +0 18 +cfn=(3652) +calls=3 0 +0 51 +0 32 +cfn=(3654) +calls=2 0 +0 6889807 +0 4 +cfn=(3654) +calls=1 0 +0 4035535 +0 19 +cob=(7) +cfi=(53) +cfn=(1174) +calls=2 0 +0 187 +0 84 + +fn=(3684) +0 50 +cfn=(3686) +calls=2 0 +0 561 +0 4 + +fn=(3738) BTS::Image::Expected::Voxel::Voxel(BTS::Image::Expected::Buffer&, BTS::Image::Coord const&, BTS::Diffusion::Model&) +0 4503 +cfn=(3740) +calls=237 0 +0 179819 +0 12798 +cfn=(3742) +calls=237 0 +0 85557 +0 379437 +cfn=(3748) +calls=1659 0 +0 2903155 +0 6873 + +fn=(3746) T.6667 +0 12215227536 + +fn=(3762) +0 35627512245 + +fn=(3780) +0 4959 +cob=(7) +cfi=(53) +cfn=(880) +calls=193 0 +0 33561 +0 344 +cob=(7) +cfi=(53) +cfn=(880) +calls=172 0 +0 29663 +0 14965 +cob=(7) +cfi=(53) +cfn=(2426) +calls=365 0 +0 26518 +0 6605 + +fn=(3786) BTS::Fibre::Tract* std::__uninitialized_copy_a<__gnu_cxx::__normal_iterator > >, BTS::Fibre::Tract*, BTS::Fibre::Tract>(__gnu_cxx::__normal_iterator > >, __gnu_cxx::__normal_iterator > >, BTS::Fibre::Tract*, std::allocator&) +0 116070 +cfn=(3504) +calls=22265 0 +0 40325441 +0 114245 + +fn=(3792) +0 42406 +cfn=(3496) +calls=3029 0 +0 4380909 +0 9087 +cfn=(3496) +calls=3029 0 +0 4384347 +0 9087 +cfn=(3496) +calls=3029 0 +0 4384373 +0 257465 +cfn=(3504) +calls=3029 0 +0 6019061 +0 12116 +cfn=(3504) +calls=3029 0 +0 6018791 +0 12116 +cfn=(3504) +calls=3029 0 +0 6018613 +0 12116 +cfn=(3504) +calls=3029 0 +0 6018886 +0 9087 +cfn=(3788) +calls=3029 0 +0 2116035 +0 21203 +cfn=(3788) +calls=3029 0 +0 2116362 +0 21203 +cfn=(3788) +calls=3029 0 +0 2116134 +0 18174 +cfn=(3508) +calls=3029 0 +0 2417142 +0 6058 +cfn=(3508) +calls=3029 0 +0 2417142 +0 6058 +cfn=(3508) +calls=3029 0 +0 2417142 +0 6058 +cfn=(3508) +calls=3029 0 +0 2417142 +0 39377 +cob=(7) +cfi=(53) +cfn=(880) +calls=3029 0 +0 440695 +0 69667 +cfn=(3794) +calls=9087 0 +0 134943169 +0 48464 +cfn=(3508) +calls=3029 0 +0 2417142 +0 6058 +cfn=(3508) +calls=3029 0 +0 2417142 +0 6058 +cfn=(3508) +calls=3029 0 +0 2417142 +0 24232 + +fn=(3794) +0 3618960 +cfn=(3496) +calls=361896 0 +0 526879892 +0 1447584 +cfn=(3496) +calls=361896 0 +0 527946230 +0 1085688 +cfn=(3496) +calls=361896 0 +0 528016716 +0 34018224 +cfn=(3504) +calls=361896 0 +0 824452297 +0 1447584 +cfn=(3504) +calls=361896 0 +0 831323124 +0 1085688 +cfn=(3504) +calls=361896 0 +0 831332524 +0 1085688 +cfn=(3788) +calls=361896 0 +0 316745848 +0 2533272 +cfn=(3788) +calls=361896 0 +0 316922246 +0 2533272 +cfn=(3788) +calls=361896 0 +0 316930114 +0 2171376 +cfn=(3508) +calls=361896 0 +0 288793008 +0 723792 +cfn=(3508) +calls=361896 0 +0 288793008 +0 723792 +cfn=(3508) +calls=361896 0 +0 288793008 +0 2533272 + +fn=(3804) +0 1669437 +cfn=(3806) +calls=61831 0 +0 15468629 +0 309155 + +fn=(3808) +0 441769042 +cfn=(3810) +calls=365 0 +0 127348439 +0 261162590 +cfn=(3820) +calls=365 0 +0 16425 +0 1460 +cfn=(3822) +calls=365 0 +0 139149 +0 1095 +cfn=(3828) BTS::Image::Container::Voxel::~Voxel() +calls=365 0 +0 6570 +0 730 +cfn=(3828) +calls=365 0 +0 6570 +0 1095 +cfn=(3830) +calls=365 0 +0 122062025 +0 2190 +cfn=(3828) +calls=365 0 +0 37228941 +0 2169 + +fn=(3814) +0 1285614 +cfn=(3504) +calls=58437 0 +0 108483110 +0 350622 +cfn=(3504) +calls=58437 0 +0 108539565 +0 1110303 +cob=(7) +cfi=(53) +cfn=(880) +calls=58437 0 +0 9581418 +0 3798267 +cob=(7) +cfi=(53) +cfn=(880) +calls=41721 0 +0 7623486 +0 2328777 +cfn=(3794) +calls=125163 0 +0 2117975987 +0 2028303 +cfn=(3800) +calls=58437 0 +0 82171925 +0 467496 + +fn=(3828) +0 13140 +cfn=(3816) +calls=365 0 +0 607725 +0 43800 +cfn=(3816) +calls=21900 0 +0 36463500 +0 71540 +cob=(7) +cfi=(53) +cfn=(1174) +calls=365 0 +0 39456 +0 2920 + +fn=(3832) +0 116070 +cfn=(3814) +calls=22265 0 +0 121369804 +0 114245 + +fn=(3840) +0 333746640 +cfn=(3842) +calls=5562444 0 +0 800991936 +0 27812220 +cfn=(3844) +calls=5562444 0 +0 344871528 +0 66749328 +cfn=(3846) +calls=5562444 0 +0 16687332 +0 11124888 +cfn=(3846) +calls=5562444 0 +0 16687332 +0 133498656 +cfn=(3848) +calls=5562444 0 +0 394933524 +0 11124888 +cfn=(3848) +calls=5562444 0 +0 394933524 +0 61186884 +cfn=(3846) +calls=5562444 0 +0 16687332 +0 11124888 +cfn=(3846) +calls=5562444 0 +0 16687332 +0 572931732 + +fn=(3872) +0 1200 +cfn=(3874) std::vector >::_M_check_len(unsigned long, char const*) const +calls=48 0 +0 864 +0 240 +cfn=(3876) std::_Vector_base >::_M_allocate(unsigned long) +calls=48 0 +0 5968 +0 576 +cfn=(3878) unsigned int* std::__uninitialized_move_a >(unsigned int*, unsigned int*, unsigned int*, std::allocator&) +calls=48 0 +0 3104 +0 240 +cfn=(3878) +calls=48 0 +0 1920 +0 224 +cob=(7) +cfi=(53) +cfn=(1174) +calls=32 0 +0 2592 +0 240 + +fn=(3896) +0 12005950 +cfn=(3898) void std::__insertion_sort<__gnu_cxx::__normal_iterator > > >(__gnu_cxx::__normal_iterator > >, __gnu_cxx::__normal_iterator > >) +calls=1200595 0 +0 201371870 +0 6002975 + +fn=(3902) +0 7944152 + +fn=(3912) void BTS::Fibre::Unzipper::unzip_element(BTS::Fibre::BasicStrand const&, MR::Math::Vector&, unsigned int&) +0 40988304 +cfn=(3914) std::vector > BTS::Fibre::Properties::Intrinsic_tpl::intrinsic_keys() +calls=3415692 0 +0 17078460 +0 20494152 +cfn=(2410) +calls=3415692 0 +0 51235380 +0 286918128 + +fn=(3948) +0 7936 + +fn=(3956) +0 22752 + +fn=(1138) +0 5 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 330 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 313 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 317 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 38 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 49 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 7 + +fn=(1168) +0 196 +cob=(7) +cfi=(53) +cfn=(1174) +calls=49 0 +0 6065 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1307 + +fn=(2000) +0 13 +cob=(11) +cfi=(60) +cfn=(2006) +calls=1 0 +0 1866987 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1072 +0 15 +cfn=(2644) MR::Math::Matrix::Matrix(MR::Math::Matrix const&) +calls=1 0 +0 5775 +0 4 +cfn=(2646) BTS::Diffusion::Encoding::Set::set(MR::Math::Matrix const&) +calls=1 0 +0 7411 +0 4 +cob=(9) +cfi=(58) +cfn=(2654) +calls=1 0 +0 209 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 877 +0 22 +cfn=(2644) +calls=1 0 +0 680 +0 24 +cfn=(2656) std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::_M_erase(std::_Rb_tree_node >*) +calls=1 0 +0 15 +0 29 +cfn=(2658) std::vector >::operator=(std::vector > const&) +calls=1 0 +0 1265 +0 4 +cfn=(2660) +calls=1 0 +0 55410 +0 15 +cob=(4) +cfi=(121) +cfn=(2802) +calls=1 29 +0 12 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1795 +0 21494 +cfn=(2806) +calls=1647 0 +0 255946 +0 23058 +cfn=(2826) +calls=1647 0 +0 4941 +0 44469 +cfn=(2828) +calls=549 0 +0 25297 +0 8241 +cfn=(2416) +calls=1 0 +0 289 +0 60 +cfn=(2416) +calls=15 0 +0 6514 +0 32 +cob=(7) +cfi=(53) +cfn=(2846) +calls=16 0 +0 1491 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1971 +0 50 +cfn=(2854) MR::ProgressBar::~ProgressBar() +calls=1 0 +0 16 +0 4 +cob=(7) +cfi=(53) +cfn=(1174) +calls=1 0 +0 81 +0 4 +cob=(9) +cfi=(58) +cfn=(2654) +calls=1 0 +0 196 +0 4 +cob=(7) +cfi=(53) +cfn=(1174) +calls=1 0 +0 114 +0 2 +cfn=(2634) +calls=1 0 +0 9403 +0 7694 + +fn=(2418) +0 345 +cfn=(2420) +calls=15 0 +0 5600 +0 60 + +fn=(2646) +0 3147 +cfn=(2648) +calls=7 0 +0 4228 +0 36 + +fn=(3002) BTS::Diffusion::Response* std::__uninitialized_copy_a(BTS::Diffusion::Response*, BTS::Diffusion::Response*, BTS::Diffusion::Response*, std::allocator&) +0 1131 +cfn=(2888) +calls=63 0 +0 24641 +0 5412 + +fn=(3070) +0 40 +cob=(7) +cfi=(53) +cfn=(1446) +calls=1 0 +0 262 +0 8 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 100 +0 11 +cob=(7) +cfi=(53) +cfn=(1446) +calls=1 0 +0 206 +0 7 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 100 +0 13 + +fn=(3084) +0 100 +cfn=(3032) +calls=2 0 +0 60778 +0 28 +cob=(6) +cfi=(129) +cfn=(3038) +calls=2 44 +0 48 +0 10 +cfn=(3040) +calls=2 0 +0 22 +0 20 + +fn=(3256) +0 300 +cfn=(2642) +calls=50 0 +0 550 +0 300 +cob=(9) +cfi=(58) +cfn=(2654) +calls=50 0 +0 8250 + +fn=(3354) +0 9637822628 +cob=(7) +cfi=(53) +cfn=(880) +calls=688415902 0 +0 76073152123 +0 4130495412 +cob=(7) +cfi=(53) +cfn=(1258) +calls=688415902 0 +0 13768318040 +0 4818911314 +cob=(7) +cfi=(53) +cfn=(2426) +calls=688415902 0 +0 22373318965 +0 7228485681 + +fn=(3370) MR::DWI::Tractography::Reader::open(std::string const&, MR::DWI::Tractography::Properties&) +0 32 +cfn=(2642) +calls=2 0 +0 22 +0 30 +cfn=(3372) +calls=2 0 +0 42 +0 4 +cfn=(3372) +calls=2 0 +0 42 +0 4 +cfn=(3372) +calls=2 0 +0 42 +0 22 +cfn=(2642) +calls=2 0 +0 22 +0 30 +cob=(7) +cfi=(53) +cfn=(722) +calls=2 0 +0 194 +0 44 +cob=(7) +cfi=(53) +cfn=(728) +calls=2 0 +0 1416 +0 14 +cob=(7) +cfi=(53) +cfn=(1608) +calls=2 0 +0 530 +0 6 +cob=(7) +cfi=(53) +cfn=(728) +calls=2 0 +0 1416 +0 8 +cob=(11) +cfi=(60) +cfn=(2204) +calls=2 0 +0 6395 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1096 +0 58 +cob=(11) +cfi=(60) +cfn=(2238) +calls=2 0 +0 6357 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 992 +0 32 +cob=(11) +cfi=(60) +cfn=(2238) +calls=16 0 +0 49390 +0 148 +cob=(7) +cfi=(53) +cfn=(2256) +calls=16 0 +0 4046 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1516 +0 96 +cob=(7) +cfi=(53) +cfn=(1372) +calls=16 0 +0 192 +0 192 +cob=(4) +cfi=(118) +cfn=(2270) +calls=16 47 +0 192 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1724 +0 360 +cob=(4) +cfi=(118) +cfn=(2270) +calls=120 47 +0 1440 +0 624 +cob=(7) +cfi=(53) +cfn=(1594) +calls=16 0 +0 704 +0 192 +cob=(7) +cfi=(53) +cfn=(1310) +calls=16 0 +0 1312 +0 80 +cob=(7) +cfi=(53) +cfn=(1594) +calls=16 0 +0 808 +0 96 +cob=(7) +cfi=(53) +cfn=(1594) +calls=16 0 +0 822 +0 40 +cob=(7) +cfi=(53) +cfn=(1264) +calls=2 0 +0 56 +0 58 +cob=(7) +cfi=(53) +cfn=(1594) +calls=14 0 +0 652 +0 766 +cob=(7) +cfi=(53) +cfn=(1264) +calls=12 0 +0 716 +0 20 +cob=(11) +cfi=(60) +cfn=(2482) +calls=2 0 +0 2951 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 984 +0 42 +cob=(7) +cfi=(53) +cfn=(1258) +calls=8 0 +0 1695 +0 24 +cob=(7) +cfi=(53) +cfn=(1258) +calls=8 0 +0 120 +0 32 +cfn=(2416) +calls=8 0 +0 2503 +0 24 +cob=(7) +cfi=(53) +cfn=(1468) +calls=8 0 +0 56 +0 16 +cob=(7) +cfi=(53) +cfn=(1468) +calls=8 0 +0 120 +0 64 +cob=(7) +cfi=(53) +cfn=(722) +calls=2 0 +0 194 +0 44 +cob=(7) +cfi=(53) +cfn=(728) +calls=2 0 +0 1416 +0 32 +cob=(7) +cfi=(53) +cfn=(492) +calls=2 0 +0 78 +0 18 +cob=(7) +cfi=(53) +cfn=(1812) +calls=2 0 +0 392 +0 12 +cob=(7) +cfi=(53) +cfn=(1528) +calls=2 0 +0 42 +0 6 +cob=(7) +cfi=(53) +cfn=(728) +calls=2 0 +0 1416 +0 12 +cob=(7) +cfi=(53) +cfn=(2532) +calls=2 0 +0 1114 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 2395 +0 12 +cob=(7) +cfi=(53) +cfn=(2308) +calls=2 0 +0 1000 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1664 +0 6 +cob=(7) +cfi=(53) +cfn=(1594) +calls=2 0 +0 104 +0 10 +cob=(7) +cfi=(53) +cfn=(1264) +calls=2 0 +0 246 +0 10 +cob=(7) +cfi=(53) +cfn=(1632) +calls=2 0 +0 3101 +0 16 +cob=(7) +cfi=(53) +cfn=(1712) +calls=2 0 +0 16 +0 18 +cob=(7) +cfi=(53) +cfn=(3412) +calls=2 0 +0 4806 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1754 +0 26 +cob=(7) +cfi=(53) +cfn=(1468) +calls=2 0 +0 200 +0 10 +cob=(7) +cfi=(53) +cfn=(746) +calls=2 0 +0 24 +0 22 +cob=(7) +cfi=(53) +cfn=(1556) +calls=2 0 +0 116 +0 12 +cfn=(2576) +calls=2 0 +0 1803 +0 36 +cob=(7) +cfi=(53) +cfn=(1310) +calls=2 0 +0 164 +0 96 + +fn=(3436) +0 3984 +cob=(7) +cfi=(53) +cfn=(1258) +calls=664 0 +0 13240 +0 1328 +cob=(4) +cfi=(69) +cfn=(642) +calls=664 26 +0 14380 +0 2656 +cob=(7) +cfi=(53) +cfn=(1772) +calls=664 0 +0 205450 +0 3320 + +fn=(3438) +0 32 +cob=(4) +cfi=(95) +cfn=(1350) +calls=4 37 +0 40 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1738 +0 48 + +fn=(3474) +0 870628 + +fn=(3514) +0 3100 +cfn=(3516) +calls=18 0 +0 60828 +0 72 +cfn=(3518) std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::erase(std::string const&) +calls=18 0 +0 7459 +0 36 +cob=(7) +cfi=(53) +cfn=(2852) +calls=18 0 +0 258 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1971 +0 144 + +fn=(3530) +0 66 + +fn=(3556) +0 168 +cob=(7) +cfi=(53) +cfn=(1258) +calls=12 0 +0 240 +0 60 +cob=(7) +cfi=(53) +cfn=(1468) +calls=12 0 +0 180 +0 8 +cob=(7) +cfi=(53) +cfn=(1468) +calls=4 0 +0 60 +0 32 +cob=(7) +cfi=(53) +cfn=(1468) +calls=16 0 +0 1600 +0 32 +cob=(7) +cfi=(53) +cfn=(2846) +calls=16 0 +0 240 +0 112 +cfn=(1396) +calls=16 0 +0 5157 +0 64 +cfn=(3436) +calls=16 0 +0 5475 +0 88 +cfn=(2390) +calls=4 0 +0 1790 +0 148 +cfn=(3338) +calls=8 0 +0 27974 +0 48 +cfn=(3338) +calls=16 0 +0 55370 +0 96 +cfn=(3436) +calls=24 0 +0 8239 +0 96 +cfn=(1396) +calls=24 0 +0 7217 +0 96 +cfn=(3436) +calls=24 0 +0 7656 +0 432 +cfn=(3338) +calls=24 0 +0 83159 +0 144 +cfn=(3338) +calls=48 0 +0 166065 +0 288 +cfn=(3436) +calls=72 0 +0 24849 +0 288 +cfn=(1396) +calls=72 0 +0 21717 +0 288 +cfn=(3436) +calls=72 0 +0 23168 +0 504 +cfn=(3558) void BTS::Fibre::Unzipper::header_element(BTS::Triple const&, BTS::Fibre::Properties::Header&, std::string const&) +calls=72 0 +0 1077095 +0 144 +cob=(7) +cfi=(53) +cfn=(1468) +calls=72 0 +0 7200 +0 144 +cob=(7) +cfi=(53) +cfn=(1468) +calls=72 0 +0 7200 +0 144 +cob=(7) +cfi=(53) +cfn=(1468) +calls=72 0 +0 7200 +0 144 +cob=(7) +cfi=(53) +cfn=(1468) +calls=72 0 +0 7200 +0 768 +cob=(7) +cfi=(53) +cfn=(1468) +calls=24 0 +0 2400 +0 48 +cob=(7) +cfi=(53) +cfn=(1468) +calls=24 0 +0 2400 +0 48 +cob=(7) +cfi=(53) +cfn=(1468) +calls=24 0 +0 2400 +0 48 +cob=(7) +cfi=(53) +cfn=(1468) +calls=24 0 +0 2400 +0 192 + +fn=(3634) +0 135 + +fn=(3646) +0 2069309610 + +fn=(3650) +0 96 + +fn=(3668) +0 1292 +cob=(7) +cfi=(53) +cfn=(880) +calls=34 0 +0 131697326 +0 204 +cfn=(3670) BTS::Fibre::Tract::Section* std::__uninitialized_copy_a(BTS::Fibre::Tract::Section*, BTS::Fibre::Tract::Section*, BTS::Fibre::Tract::Section*, std::allocator&) +calls=34 0 +0 136 +0 646 + +fn=(3676) +0 26 +cob=(7) +cfi=(53) +cfn=(880) +calls=2 0 +0 525 +0 38 +cob=(7) +cfi=(53) +cfn=(2426) +calls=2 0 +0 60 +0 22 + +fn=(3688) +0 20 +cfn=(3626) +calls=1 0 +0 332 +0 271 +cob=(6) +cfi=(151) +cfn=(3694) cos +calls=2 348 +0 152 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1382 +0 232 +cob=(6) +cfi=(151) +cfn=(3694) +calls=58 348 +0 6225 +0 677 + +fn=(3696) +0 2244 +cob=(9) +cfi=(58) +cfn=(1916) +calls=2 0 +0 596 +0 10 + +fn=(3710) +0 8343672 +cob=(6) +cfi=(152) /build/buildd/eglibc-2.11.1/math/../sysdeps/ieee754/dbl-64/s_floor.c +cfn=(3716) floor +calls=695306 44 +0 25089827 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1422 +0 3476530 +cob=(6) +cfi=(152) +cfn=(3716) +calls=695306 44 +0 25321240 +0 4171836 +cob=(6) +cfi=(152) +cfn=(3716) +calls=695306 44 +0 25349212 +0 6257754 +cfn=(3718) +calls=695306 0 +0 73041204 +0 7648876 +cfn=(3728) +calls=102 0 +0 5952575 +0 306 +cfn=(3718) +calls=102 0 +0 10524 +0 612 +cfn=(3726) +calls=102 0 +0 1122 +0 1122 +cfn=(3768) +calls=102 0 +0 197854 +0 3642 +cfn=(3726) +calls=102 0 +0 84009 +0 102 + +fn=(3720) +0 1827 +cob=(7) +cfi=(53) +cfn=(2834) +calls=76 0 +0 1272 +0 645 +cfn=(3724) std::_Rb_tree, std::allocator > >, std::_Select1st, std::allocator > > >, std::less, std::allocator, std::allocator > > > >::_M_insert_(std::_Rb_tree_node_base const*, std::_Rb_tree_node_base const*, std::pair, std::allocator > > const&) +calls=53 0 +0 11955 +0 899 +cfn=(3722) std::_Rb_tree, std::allocator > >, std::_Select1st, std::allocator > > >, std::less, std::allocator, std::allocator > > > >::_M_insert_unique(std::pair, std::allocator > > const&) +calls=1 0 +0 371 +0 763 +cfn=(3724) +calls=48 0 +0 11376 +0 48 + +fn=(3766) +0 10914 +cob=(7) +cfi=(53) +cfn=(880) +calls=102 0 +0 12154 +0 1428 +cob=(7) +cfi=(53) +cfn=(880) +calls=714 0 +0 89686 +0 8160 +cob=(7) +cfi=(53) +cfn=(2426) +calls=816 0 +0 42216 +0 13362 + +fn=(3768) +0 6954080 +cob=(7) +cfi=(53) +cfn=(880) +calls=695408 0 +0 76505560 +0 11126528 +cfn=(3769) std::_Rb_tree, std::less, std::allocator >::_M_copy(std::_Rb_tree_node const*, std::_Rb_tree_node*)'2 +calls=695408 0 +0 283187071 +0 5563264 +cob=(7) +cfi=(53) +cfn=(880) +calls=695408 0 +0 76505493 +0 1928100 +cob=(7) +cfi=(53) +cfn=(880) +calls=964050 0 +0 106059684 +0 24987038 +cfn=(3769) +calls=853521 0 +0 168776721 +0 12359209 + +fn=(3769) +0 24666330 +cob=(7) +cfi=(53) +cfn=(880) +calls=2466633 0 +0 271370879 +0 32916464 +cfn=(3769) +calls=829217 0 +0 143877333 +0 10972872 +cob=(7) +cfi=(53) +cfn=(880) +calls=685939 0 +0 75464869 +0 111652 +cob=(7) +cfi=(53) +cfn=(880) +calls=55826 0 +0 6141855 +0 9996893 +cfn=(3769) +calls=88487 0 +0 12566827 +0 20321978 + +fn=(3774) +0 16425 + +fn=(3784) +0 10207 +cfn=(3788) +calls=8 0 +0 2432 +0 120 +cfn=(3788) +calls=24 0 +0 7296 +0 7367 +cob=(7) +cfi=(53) +cfn=(880) +calls=365 0 +0 272869 +0 2190 +cfn=(3786) +calls=365 0 +0 40555756 +0 4380 + +fn=(3790) +0 153005820 +cob=(7) +cfi=(53) +cfn=(880) +calls=3642822 0 +0 625293639 +0 171212634 + +fn=(3846) +0 266997312 + +fn=(3874) +0 864 + +fn=(3878) +0 1056 +cob=(4) +cfi=(90) +cfn=(1282) +calls=96 47 +0 3488 +0 480 + +fn=(3880) +0 1248 + +fn=(3906) void BTS::Fibre::Unzipper::unzip_element(BTS::Fibre::Tract const&, MR::Math::Vector&, unsigned int&) +0 10247076 +cfn=(3908) +calls=1138564 0 +0 3855885463 +0 17078460 +cfn=(3912) +calls=1138564 0 +0 138904808 +0 15939896 +cfn=(3912) +calls=2277128 0 +0 277809616 +0 27325536 + +fn=(3926) +0 12 +cob=(7) +cfi=(53) +cfn=(1258) +calls=1 0 +0 20 +0 8 +cob=(4) +cfi=(121) +cfn=(2802) +calls=1 29 +0 12 +0 29 +cob=(11) +cfi=(60) +cfn=(3928) +calls=1 0 +0 3668 +0 5 + +fn=(2854) +0 9 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 7 + +fn=(1040) +0 11 +cob=(4) +cfi=(85) +cfn=(1048) +calls=1 96 +0 7351905246676 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1850 + +fn=(1050) +0 15 +cob=(2) +cfi=(13) +cfn=(1052) +calls=1 0 +0 253290 +0 10 + +fn=(1088) +0 5 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 330 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 313 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 317 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 10 + +fn=(1094) +0 4 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 6 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 + +fn=(1098) +0 6 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 330 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 313 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 317 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 314 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 8 + +fn=(1104) +0 5 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 330 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 313 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 317 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 + +fn=(1142) +0 6 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 330 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 313 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 317 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 314 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 5 + +fn=(1196) +0 7 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 6 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 330 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 313 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 317 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 + +fn=(1206) +0 3 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 + +fn=(1234) +0 19 +cob=(11) +cfi=(60) +cfn=(1240) +calls=1 0 +0 68324 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1496 +0 5 +cob=(11) +cfi=(60) +cfn=(1412) +calls=1 0 +0 10641 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1024 +0 3 +cfn=(1434) +calls=1 0 +0 7351904911703 + +fn=(1430) +0 141 +cob=(7) +cfi=(53) +cfn=(880) +calls=7 0 +0 940 +0 126 +cob=(7) +cfi=(53) +cfn=(880) +calls=3 0 +0 346 +0 149 +cfn=(1432) +calls=3 0 +0 63 +0 36 +cfn=(1432) +calls=4 0 +0 832 +0 42 +cfn=(1432) +calls=7 0 +0 147 +0 56 +cob=(7) +cfi=(53) +cfn=(1174) +calls=3 0 +0 243 +0 27 +cob=(7) +cfi=(53) +cfn=(1174) +calls=2 0 +0 162 +0 159 + +fn=(2644) +0 3322 +cob=(9) +cfi=(58) +cfn=(1916) +calls=2 0 +0 3125 +0 8 + +fn=(2658) +0 31 +cob=(7) +cfi=(53) +cfn=(880) +calls=1 0 +0 362 +0 872 + +fn=(2818) +0 14 +cfn=(2820) +calls=1 0 +0 247 +0 12 + +fn=(2878) +0 7 + +fn=(2984) MR::Math::Vector::allocate(unsigned long) +0 2534 +cob=(9) +cfi=(58) +cfn=(2654) +calls=60 0 +0 9900 +0 300 +cob=(9) +cfi=(58) +cfn=(1916) +calls=60 0 +0 12720 +0 240 + +fn=(3000) std::vector >::_M_insert_aux(__gnu_cxx::__normal_iterator > >, BTS::Diffusion::Response const&) +0 427 +cfn=(2888) +calls=7 0 +0 2030 +0 586 +cfn=(3002) +calls=7 0 +0 31037 +0 49 +cfn=(3002) +calls=7 0 +0 147 +0 294 +cob=(9) +cfi=(58) +cfn=(2654) +calls=63 0 +0 10395 +0 215 +cob=(7) +cfi=(53) +cfn=(1174) +calls=6 0 +0 729 +0 73 +cob=(7) +cfi=(53) +cfn=(880) +calls=7 0 +0 5723 +0 52 + +fn=(3018) +0 5820 +cob=(7) +cfi=(53) +cfn=(880) +calls=240 0 +0 36813 +0 2640 +cfn=(3020) +calls=240 0 +0 53096 +0 1440 +cfn=(3022) std::vector >* std::__uninitialized_move_a >*, std::vector >*, std::allocator > > >(std::vector >*, std::vector >*, std::vector >*, std::allocator > >&) +calls=240 0 +0 102390 +0 1440 +cfn=(3022) +calls=240 0 +0 5040 +0 3300 +cob=(7) +cfi=(53) +cfn=(1174) +calls=420 0 +0 34020 +0 2100 +cob=(7) +cfi=(53) +cfn=(1174) +calls=180 0 +0 14580 +0 6120 + +fn=(3040) +0 33 + +fn=(3090) +0 16 +cfn=(3092) +calls=2 0 +0 78750 +0 26 + +fn=(3248) std::vector >::_M_insert_aux(__gnu_cxx::__normal_iterator > >, BTS::Prob::Test::Peaks::Peak const&) +0 129 +cob=(7) +cfi=(53) +cfn=(880) +calls=4 0 +0 1115 +0 44 +cfn=(3250) +calls=4 0 +0 3327 +0 24 +cfn=(3252) +calls=4 0 +0 6539 +0 24 +cfn=(3252) +calls=4 0 +0 84 +0 36 +cfn=(3254) +calls=3 0 +0 1155 +0 12 +cfn=(3254) +calls=4 0 +0 1540 +0 28 +cob=(7) +cfi=(53) +cfn=(1174) +calls=3 0 +0 336 +0 78 + +fn=(3266) +0 37 +cob=(7) +cfi=(53) +cfn=(880) +calls=1 0 +0 1293 +0 36 +cfn=(2888) +calls=6 0 +0 2341 +0 174 +cfn=(3268) +calls=6 0 +0 108 +0 30 +cfn=(2888) +calls=6 0 +0 2171 +0 298 + +fn=(3368) +0 22 +cob=(7) +cfi=(53) +cfn=(1264) +calls=2 0 +0 39 +0 70 +cfn=(3370) +calls=2 0 +0 116166 +0 12 +cfn=(2642) +calls=2 0 +0 1245 +0 20 +cfn=(2588) +calls=2 0 +0 1708 +0 66 +cfn=(3436) +calls=2 0 +0 736 +0 8 +cob=(7) +cfi=(53) +cfn=(1258) +calls=2 0 +0 40 +0 4 +cfn=(3438) +calls=2 0 +0 1798 +0 6 +cob=(7) +cfi=(53) +cfn=(1468) +calls=2 0 +0 30 +0 14 +cob=(7) +cfi=(53) +cfn=(1632) +calls=2 0 +0 2578 +0 14 +cob=(7) +cfi=(53) +cfn=(1712) +calls=2 0 +0 16 +0 8 +cfn=(3444) +calls=2 0 +0 13837 +0 6 +cfn=(2402) +calls=2 0 +0 457 +0 4 +cfn=(3462) +calls=2 0 +0 234 +0 6 +cob=(7) +cfi=(53) +cfn=(1468) +calls=2 0 +0 200 +0 4 +cfn=(3464) +calls=2 0 +0 1368 +0 16 + +fn=(3508) +0 10641223834 +cob=(7) +cfi=(53) +cfn=(1174) +calls=1023212298 0 +0 82880196138 +0 4465505356 +cob=(7) +cfi=(53) +cfn=(1174) +calls=343500412 0 +0 27823533372 +0 2061002472 +cfn=(3510) +calls=343500412 0 +0 143383554816 +0 2061002472 + +fn=(3524) +0 100 +cob=(7) +cfi=(53) +cfn=(880) +calls=4 0 +0 626 +0 88 +cob=(7) +cfi=(53) +cfn=(1258) +calls=8 0 +0 160 +0 64 +cfn=(3496) +calls=4 0 +0 5772 +0 60 +cfn=(3526) +calls=4 0 +0 140 +0 24 +cfn=(3526) +calls=4 0 +0 156 +0 92 +cob=(7) +cfi=(53) +cfn=(1264) +calls=4 0 +0 144 +0 28 +cob=(7) +cfi=(53) +cfn=(1468) +calls=4 0 +0 60 +0 12 +cob=(7) +cfi=(53) +cfn=(1468) +calls=4 0 +0 60 +0 16 +cob=(7) +cfi=(53) +cfn=(2846) +calls=8 0 +0 120 +0 32 +cfn=(3508) +calls=4 0 +0 2208 +0 36 + +fn=(3542) +0 920 + +fn=(3566) +0 3416196 +cfn=(3568) +calls=1138732 0 +0 2439152781 +0 56936600 + +fn=(3618) +0 23 +cob=(7) +cfi=(53) +cfn=(1258) +calls=2 0 +0 40 +0 18 + +fn=(3644) +0 689743086 +cfn=(3646) +calls=344871543 0 +0 2069229258 + +fn=(3722) +0 14 +cfn=(3724) +calls=1 0 +0 345 +0 12 + +fn=(3724) +0 1182 +cob=(7) +cfi=(53) +cfn=(880) +calls=54 0 +0 6132 +0 96 +cob=(7) +cfi=(53) +cfn=(880) +calls=48 0 +0 5280 +0 2142 +cob=(7) +cfi=(53) +cfn=(2426) +calls=102 0 +0 7277 +0 1567 + +fn=(3736) BTS::Image::Expected::Quartic::Voxel::Voxel(BTS::Image::Expected::Quartic::Buffer&, BTS::Image::Coord const&) +0 1659 +cfn=(3738) +calls=237 0 +0 3572142 +0 1896 + +fn=(3744) +0 8822108776 +cfn=(3746) +calls=678623752 0 +0 2035871256 +0 1357247504 +cfn=(3746) +calls=678623752 0 +0 2035871256 +0 6786237520 +cfn=(3746) +calls=678623752 0 +0 2035871256 +0 1357247504 +cfn=(3746) +calls=678623752 0 +0 2035871256 +0 6786237520 +cfn=(3746) +calls=678623752 0 +0 2035871256 +0 1357247504 +cfn=(3746) +calls=678623752 0 +0 2035871256 +0 3393118760 + +fn=(3750) +0 40527 +cfn=(3744) +calls=237 0 +0 14694 +0 22989 +cfn=(3744) +calls=237 0 +0 14694 +0 8769 + +fn=(3778) +0 56 +cfn=(3780) +calls=4 0 +0 1248 +0 48 + +fn=(3798) +0 78754 +cfn=(3508) +calls=9087 0 +0 7251426 +0 27261 +cfn=(3508) +calls=9087 0 +0 7251426 +0 18174 +cfn=(3508) +calls=9087 0 +0 7251426 +0 54522 +cob=(7) +cfi=(53) +cfn=(1174) +calls=3029 0 +0 321127 + +fn=(3818) +0 435226 +cfn=(3819) std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::_M_erase(std::_Rb_tree_node >*)'2 +calls=39566 0 +0 435226 +0 118698 +cfn=(3819) +calls=39566 0 +0 435226 +0 237396 +cob=(7) +cfi=(53) +cfn=(1468) +calls=79132 0 +0 7913200 +0 237396 +cob=(7) +cfi=(53) +cfn=(1174) +calls=79132 0 +0 6409692 +0 316528 + +fn=(3819) +0 870452 + +fn=(3826) +0 4959 +cob=(7) +cfi=(53) +cfn=(880) +calls=193 0 +0 34664 +0 344 +cob=(7) +cfi=(53) +cfn=(880) +calls=172 0 +0 30789 +0 14965 +cob=(7) +cfi=(53) +cfn=(2426) +calls=365 0 +0 26518 +0 6683 + +fn=(3876) +0 432 +cob=(7) +cfi=(53) +cfn=(880) +calls=48 0 +0 5536 + +fn=(3898) +0 23853650 +cob=(7) +cfi=(53) +cfn=(1258) +calls=1174220 0 +0 23484400 +0 22310180 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1174220 0 +0 17613300 +0 5871100 +cob=(7) +cfi=(53) +cfn=(1258) +calls=1174220 0 +0 23484400 +0 3522660 +cfn=(3900) +calls=1174220 0 +0 49317240 +0 2348440 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1174220 0 +0 17613300 +0 11953200 + +fn=(3904) +0 7231672 +cfn=(3566) +calls=1033096 0 +0 2276665079 +0 3099288 +cfn=(2888) +calls=1033096 0 +0 261739384 +0 5165480 +cfn=(3906) +calls=1033096 0 +0 3946577353 +0 5165480 + +fn=(3910) +0 256536472 + +fn=(3916) +0 7694784 +cfn=(3904) +calls=961848 0 +0 6054332880 +0 186598512 +cob=(9) +cfi=(58) +cfn=(2654) +calls=961848 0 +0 182751120 +0 3847392 + +fn=(3918) +0 290037 +cfn=(3620) +calls=26367 0 +0 250825489 +0 79101 +cfn=(2888) +calls=26367 0 +0 11294707 +0 131835 +cfn=(3920) void BTS::Fibre::Unzipper::unzip_intrinsic >(BTS::Fibre::Set const&, MR::Math::Vector&, unsigned int&) +calls=26367 0 +0 41931450 +0 448239 +cfn=(3906) +calls=26367 0 +0 99180512 +0 553707 +cfn=(3906) +calls=79101 0 +0 297432990 +0 1054680 + +fn=(3920) +0 316404 +cfn=(3922) std::vector > BTS::Fibre::Properties::Intrinsic_tpl::intrinsic_keys >() +calls=26367 0 +0 30857310 +0 421872 +cfn=(3894) +calls=26367 0 +0 553707 +0 79101 +cfn=(3896) +calls=26367 0 +0 975579 +0 369138 +cfn=(3910) +calls=26367 0 +0 2636700 +0 184569 +cfn=(2410) +calls=26367 0 +0 5326134 +0 210936 + +fn=(3946) +0 96 +cfn=(3922) +calls=8 0 +0 9408 +0 128 +cfn=(3894) +calls=8 0 +0 168 +0 24 +cfn=(3896) +calls=8 0 +0 296 +0 56 +cfn=(3948) +calls=8 0 +0 800 +0 112 +cfn=(2410) +calls=8 0 +0 1616 +0 64 + +fn=(3954) +0 1152 +cfn=(3914) +calls=96 0 +0 480 +0 576 +cfn=(2410) +calls=96 0 +0 1440 +0 8064 + +fn=(3958) +0 265 +cob=(11) +cfi=(60) +cfn=(3928) +calls=6 0 +0 10428 +0 3 +cob=(11) +cfi=(60) +cfn=(3928) +calls=1 0 +0 1738 +0 21 + +fn=(1092) +0 6 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 330 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 313 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 317 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 315 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 14 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 330 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 313 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 317 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 8 + +fn=(1102) +0 7 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 6 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 330 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 313 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 317 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 + +fn=(1120) +0 6 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 330 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 313 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 317 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 308 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 314 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 304 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 12 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 315 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 5 + +fn=(1146) +0 5 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 330 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 313 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 317 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 7 + +fn=(1158) +0 864 +cfn=(1160) +calls=74 0 +0 18685 +0 148 + +fn=(1166) +0 1193 +cob=(7) +cfi=(53) +cfn=(880) +calls=49 0 +0 10299 +0 3257 + +fn=(1202) +0 5 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 5 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 5 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 350 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 + +fn=(1222) +0 7 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 319 +0 6 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 344 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 309 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 330 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 313 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 +cob=(7) +cfi=(53) +cfn=(934) +calls=1 0 +0 317 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 2 +cob=(7) +cfi=(53) +cfn=(486) +calls=1 0 +0 24 +0 4 +cob=(4) +cfi=(56) +cfn=(362) +calls=1 57 +0 62 +0 4 + +fn=(1598) +0 451 +cob=(7) +cfi=(53) +cfn=(1174) +calls=3 0 +0 243 +0 190 +cob=(7) +cfi=(53) +cfn=(1174) +calls=4 0 +0 324 +0 200 + +fn=(2420) +0 915 +cob=(7) +cfi=(53) +cfn=(880) +calls=21 0 +0 3099 +0 100 +cob=(7) +cfi=(53) +cfn=(880) +calls=50 0 +0 7748 +0 497 +cob=(7) +cfi=(53) +cfn=(1258) +calls=71 0 +0 1420 +0 213 +cob=(7) +cfi=(53) +cfn=(1258) +calls=71 0 +0 1145 +0 355 +cob=(7) +cfi=(53) +cfn=(2426) +calls=71 0 +0 6618 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 2251 +0 1861 + +fn=(2634) +0 16 +cob=(11) +cfi=(60) +cfn=(2856) +calls=1 0 +0 5859 +0 25 +cob=(7) +cfi=(53) +cfn=(1468) +calls=1 0 +0 100 +0 10 +cob=(7) +cfi=(53) +cfn=(1174) +calls=1 0 +0 81 +0 8 +cob=(9) +cfi=(58) +cfn=(2522) +calls=2 0 +0 392 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 939 +0 14 +cfn=(2640) +calls=2 0 +0 248 +0 12 +cfn=(2640) +calls=6 0 +0 542 +0 32 +cob=(7) +cfi=(53) +cfn=(1174) +calls=2 0 +0 162 +0 8 +cob=(9) +cfi=(58) +cfn=(2522) +calls=2 0 +0 330 +0 4 +cob=(7) +cfi=(53) +cfn=(1468) +calls=2 0 +0 22 +0 6 +cfn=(2642) +calls=2 0 +0 4360 +0 8 + +fn=(2656) +0 15 + +fn=(2810) +0 297 +cfn=(2812) +calls=27 0 +0 108 +0 324 +cob=(7) +cfi=(53) +cfn=(880) +calls=27 0 +0 4658 +0 7425 + +fn=(2820) +0 345 +cob=(7) +cfi=(53) +cfn=(880) +calls=7 0 +0 1997 +0 40 +cob=(7) +cfi=(53) +cfn=(880) +calls=20 0 +0 4460 +0 864 +cob=(4) +cfi=(90) +cfn=(1282) +calls=27 47 +0 648 +0 621 +cob=(7) +cfi=(53) +cfn=(2426) +calls=27 0 +0 1217 +0 576 + +fn=(2890) +0 2623 +cfn=(2888) +calls=61 0 +0 19111 +0 549 +cfn=(2884) +calls=61 0 +0 37605 +0 2318 +cob=(6) +cfi=(122) /build/buildd/eglibc-2.11.1/math/../sysdeps/x86_64/fpu/s_sincos.S +cfn=(2896) sincos +calls=61 34 +0 549 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1430 +0 42273 +cob=(6) +cfi=(122) +cfn=(2896) +calls=6039 34 +0 54351 +0 97600 +cob=(6) +cfi=(123) /build/buildd/eglibc-2.11.1/math/../sysdeps/ieee754/dbl-64/w_exp.c +cfn=(2902) exp +calls=6100 38 +0 700400 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1390 +0 1439844 +cfn=(2884) +calls=61 0 +0 23241 +0 549 +cfn=(2884) +calls=61 0 +0 19764 +0 305 +cfn=(2884) +calls=61 0 +0 23241 +0 276025 +cob=(9) +cfi=(58) +cfn=(2912) gsl_blas_dgemm +calls=61 0 +0 1273115 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 843 +0 122 +cob=(9) +cfi=(58) +cfn=(2924) gsl_linalg_cholesky_decomp +calls=61 0 +0 118003 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1027 +0 122 +cob=(9) +cfi=(58) +cfn=(2950) gsl_linalg_cholesky_invert +calls=61 0 +0 216342 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1027 +0 488 +cob=(9) +cfi=(58) +cfn=(2976) gsl_blas_dsymm +calls=61 0 +0 1617765 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 843 +0 244 +cob=(9) +cfi=(58) +cfn=(2654) +calls=61 0 +0 11285 +0 244 +cob=(9) +cfi=(58) +cfn=(2654) +calls=61 0 +0 11956 +0 183 +cfn=(2984) +calls=61 0 +0 854 +0 427 +cob=(9) +cfi=(58) +cfn=(2990) gsl_blas_dgemv +calls=61 0 +0 259120 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 835 +0 244 +cob=(9) +cfi=(58) +cfn=(2654) +calls=61 0 +0 11285 +0 244 +cob=(9) +cfi=(58) +cfn=(2654) +calls=61 0 +0 11285 +0 244 +cob=(9) +cfi=(58) +cfn=(2654) +calls=61 0 +0 11956 +0 1098 + +fn=(2998) +0 39 +cfn=(2888) +calls=1 0 +0 240 +0 180 +cfn=(2888) +calls=60 0 +0 14400 +0 2565 +cfn=(2888) +calls=61 0 +0 14832 +0 5607 +cfn=(2888) +calls=54 0 +0 12960 +0 4726 +cob=(9) +cfi=(58) +cfn=(2654) +calls=61 0 +0 10065 +0 244 +cob=(9) +cfi=(58) +cfn=(2654) +calls=61 0 +0 10065 +0 672 +cfn=(2888) +calls=60 0 +0 14400 +0 2760 +cfn=(3004) +calls=60 0 +0 515202 +0 180 +cfn=(2984) +calls=60 0 +0 24840 +0 3480 +cob=(9) +cfi=(58) +cfn=(2654) +calls=60 0 +0 9900 +0 240 +cob=(9) +cfi=(58) +cfn=(2654) +calls=60 0 +0 9900 +0 88 +cfn=(3000) +calls=7 0 +0 51757 +0 7 + +fn=(3022) +0 13620 +cob=(7) +cfi=(53) +cfn=(880) +calls=420 0 +0 51930 +0 5460 +cob=(4) +cfi=(90) +cfn=(1282) +calls=420 47 +0 28560 +0 7860 + +fn=(3088) +0 4 + +fn=(3102) +0 35 +cfn=(3104) +calls=1 0 +0 218 +0 10 +cfn=(3108) +calls=1 0 +0 93 +0 84 +cob=(7) +cfi=(53) +cfn=(1594) +calls=1 0 +0 69 +0 9 +cob=(7) +cfi=(53) +cfn=(1594) +calls=1 0 +0 63 +0 25 +cfn=(3112) +calls=1 0 +0 674 +0 18 +cfn=(3112) +calls=1 0 +0 366 +0 12 +cob=(7) +cfi=(53) +cfn=(1594) +calls=1 0 +0 63 +0 4 +cob=(7) +cfi=(53) +cfn=(880) +calls=1 0 +0 195 +0 10 + +fn=(3110) +0 10 +cob=(7) +cfi=(53) +cfn=(1174) +calls=1 0 +0 81 + +fn=(3122) +0 30 +cob=(7) +cfi=(53) +cfn=(1506) +calls=1 0 +0 2745 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 2456 +0 4 +cob=(7) +cfi=(53) +cfn=(2786) +calls=1 0 +0 583 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1648 +0 13 +cob=(7) +cfi=(53) +cfn=(3162) +calls=1 0 +0 1910 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1412 +0 2 +cob=(7) +cfi=(53) +cfn=(3186) +calls=1 0 +0 1762 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1444 +0 3 +cob=(9) +cfi=(58) +cfn=(3204) gsl_rng_alloc +calls=1 0 +0 312 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 835 +0 4 +cob=(9) +cfi=(58) +cfn=(3206) gsl_rng_set +calls=1 0 +0 171 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 803 +0 20 +cfn=(2888) +calls=1 0 +0 410 +0 15 +cfn=(2888) +calls=5 0 +0 1200 +0 504 +cob=(9) +cfi=(58) +cfn=(3226) gsl_ran_flat +calls=8 0 +0 392 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 803 +0 64 +cob=(9) +cfi=(58) +cfn=(3226) +calls=8 0 +0 392 +0 50 +cfn=(2888) +calls=6 0 +0 1610 +0 60 +cob=(9) +cfi=(58) +cfn=(3236) gsl_ran_rayleigh +calls=6 0 +0 2962 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 875 +0 42 +cob=(9) +cfi=(58) +cfn=(3236) +calls=6 0 +0 1552 +0 24 +cob=(9) +cfi=(58) +cfn=(3236) +calls=6 0 +0 1528 +0 30 +cob=(9) +cfi=(58) +cfn=(3226) +calls=6 0 +0 294 +0 54 +cfn=(3246) +calls=6 0 +0 3628 +0 28 +cfn=(3258) +calls=2 0 +0 550 +0 6 +cfn=(3258) +calls=2 0 +0 550 +0 18 +cfn=(3254) +calls=2 0 +0 770 +0 8 +cfn=(3254) +calls=4 0 +0 1540 +0 12 +cfn=(3256) +calls=6 0 +0 1128 +0 12 +cfn=(3256) +calls=6 0 +0 1128 +0 27 +cob=(9) +cfi=(58) +cfn=(3264) gsl_rng_free +calls=1 0 +0 165 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 827 +0 24 +cfn=(3248) +calls=4 0 +0 14471 +0 4 + +fn=(3338) +0 2576 +cfn=(3340) +calls=322 0 +0 754124 +0 966 +cob=(7) +cfi=(53) +cfn=(2786) +calls=322 0 +0 200637 +0 966 +cob=(7) +cfi=(53) +cfn=(1534) +calls=322 0 +0 78565 +0 644 +cob=(7) +cfi=(53) +cfn=(1550) +calls=322 0 +0 75784 +0 1932 + +fn=(3462) +0 98 +cob=(7) +cfi=(53) +cfn=(1468) +calls=6 0 +0 90 +0 468 +cob=(7) +cfi=(53) +cfn=(1468) +calls=234 0 +0 3510 +0 790 +cob=(7) +cfi=(53) +cfn=(1174) +calls=10 0 +0 876 + +fn=(3466) +0 160 + +fn=(3494) +0 80 +cob=(4) +cfi=(100) +cfn=(1476) +calls=2 25 +0 72 +0 32 +cob=(4) +cfi=(100) +cfn=(1476) +calls=8 25 +0 280 +0 36 +cfn=(3496) +calls=8 0 +0 11586 +0 1400 +cfn=(3476) +calls=72 0 +0 14112 +0 2352 +cfn=(3500) +calls=72 0 +0 18786 +0 672 +cob=(7) +cfi=(53) +cfn=(880) +calls=24 0 +0 2895 +0 1536 +cfn=(3476) +calls=24 0 +0 4704 +0 288 +cob=(7) +cfi=(53) +cfn=(1174) +calls=24 0 +0 1944 +0 76 +cfn=(3504) +calls=5 0 +0 10099 +0 121 +cfn=(3476) +calls=8 0 +0 1568 +0 64 +cfn=(3508) +calls=8 0 +0 6384 +0 20 +cfn=(3502) +calls=3 0 +0 18270 +0 19 + +fn=(3506) +0 81 +cfn=(3504) +calls=3 0 +0 7826 +0 59 + +fn=(3518) +0 1588 +cfn=(2642) +calls=10 0 +0 1640 +0 386 +cob=(7) +cfi=(53) +cfn=(2852) +calls=8 0 +0 80 +0 32 +cob=(7) +cfi=(53) +cfn=(3540) +calls=8 0 +0 408 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 2171 +0 24 +cob=(7) +cfi=(53) +cfn=(1468) +calls=8 0 +0 120 +0 16 +cob=(7) +cfi=(53) +cfn=(1468) +calls=8 0 +0 120 +0 16 +cob=(7) +cfi=(53) +cfn=(1174) +calls=8 0 +0 648 +0 210 + +fn=(3552) +0 26 +cfn=(3554) +calls=2 0 +0 1601047 +0 6 +cfn=(2402) +calls=2 0 +0 7538 +0 8 +cfn=(3462) +calls=2 0 +0 4940 +0 2 +cfn=(3560) +calls=2 0 +0 1994 +0 30 +cfn=(3566) +calls=2 0 +0 4582 +0 36 +cfn=(3566) +calls=6 0 +0 12648 +0 76 +cob=(7) +cfi=(53) +cfn=(1632) +calls=2 0 +0 3727 +0 14 +cob=(7) +cfi=(53) +cfn=(1712) +calls=2 0 +0 16 +0 10 +cob=(7) +cfi=(53) +cfn=(1506) +calls=2 0 +0 1790 +0 18 +cob=(7) +cfi=(53) +cfn=(1506) +calls=2 0 +0 354 +0 1160 +cob=(7) +cfi=(53) +cfn=(1506) +calls=232 0 +0 41224 +0 702 +cob=(7) +cfi=(53) +cfn=(1500) +calls=234 0 +0 46332 +0 490 +cob=(7) +cfi=(53) +cfn=(3162) +calls=2 0 +0 106 +0 4 +cob=(7) +cfi=(53) +cfn=(3186) +calls=2 0 +0 4579 +0 16 + +fn=(3558) +0 1564 +cob=(7) +cfi=(53) +cfn=(1258) +calls=206 0 +0 4120 +0 1030 +cob=(7) +cfi=(53) +cfn=(1468) +calls=206 0 +0 3090 +0 20 +cob=(7) +cfi=(53) +cfn=(1468) +calls=10 0 +0 150 +0 432 +cob=(7) +cfi=(53) +cfn=(1468) +calls=216 0 +0 21600 +0 432 +cob=(7) +cfi=(53) +cfn=(1468) +calls=216 0 +0 21600 +0 432 +cob=(7) +cfi=(53) +cfn=(1468) +calls=216 0 +0 21600 +0 1440 +cfn=(3338) +calls=144 0 +0 498367 +0 216 +cfn=(3338) +calls=72 0 +0 248961 +0 864 +cfn=(3436) +calls=216 0 +0 76254 +0 864 +cfn=(1396) +calls=216 0 +0 63077 +0 864 +cfn=(3436) +calls=216 0 +0 90719 +0 1100 +cfn=(2390) +calls=10 0 +0 17713 +0 586 + +fn=(3670) +0 136 + +fn=(3734) +0 711 +cfn=(3736) +calls=237 0 +0 3575697 +0 711 + +fn=(3850) +0 67183188336 +cfn=(3744) +calls=678618064 0 +0 42074319968 +0 1357236128 + +fn=(3914) +0 17078940 + +fn=(3922) +0 791250 +cfn=(3268) +calls=26375 0 +0 474750 +0 764875 +cob=(7) +cfi=(53) +cfn=(934) +calls=26375 0 +0 6171766 +0 79125 +cfn=(3348) +calls=26375 0 +0 8387378 +0 105500 +cob=(7) +cfi=(53) +cfn=(1468) +calls=26375 0 +0 395625 +0 79125 +cfn=(2642) +calls=26375 0 +0 290125 +0 158250 +cob=(7) +cfi=(53) +cfn=(2846) +calls=26375 0 +0 474750 +0 290125 +cfn=(2390) +calls=26375 0 +0 6153199 +0 79125 +cfn=(3624) +calls=26375 0 +0 5960750 +0 211000 + +ob=(3) +fl=(39) +fn=(184) +0 6 + +fn=(178) +0 6 + +fn=(190) +0 11 + +ob=(9) +fl=(58) +fn=(2506) +0 48 +cob=(4) +cfi=(71) +cfn=(886) +calls=6 3615 +0 586 +0 30 +cob=(4) +cfi=(71) +cfn=(886) +calls=6 3615 +0 1103 +0 54 + +fn=(2952) gsl_matrix_submatrix +0 8052 + +fn=(2924) +0 20069 +cfn=(2926) gsl_matrix_row +calls=549 0 +0 9333 +0 2196 +cfn=(2926) +calls=549 0 +0 9333 +0 2928 +cfn=(2928) gsl_vector_subvector +calls=366 0 +0 6954 +0 1830 +cfn=(2928) +calls=366 0 +0 6954 +0 1464 +cfn=(2930) gsl_blas_ddot +calls=366 0 +0 18878 +0 1098 +cfn=(2926) +calls=183 0 +0 3111 +0 915 +cfn=(2928) +calls=183 0 +0 3477 +0 366 +cfn=(2938) gsl_blas_dnrm2 +calls=183 0 +0 14762 +0 14335 + +fn=(2926) +0 21777 + +fn=(2956) gsl_blas_dtrmv +0 5124 +cob=(8) +cfi=(57) +cfn=(2962) +calls=244 0 +0 37210 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 898 +0 488 + +fn=(3228) 0x000000000011f6b0 +0 1360 + +fn=(2912) +0 2379 +cob=(8) +cfi=(57) +cfn=(2918) +calls=61 0 +0 1269593 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 838 +0 305 + +fn=(2930) +0 15372 +cob=(8) +cfi=(57) +cfn=(2936) +calls=1281 0 +0 47580 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 822 +0 5124 + +fn=(3204) +0 6 +cob=(4) +cfi=(71) +cfn=(886) +calls=1 3615 +0 95 +0 5 +cob=(4) +cfi=(71) +cfn=(886) +calls=1 3615 +0 180 +0 8 +cfn=(3206) +calls=1 0 +0 13 +0 5 + +fn=(2522) +0 36 +cob=(4) +cfi=(71) +cfn=(1180) +calls=6 3692 +0 574 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1642 +0 18 +cob=(4) +cfi=(71) +cfn=(1180) +calls=6 3692 +0 468 + +fn=(428) +0 6 + +fn=(1916) +0 8980464 +cob=(4) +cfi=(71) +cfn=(886) +calls=1122558 3615 +0 106894723 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1742 +0 5612790 +cob=(4) +cfi=(71) +cfn=(886) +calls=1122558 3615 +0 301348579 +0 10103022 + +fn=(2954) gsl_matrix_subcolumn +0 40687 + +fn=(422) +0 6 + +fn=(434) +0 11 + +fn=(2654) +0 6733764 +cob=(4) +cfi=(71) +cfn=(1180) +calls=1122294 3692 +0 135873263 +0 3366882 +cob=(4) +cfi=(71) +cfn=(1180) +calls=1122294 3692 +0 87538932 + +fn=(2938) +0 732 +cob=(8) +cfi=(57) +cfn=(2944) +calls=183 0 +0 13176 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 854 + +fn=(2950) +0 8174 +cfn=(2952) +calls=244 0 +0 8052 +0 4880 +cfn=(2954) +calls=244 0 +0 5612 +0 3904 +cfn=(2956) +calls=244 0 +0 43720 +0 976 +cfn=(2964) gsl_blas_dscal +calls=244 0 +0 8288 +0 2013 +cfn=(2954) +calls=61 0 +0 1403 +0 1830 +cfn=(2954) +calls=183 0 +0 4209 +0 2196 +cfn=(2954) +calls=366 0 +0 8418 +0 10370 +cfn=(2954) +calls=610 0 +0 14030 +0 8540 +cfn=(2930) +calls=610 0 +0 31720 +0 6954 +cfn=(2954) +calls=244 0 +0 5612 +0 3416 +cfn=(2930) +calls=244 0 +0 15616 +0 3294 +cfn=(2954) +calls=61 0 +0 1403 +0 854 +cfn=(2930) +calls=61 0 +0 2684 +0 8174 + +fn=(2964) +0 976 +cob=(8) +cfi=(57) +cfn=(2970) +calls=244 0 +0 6466 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 846 + +fn=(3206) +0 184 + +fn=(3226) +0 132 +cfn=(3228) +calls=22 0 +0 748 +0 198 + +fn=(3264) +0 6 +cob=(4) +cfi=(71) +cfn=(1180) +calls=1 3692 +0 78 +0 3 +cob=(4) +cfi=(71) +cfn=(1180) +calls=1 3692 +0 78 + +fn=(2622) +0 24 + +fn=(2976) +0 1891 +cob=(8) +cfi=(57) +cfn=(2982) +calls=61 0 +0 1614365 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 838 +0 671 + +fn=(2628) +0 6 +cob=(4) +cfi=(71) +cfn=(1180) +calls=1 3692 +0 78 +0 3 +cob=(4) +cfi=(71) +cfn=(1180) +calls=1 3692 +0 78 + +fn=(3236) +0 144 +cfn=(3228) +calls=18 0 +0 612 +0 108 +cob=(6) +cfi=(136) /build/buildd/eglibc-2.11.1/math/w_log.c +cfn=(3242) log +calls=18 31 +0 3574 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 1424 +0 180 + +fn=(2616) +0 8 +cob=(4) +cfi=(71) +cfn=(886) +calls=1 3615 +0 95 +0 5 +cob=(4) +cfi=(71) +cfn=(886) +calls=1 3615 +0 95 +0 9 + +fn=(2928) +0 17385 + +fn=(2990) +0 1342 +cob=(8) +cfi=(57) +cfn=(2996) +calls=61 0 +0 256444 +cob=(1) +cfi=(54) +cfn=(356) +calls=1 30 +0 846 +0 488 + +ob=(6) +fl=(136) +fn=(3242) +31 36 ++5 36 +cfi=(137) /build/buildd/eglibc-2.11.1/math/../sysdeps/ieee754/dbl-64/e_log.c +cfn=(3244) __ieee754_log +calls=18 +14 +* 2908 ++1 18 +-1 18 ++1 108 +cfi=(128) /build/buildd/eglibc-2.11.1/math/../sysdeps/ieee754/dbl-64/s_isnan.c +cfn=(3014) isnan +calls=18 -4 +* 270 +* 126 ++6 54 + +fl=(129) +fn=(3038) +44 18 ++1 3 +-1 6 ++1 9 ++1 6 ++1 6 ++6 9 ++1 12 ++26 3 + +fl=(124) /build/buildd/eglibc-2.11.1/math/../sysdeps/ieee754/dbl-64/e_exp.c +fn=(2904) __ieee754_exp +57 12200 ++1 12200 ++1 12200 ++2 18300 ++2 6000 ++19 6000 +-19 12000 ++6 6000 +-1 6000 +-5 6000 ++1 6000 ++2 6000 ++5 6000 +-5 6000 +-2 12000 ++4 6000 ++3 6000 +-2 12000 ++2 6000 +-2 6000 ++4 6000 ++1 6000 +-1 6000 ++2 6000 ++4 6000 ++1 6000 +-6 6000 ++5 6000 ++1 6000 +-1 6000 ++3 6000 ++1 6000 +-4 6000 ++4 18000 +-9 6000 ++8 24000 +-7 12000 ++8 6000 +-8 18000 ++8 6000 +-8 6000 ++7 6000 ++1 6000 +-1 6000 ++1 24000 ++2 30000 ++1 12000 ++2 36000 ++36 6000 +-1 30000 ++1 6000 ++23 12000 +-55 300 ++55 200 + +fn=(3016) __exp1 +164 540 ++1 360 ++1 360 ++2 540 ++1 180 ++19 180 ++6 180 +-25 360 ++25 180 +-24 180 ++2 180 ++5 180 +-5 180 +-2 360 ++4 180 ++1 180 ++5 180 +-5 180 ++2 360 ++2 180 ++1 180 +-1 180 ++6 180 ++1 180 +-6 180 ++1 180 ++4 180 ++1 180 +-1 180 ++3 180 ++1 180 +-4 180 ++4 360 +-9 180 ++9 180 +-1 180 ++1 180 +-8 1080 ++7 720 ++1 180 +-1 180 ++1 900 ++2 720 ++1 180 +-1 180 ++3 180 +-2 180 ++2 1260 +-11 900 ++11 360 ++58 360 + +fl=(123) +fn=(2902) +38 12200 ++5 12200 +cfi=(124) +cfn=(2904) +calls=6100 +14 +* 517400 ++1 6100 +-1 6100 ++1 18300 ++1 18300 +cfi=(125) /build/buildd/eglibc-2.11.1/math/../sysdeps/ieee754/dbl-64/s_finite.c +cfn=(2906) finite +calls=6100 -12 +* 42700 +* 24400 ++1 12200 ++2 12200 ++5 18300 + +fl=(137) +fn=(3244) +50 144 ++19 72 ++2 36 ++10 36 ++1 18 +-1 18 ++1 90 +-5 54 +203 144 +77 36 ++56 18 ++1 18 +-1 36 ++1 36 +-1 18 ++1 18 +-1 18 ++1 18 ++1 92 ++4 10 +-3 10 ++12 10 +-9 10 ++15 10 +-15 20 ++1 20 ++3 10 +-3 20 ++14 10 +-11 10 ++4 10 +-4 10 ++4 10 ++8 10 +-12 10 ++12 10 +-12 20 ++4 10 +-4 20 ++1 20 ++3 10 +-3 20 ++3 10 ++1 10 +-1 10 ++1 20 ++7 30 ++1 20 +-1 10 ++1 20 ++1 20 +-1 20 +-9 30 ++10 20 +-9 30 ++9 10 +-18 8 +-3 8 ++12 8 +-9 8 ++15 8 +-15 16 ++1 16 ++3 8 +-3 16 ++14 8 +-11 8 ++4 8 +-4 8 ++4 8 ++8 8 +-12 8 ++12 8 +-12 16 ++4 8 +-4 16 ++1 16 ++3 8 +-3 16 ++3 8 ++1 8 +-1 8 ++1 16 ++7 24 ++1 16 +-1 8 ++1 16 ++1 16 +-1 16 +-9 24 ++10 16 +-9 24 ++9 46 ++1 285 ++1 85 ++4 34 +-4 17 ++1 34 +-1 17 ++1 85 ++3 102 +-4 5 ++4 2 +-4 1 ++1 2 +-1 1 ++1 5 ++3 24 +-81 54 ++75 185 ++1 4 + +fl=(128) +fn=(3014) +33 1854 ++2 618 +-2 618 ++2 5562 ++3 618 + +fl=(151) +fn=(3704) +90 300 ++11 120 ++1 120 ++1 120 ++1 120 ++3 120 ++1 3 ++2 3 ++1 3 +-3 3 ++2 36 ++3 3 +-2 3 ++2 21 +785 3 +339 354 +116 114 ++1 27 ++6 9 +-5 9 +-1 9 ++3 18 +-3 9 ++4 18 +-4 9 ++1 9 +-1 9 ++5 9 +-4 9 ++5 18 ++1 18 +-5 9 +-1 9 ++6 9 +-5 9 ++1 45 ++1 9 +-1 9 ++1 54 ++6 90 ++3 9 +-3 9 ++1 18 ++2 81 ++4 144 ++2 110 ++1 66 ++5 12 ++1 12 +-1 36 ++1 12 +-1 12 ++1 48 ++2 12 ++3 12 +-2 12 ++7 12 +-8 12 ++1 24 ++5 24 ++2 24 +-7 24 ++5 24 ++2 12 +-7 12 ++7 48 +-7 24 ++7 12 +-7 12 ++7 144 ++3 12 +-3 12 ++1 24 ++2 72 +-11 10 ++3 10 +-2 10 ++7 10 +-8 10 ++1 20 ++5 20 ++2 20 +-7 20 ++5 20 ++2 10 +-7 10 ++7 40 +-7 20 ++7 10 +-7 10 ++7 120 ++3 10 +-3 10 ++1 20 ++2 140 +827 3 +339 1 +-78 1 ++78 5 +160 52 ++1 52 ++3 26 +-3 26 ++3 26 ++2 26 +-5 26 ++1 26 ++1 52 +-1 26 ++3 26 +-1 26 +-2 26 ++4 26 +-2 130 ++3 26 ++1 26 +-1 26 ++1 26 +-1 26 ++1 26 ++1 78 +-1 26 ++1 78 ++2 104 ++3 18 ++1 18 +-1 18 ++1 93 ++1 39 ++2 54 ++2 3 +-2 3 ++1 6 ++1 6 ++1 8 ++1 18 +694 4 +316 6 +138 20 ++1 10 +-1 20 ++1 10 +-1 10 ++1 30 +659 8 ++1 6 ++1 4 ++1 1 ++1 1 +-1 2 ++1 1 +-1 1 ++1 2 ++8 1 ++3 1 ++1 1 ++4 1 +-8 1 ++8 1 +-4 1 ++2 1 ++2 1 ++2 1 +-4 1 ++6 1 +-2 1 +-4 1 ++2 1 ++4 6 +-2 1 ++2 17 ++1 1 +-1 3 ++1 2 +-1 2 ++2 1 +-2 1 ++2 1 ++1 1 +-3 1 +-12 1 ++3 1 ++1 1 ++4 1 +-8 1 ++8 1 +-4 1 ++2 1 ++2 1 ++2 1 +-4 1 ++6 1 +-2 1 +-4 1 ++2 1 ++4 6 +-2 1 ++2 17 ++1 1 +-1 3 ++1 2 +-1 2 ++2 1 +-2 1 ++2 1 ++1 1 +-3 1 ++2 1 ++1 1 ++2 6 +-3 1 ++1 1 ++2 8 +209 16 ++1 20 ++1 4 ++6 4 +-5 4 +-1 4 ++10 4 +-9 4 +-1 4 ++8 4 +-8 4 ++1 4 ++2 4 ++7 4 +-4 4 ++4 4 +-4 4 +-5 4 ++5 4 ++4 12 +-9 8 ++7 4 +-7 4 ++9 4 +-8 4 ++6 4 +-6 4 ++6 8 ++2 4 +-2 4 ++2 4 +-2 8 ++2 8 +-2 4 ++2 40 ++1 4 +-1 4 ++1 4 ++1 8 ++1 8 +-13 4 ++6 4 +-5 4 +-1 4 ++10 4 +-9 4 +-1 4 ++8 4 +-8 4 ++1 4 ++2 4 ++7 4 +-4 4 ++4 4 +-4 4 +-5 4 ++5 4 ++4 12 +-9 8 ++7 4 +-7 4 ++9 4 +-8 4 ++6 4 +-6 4 ++6 8 ++2 4 +-2 4 ++2 4 +-2 8 ++2 8 +-2 4 ++2 40 ++1 4 +-1 4 ++1 4 ++1 8 ++1 16 ++1 91 +667 1 ++1 1 +-1 2 ++1 1 +-1 1 ++1 3 ++1 2 +224 12 +-39 72 ++4 9 ++6 9 +-3 9 +-3 9 ++10 9 +-10 9 ++1 9 +-1 9 ++5 9 ++1 18 ++4 9 +-9 9 ++2 9 ++7 45 +-8 9 ++1 9 ++7 9 +-8 9 ++1 18 ++7 9 +-7 9 ++7 9 +-7 18 ++7 18 +-7 9 ++7 18 +-7 9 ++7 63 ++1 9 +-1 27 ++1 9 ++1 18 ++1 18 +-13 6 ++6 6 +-3 6 +-3 6 ++10 6 +-10 6 ++1 6 +-1 6 ++5 6 ++1 12 ++4 6 +-9 6 ++2 6 ++7 30 +-8 6 ++1 6 ++7 6 +-8 6 ++1 12 ++7 6 +-7 6 ++7 6 +-7 12 ++7 12 +-7 6 ++7 12 +-7 6 ++7 42 ++1 6 +-1 18 ++1 6 ++1 12 ++1 26 ++1 117 +800 2 ++1 1 +-1 2 ++4 1 ++3 1 ++1 1 ++5 1 +-9 1 ++9 1 +-5 1 ++2 1 ++3 1 ++2 1 +-5 1 ++7 1 +-2 1 +-5 1 ++3 1 ++4 6 +-2 1 ++2 17 ++1 1 +-1 5 ++1 2 +-1 1 ++2 1 ++1 1 +-3 1 ++2 2 ++1 1 ++1 2 ++1 8 ++1 4 ++4 2 +202 24 +-14 36 +-7 6 + +fn=(3694) +348 240 ++5 120 ++2 180 ++2 120 ++2 120 ++1 36 ++1 12 ++8 12 +-8 12 ++3 12 +-3 12 ++3 12 ++7 36 +-10 12 ++1 12 +-1 12 ++5 12 +-4 12 ++9 12 +-2 12 ++2 12 +-2 24 ++2 24 +-8 12 ++1 12 ++7 12 +-8 12 ++1 60 ++7 12 +-7 12 ++7 144 ++1 12 +-1 12 ++1 12 ++2 84 ++4 96 ++1 132 ++1 66 ++1 22 +-1 22 ++1 22 ++1 44 +-1 22 ++2 47 ++1 39 ++2 3 +-2 3 ++1 3 +-1 3 ++1 3 ++1 6 ++1 8 ++47 16 +587 240 +360 24 ++53 52 ++1 52 ++3 26 +-3 26 ++3 26 +-3 26 ++1 26 ++1 26 ++1 26 +-1 26 +-1 26 ++3 26 +-1 26 +-2 26 ++2 26 ++2 26 +-2 78 ++3 52 ++1 26 +-1 26 ++1 26 ++1 78 +-1 26 ++1 26 ++2 104 ++35 106 ++1 14 ++6 14 +-5 14 +-1 14 ++8 14 ++2 28 +-9 14 +-1 28 ++1 14 ++2 14 ++7 14 +-4 14 ++4 14 +-4 14 +-5 14 ++5 14 ++4 42 +-9 28 ++7 14 +-7 14 ++9 14 +-8 14 ++6 14 +-6 14 ++6 70 ++2 14 +-2 14 ++2 168 ++1 14 +-1 14 ++1 14 ++1 28 ++1 28 +-13 4 ++6 4 +-5 4 +-1 4 ++8 4 ++2 8 +-9 4 +-1 8 ++1 4 ++2 4 ++7 4 +-4 4 ++4 4 +-4 4 +-5 4 ++5 4 ++4 12 +-9 8 ++7 4 +-7 4 ++9 4 +-8 4 ++6 4 +-6 4 ++6 20 ++2 4 +-2 4 ++2 48 ++1 4 +-1 4 ++1 4 ++1 8 ++1 26 ++1 72 +1125 42 +391 57 ++1 50 ++1 10 ++6 10 +-6 30 ++1 10 +-1 10 ++3 10 ++2 10 +-4 10 ++5 20 ++4 20 +-8 10 ++1 10 ++7 20 +-8 10 ++8 30 +-7 40 ++7 20 +-7 10 ++7 10 +-7 10 ++7 80 ++1 10 +-1 30 ++2 10 +-1 10 ++1 20 ++1 20 +-13 9 ++6 9 +-6 27 ++1 9 +-1 9 ++3 9 ++2 9 +-4 9 ++5 18 ++4 18 +-8 9 ++1 9 ++7 18 +-8 9 ++8 27 +-7 36 ++7 18 +-7 9 ++7 9 +-7 9 ++7 72 ++1 9 +-1 27 ++2 9 +-1 9 ++1 18 ++1 38 ++47 104 ++75 52 ++21 84 +391 36 +-4 6 ++35 78 +-16 27 ++21 8 ++1 8 +-1 8 ++1 8 ++1 17 ++1 13 ++2 1 +-2 2 ++1 2 ++1 2 ++1 5 ++4 26 ++2 4 ++6 4 +-6 12 ++1 4 +-1 4 ++3 4 ++2 4 +-4 4 ++5 8 ++4 8 +-8 4 ++1 4 ++7 8 +-8 4 ++8 12 +-7 16 ++7 8 +-7 4 ++7 4 +-7 4 ++7 32 ++1 4 +-1 12 ++2 4 +-1 4 ++1 8 ++1 8 +-13 3 ++6 3 +-6 9 ++1 3 +-1 3 ++3 3 ++2 3 +-4 3 ++5 6 ++4 6 +-8 3 ++1 3 ++7 6 +-8 3 ++8 9 +-7 12 ++7 6 +-7 3 ++7 3 +-7 3 ++7 24 ++1 3 +-1 9 ++2 3 +-1 3 ++1 6 ++1 15 ++21 27 +-21 12 +-14 18 + +fl=(126) +fn=(3010) +29 900 ++5 300 +cfi=(127) /build/buildd/eglibc-2.11.1/math/../sysdeps/ieee754/dbl-64/e_pow.c +cfn=(3012) __ieee754_pow +calls=300 +24 +* 55080 ++1 300 +-1 300 ++1 1200 +cfi=(128) +cfn=(3014) +calls=300 -2 +* 4500 +* 600 ++1 600 +cfi=(128) +cfn=(3014) +calls=300 -3 +* 4500 +* 600 ++29 900 +-23 1200 ++11 900 +cfi=(125) +cfn=(2906) +calls=300 -20 +* 2100 +* 900 ++8 900 + +fl=(122) +fn=(2896) +34 6100 ++1 6100 ++1 6100 ++1 6100 ++1 6100 ++1 6100 ++1 6100 ++1 6100 ++3 6100 + +fl=(70) +fn=(868) +39 1 ++1 4 ++1 2 ++1 2 ++6 1 ++1 1 +-1 1 ++1 2 ++12 1 + +fl=(125) +fn=(2906) +33 38400 ++2 6400 + +fl=(52) +fn=(252) +0 6 + +fn=(246) +0 6 + +fn=(258) +0 11 + +fl=(152) +fn=(3716) +44 12515508 ++1 2085918 +-1 4171836 ++1 6257754 ++1 4171836 ++1 4171836 ++7 4278831 ++1 2852554 ++1 5705108 ++1 2852554 ++1 5705108 ++21 8557662 ++2 1426277 +-2 3957846 ++2 659641 +-33 2638564 ++1 2638564 ++1 1063955 ++5 32 ++2 48895 + +fl=(127) +fn=(3012) +58 600 ++17 300 +-17 2100 ++14 300 ++1 300 ++1 300 ++63 300 +-71 300 ++2 300 +-1 300 ++1 600 ++10 540 ++3 540 +-3 360 +-9 900 ++2 900 ++1 1200 ++1 900 ++1 720 ++1 1140 ++80 1800 ++48 360 +78 180 +203 180 ++4 180 +-3 360 ++3 360 ++3 720 ++5 1260 ++1 180 ++1 540 ++1 360 ++37 180 ++1 180 +-2 180 ++1 180 ++1 360 ++1 180 +-2 180 ++5 180 +-3 180 +-1 180 +-1 180 ++2 180 ++3 180 ++2 180 +-5 180 ++1 180 ++2 180 ++2 180 +-2 180 ++2 180 +-4 180 ++2 180 ++1 180 ++1 180 +-1 180 ++1 3240 ++1 180 +-1 180 ++1 180 ++2 540 +83 180 ++10 360 +-10 180 ++3 180 +-1 180 +-2 180 ++3 180 +-2 540 ++3 360 +-2 180 ++2 180 ++2 180 ++1 180 +-1 180 ++1 720 ++1 360 ++2 360 ++1 2520 +cfi=(124) +cfn=(3016) +calls=180 +70 +* 15840 ++1 1800 +-22 240 +211 1620 + +totals: 7351907657194 diff --git a/python/fibre/__init__.py b/python/fibre/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/python/fibre/base/__init__.py b/python/fibre/base/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/python/fibre/base/object.py b/python/fibre/base/object.py new file mode 100644 index 0000000..cfde8e5 --- /dev/null +++ b/python/fibre/base/object.py @@ -0,0 +1,34 @@ + + + +class Object(object): + + def __init__(self, size=0, value=0.0): + + self.vector = list() + self.prps = dict() + self.extend_prps = dict() + + for i in range(size): + self.vector.append((value,value,value)) + + def size(self): + + return len(self.vector) + + def num_props(self): + + return len(self.prps) + + + def __str__(self): + + string = '' + + for key_val in sorted(self.prps.items()): + string = string + key_val[0] + ': ' + str(key_val[1]) + '\n' + + for triple in self.vector: + string = string + '[ %s, %s, %s ]\n' % (triple[0], triple[1], triple[2]) + + return string \ No newline at end of file diff --git a/python/fibre/base/set.py b/python/fibre/base/set.py new file mode 100644 index 0000000..ffaccce --- /dev/null +++ b/python/fibre/base/set.py @@ -0,0 +1,539 @@ +from copy import copy, deepcopy +from object import Object + +class CantBeFrozenException(Exception): + + def __init__(self, value): + self.value = value + + def __str__(self): + return repr(self.value) + + +class ElemSizeException(Exception): + + def __init__(self, value): + self.value = value + + def __str__(self): + return repr(self.value) + + +class UnmatchedPropertiesException(Exception): + + def __init__(self, value): + self.value = value + + def __str__(self): + return repr(self.value) + + +class Set(object): + + def __init__(self): + + self.elems = list() + + self.prps = dict() + self.extend_prps = dict() + + self.elem_prp_keys = list() + self.elem_extend_prps = dict() + + self.elem_degree = 0 + + + def first_set(self, num_elems, elem_degree): + + self.elems = list() + + self.prps = dict() + self.extend_prps = dict() + + self.elem_prp_keys = list() + self.elem_extend_prps = dict() + + for elem_i in range(num_elems): + + self.elems.append(Object(elem_degree)) + + for elem_elem_i in range(elem_degree): + base = elem_i * 100 + elem_elem_i * 10 + self.elems[elem_i].vector[elem_elem_i] = (base + 1, base + 2, base + 3) + + for prop_i in range(5): + self.elems[elem_i].prps['ELEM_PROP_' + str(prop_i+1)] = elem_i * 100.0 + (prop_i+1) * .1 + 0.001; + + for prop_i in range(5): + self.elem_prp_keys.append('ELEM_PROP_' + str(prop_i+1)) + self.prps['PROP_' + str(prop_i+1)] = (prop_i+1) * 1.1 + 0.001 + + + for i in range(1,6): + self.add_extend_elem_prop("EXT_ELEM_PROP_" + str(i),"NaN") + for j in range(len(self.elems)): + self.set_extend_elem_prop("EXT_ELEM_PROP_" + str(i), "Ooogle " + str(i) + "-" + str(j), j) + + + self.elem_degree = elem_degree + + + def second_set(self, num_elems, elem_degree): + + self.elems = list() + + self.prps = dict() + self.extend_prps = dict() + + self.elem_prp_keys = list() + self.elem_extend_prps = dict() + + for elem_i in range(num_elems): + + self.elems.append(Object(elem_degree)) + + for elem_elem_i in range(elem_degree): + base = elem_i * 100 + elem_elem_i * 10 + self.elems[elem_i].vector[elem_elem_i] = (-(base + 1), -(base + 2), -(base + 3)) + + for prop_i in range(5): + self.elems[elem_i].prps['ELEM_PROP_' + str(prop_i+1)] = -(elem_i * 100.0 + (prop_i+1) * .1 + 0.001); + + for prop_i in range(5): + self.elem_prp_keys.append('ELEM_PROP_' + str(prop_i+1)) + self.prps['PROP_' + str(prop_i+1)] = -((prop_i+1) * 1.1 + 0.001) + + + for i in range(6,11): + self.add_extend_elem_prop("EXT_ELEM_PROP_" + str(i),"NaN") + for j in range(len(self.elems)): + self.set_extend_elem_prop("EXT_ELEM_PROP_" + str(i), "Boogle " + str(i) + "-" + str(j), j) + + + self.elem_degree = elem_degree + + + def __str__(self): + + string = '' + + if self.extend_prps: + string = string + '(' + for key_val in sorted(self.extend_prps.items()): + string = string + key_val[0] + ': ' + str(key_val[1]) + ', ' + if self.extend_prps: + string = string + ')\n' + + string = string + '\n' + + for (key,val) in sorted(self.prps.items()): + string = string + key + ': ' + str(val) + '\n' + + elem_i = 0 + + for elem in self.elems: + string = string + '\n--------------------\n' + string = string + ' %d\n' % elem_i + string = string + '--------------------\n' + + if elem.extend_prps: + string = string + '{' + count = 0 + for (key,val) in sorted(elem.extend_prps.items()): + string = string + key + ': ' + str(val) + count = count + 1 + if count != len(elem.extend_prps): + string = string + ', ' + if elem.extend_prps: + string = string + '}\n' + + string = string + '\n' + + string = string + str(elem) + + string = string + '\n' + + elem_i = elem_i + 1 + + return string + + #===================================================================================================================== + # Set functions + #===================================================================================================================== + + + def elem_resize(self, new_size, value): + + for elem_i in range(self.size()): + + elem_degree = len(self.elems[elem_i].vector) + + for i in range(elem_degree,new_size): + self.elems[elem_i].vector.append((value,value,value)) + + for i in range(elem_degree-1,new_size-1,-1): + self.elems[elem_i].vector.pop(i) + + self.elem_degree = new_size + + + def push_back(self, elem, ext_prop_row=dict()): + + # Make a copy of the element and reset its extended properties + append_elem = deepcopy(elem) + append_elem.extend_prps = dict() + + # Loop through the keys present in the set + for key in self.elem_extend_prps.keys(): + if ext_prop_row: + # Use the properties explicitly provided + if ext_prop_row.has_key(key): + append_elem.extend_prps[key] = ext_prop_row[key] + else: + append_elem.extend_prps[key] = self.elem_extend_prps[key] + else: + # Copy across only the extended properties present in the set, and populate the missing extended properties with defaults. + if elem.extend_prps.has_key(key): + append_elem.extend_prps[key] = elem.extend_prps[key] + else: + append_elem.extend_prps[key] = self.elem_extend_prps[key] + + self.elems.append(append_elem) + + + def erase(self, index): + + self.elems.pop(index) + + + def insert(self, elem, index): + + # Make a copy of the element and reset its extended properties + insert_elem = deepcopy(elem) + insert_elem.extend_prps = dict() + + # Loop through the keys present in the set + for key in self.elem_extend_prps.keys(): + # Copy across only the extended properties present in the set, and populate the missing extended properties with defaults. + if elem.extend_prps.has_key(key): + insert_elem.extend_prps[key] = elem.extend_prps[key] + else: + insert_elem.extend_prps[key] = self.elem_extend_prps[key] + + self.elems.insert(index, insert_elem) + + def append(self, set): + + if self.elem_prp_keys != set.elem_prp_keys or self.prps != set.prps: + raise UnmatchedPropertiesException ('properties do not match') + + if self.elem_degree and self.elem_degree != set.elem_degree: + raise ElemSizeException ('Element sizes do not match') + + for elem in set.elems: + self.push_back(elem) + + + def get_extend_elem_prop_header(self): + + return sorted(self.elem_extend_prps.keys()) + + + def get_elem_prop_header(self): + + return sorted(self.elem_prp_keys) + + + def add_extend_elem_prop(self, key, default_value): + + if not self.elem_extend_prps.has_key(key): + for elem in self.elems: + elem.extend_prps[key] = default_value + + self.elem_extend_prps[key] = default_value + + def add_extend_elem_props(self,set): + + for (key,val) in set.elem_extend_prps.items(): + self.add_extend_elem_prop(key,val) + + + def clear_extend_elem_props(self): + + self.elem_extend_prps = dict() + + for elem in self.elems: + + elem.extend_prps = dict() + + + def remove_extend_elem_prop(self, key): + + self.elem_extend_prps.pop(key,None) + + for elem in self.elems: + + elem.extend_prps.pop(key,None) + + ####################### + def set_extend_elem_prop(self,key,value,index): + + self.elems[index].extend_prps[key] = value + + + def get_extend_elem_prop(self,key,index): + + return self.elems[index].extend_prps[key] + + + def has_extend_elem_prop(self,key): + + return self.elem_extend_prps.keys().count(key) + + + def get_extend_elem_prop_row(self,index): + + return self.elems[index].extend_prps + + + def set_extend_elem_prop_row(self,prop_row,index): + + this_props = self.elems[index].extend_prps + + # Loop through the keys present in the set + for key in self.elem_extend_prps.keys(): + # Copy across only the extended properties present in the set, and populate the missing extended properties with defaults. + if prop_row.has_key(key): + this_props[key] = prop_row[key] + else: + this_props[key] = self.elem_extend_prps[key] + + + def copy_extend_elem_prop_row(self,set,their_index,this_index): + + self.set_extend_elem_prop_row(set.get_extend_elem_prop_row(their_index),this_index) + + + def copy_extend_elem_props(self,set): + + self.elem_extend_prps = copy(set.elem_extend_prps) + + for (this_elem,their_elem) in zip(self.elems,set.elems): + this_elem.extend_prps = copy(their_elem.extend_prps) + + + def append_extend_elem_props(self,set): + + for (key,val) in set.elem_extend_prps.items(): +# if key not in self.elem_extend_prps: + self.elem_extend_prps[key] = val + for (this_elem,their_elem) in zip(self.elems,set.elems): + this_elem.extend_prps[key] = their_elem.extend_prps[key] + + + def add_elem_prop(self,key,value): + + if key not in self.elem_prp_keys: + self.elem_prp_keys.append(key) + + for elem in self.elems: + + elem.prps[key] = value + + + def has_elem_prop(self,key): + + return self.elem_prp_keys.count(key) + + + def remove_elem_prop(self,key,ignore_missing=True): + + try: + self.elem_prp_keys.remove(key) + except ValueError: + if not ignore_missing: + raise Exception ("Could not remove element property '%s' as it was not present" % key) + + for elem in self.elems: + + elem.prps.pop(key,None) + + + def clear_elem_props(self): + + self.elem_prp_keys = list() + + for elem in self.elems: + + elem.prps = dict() + + + def elem_prop_index(self,key): + + keys = sorted(self.elem_prp_keys) + + for i in range(len(keys)): + if keys[i] == key: + return i + + raise Exception ("Key (" + key + ") was not found.") + + + def elem_prop_name(self, index): + + keys = sorted(self.elem_prp_keys) + + return keys[index] + + + def elem_prop_keys(self): + + keys = sorted(self.elem_prp_keys) + + return keys + + + def freeze_elem_degree(self): + + if self.size(): + elem_degree = self.elems[0].size() + + for elem in self.elems: + if elem.size() != elem_degree: + raise CantBeFrozenException ("Elements not all the same size") + + self.elem_degree = elem_degree + + + def free_elem_degree(self): + + self.elem_degree = 0 + + + + def resize(self, new_size, fill_value, new_elem_degree=0): + + if self.elem_degree: + if new_elem_degree: + raise Exception ("'new_elem_degree' parameter can only be supplied when element size is variable."); + elem_degree = self.elem_degree + else: + elem_degree = new_elem_degree + + old_size = self.size() + + for i in range(old_size,new_size): + object = Object(elem_degree,fill_value) + for key in self.elem_prp_keys: + object.prps[key] = fill_value + + for (key,val) in self.elem_extend_prps.items(): + object.extend_prps[key] = val + + self.elems.append(object) + + for i in range(old_size-1,new_size-1,-1): + self.elems.pop(i) + + + def clear(self): + + self.elems = list() + self.extend_prps = dict() + self.elem_extend_prps = dict() + + + def size(self): + + return len(self.elems) + + + def num_props(self): + + return len(self.prps) + + + def num_elem_props(self): + + return len(self.elem_prp_keys) + + + def num_extend_elem_props(self): + + return len(self.elem_extend_prps) + + + def vsize(self): + + return self.bsize() + self.num_props() + + + def bsize(self): + + base_size = 0 + + for elem in self.elems: + base_size = base_size + elem.size() * 3 + elem.num_props() + + return base_size + + + def add_prop(self, prop_key,value): + + if self.prps.has_key(prop_key): + raise Exception ("'" + prop_key + "' property already present.") + + self.prps[prop_key] = value + + + def has_prop(self, prop_key): + + return int(self.prps.has_key(prop_key)) + + + def remove_prop(self, prop_key): + + if self.prps.pop(prop_key,-9999) == -9999: + raise Exception ("key + (" + prop_key + ") was not found, use 'ignore_missing' to ignore.") + + + def clear_props(self): + + self.prps.clear() + + + def prop_index(self, prop_key): + + keys = sorted(self.prps.keys()) + + for prop_i in range(len(keys)): + if prop_key == keys[prop_i]: + return prop_i + + raise Exception ("Key '" + str(prop_key) + "' not found.") + + +# def prop(self, index): +# +# keys = sorted(self.prps.keys()) +# +# return self.prps[keys[index]] + + + def prop_name(self, index): + + return sorted(self.prps.keys())[index] + + + def prop_keys(self): + + return sorted(self.prps.keys()) + + + def prop(self, key): + + return self.prps[key] + + + + \ No newline at end of file diff --git a/python/fibre/base/test/__init__.py b/python/fibre/base/test/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/python/fibre/base/test/output/cpp_output.txt b/python/fibre/base/test/output/cpp_output.txt new file mode 100644 index 0000000..b885816 --- /dev/null +++ b/python/fibre/base/test/output/cpp_output.txt @@ -0,0 +1,4273 @@ + + +------------------------------------- + INITIAL SET +------------------------------------- + +PROP_1: 1.101 +PROP_2: 2.201 +PROP_3: 3.301 +PROP_4: 4.401 +PROP_5: 5.501 + +-------------------- + 0 +-------------------- +{EXT_ELEM_PROP_1: Ooogle 1-0, EXT_ELEM_PROP_2: Ooogle 2-0, EXT_ELEM_PROP_3: Ooogle 3-0, EXT_ELEM_PROP_4: Ooogle 4-0, EXT_ELEM_PROP_5: Ooogle 5-0} + +ELEM_PROP_1: 0.101 +ELEM_PROP_2: 0.201 +ELEM_PROP_3: 0.301 +ELEM_PROP_4: 0.401 +ELEM_PROP_5: 0.501 +[ 1, 2, 3 ] +[ 11, 12, 13 ] +[ 21, 22, 23 ] +[ 31, 32, 33 ] +[ 41, 42, 43 ] + + +-------------------- + 1 +-------------------- +{EXT_ELEM_PROP_1: Ooogle 1-1, EXT_ELEM_PROP_2: Ooogle 2-1, EXT_ELEM_PROP_3: Ooogle 3-1, EXT_ELEM_PROP_4: Ooogle 4-1, EXT_ELEM_PROP_5: Ooogle 5-1} + +ELEM_PROP_1: 100.101 +ELEM_PROP_2: 100.201 +ELEM_PROP_3: 100.301 +ELEM_PROP_4: 100.401 +ELEM_PROP_5: 100.501 +[ 101, 102, 103 ] +[ 111, 112, 113 ] +[ 121, 122, 123 ] +[ 131, 132, 133 ] +[ 141, 142, 143 ] + + +-------------------- + 2 +-------------------- +{EXT_ELEM_PROP_1: Ooogle 1-2, EXT_ELEM_PROP_2: Ooogle 2-2, EXT_ELEM_PROP_3: Ooogle 3-2, EXT_ELEM_PROP_4: Ooogle 4-2, EXT_ELEM_PROP_5: Ooogle 5-2} + +ELEM_PROP_1: 200.101 +ELEM_PROP_2: 200.201 +ELEM_PROP_3: 200.301 +ELEM_PROP_4: 200.401 +ELEM_PROP_5: 200.501 +[ 201, 202, 203 ] +[ 211, 212, 213 ] +[ 221, 222, 223 ] +[ 231, 232, 233 ] +[ 241, 242, 243 ] + + +-------------------- + 3 +-------------------- +{EXT_ELEM_PROP_1: Ooogle 1-3, EXT_ELEM_PROP_2: Ooogle 2-3, EXT_ELEM_PROP_3: Ooogle 3-3, EXT_ELEM_PROP_4: Ooogle 4-3, EXT_ELEM_PROP_5: Ooogle 5-3} + +ELEM_PROP_1: 300.101 +ELEM_PROP_2: 300.201 +ELEM_PROP_3: 300.301 +ELEM_PROP_4: 300.401 +ELEM_PROP_5: 300.501 +[ 301, 302, 303 ] +[ 311, 312, 313 ] +[ 321, 322, 323 ] +[ 331, 332, 333 ] +[ 341, 342, 343 ] + + +-------------------- + 4 +-------------------- +{EXT_ELEM_PROP_1: Ooogle 1-4, EXT_ELEM_PROP_2: Ooogle 2-4, EXT_ELEM_PROP_3: Ooogle 3-4, EXT_ELEM_PROP_4: Ooogle 4-4, EXT_ELEM_PROP_5: Ooogle 5-4} + +ELEM_PROP_1: 400.101 +ELEM_PROP_2: 400.201 +ELEM_PROP_3: 400.301 +ELEM_PROP_4: 400.401 +ELEM_PROP_5: 400.501 +[ 401, 402, 403 ] +[ 411, 412, 413 ] +[ 421, 422, 423 ] +[ 431, 432, 433 ] +[ 441, 442, 443 ] + + + + + +------------------------------------- + SECOND SET +------------------------------------- + +PROP_1: -1.101 +PROP_2: -2.201 +PROP_3: -3.301 +PROP_4: -4.401 +PROP_5: -5.501 + +-------------------- + 0 +-------------------- +{EXT_ELEM_PROP_10: Boogle 10-0, EXT_ELEM_PROP_6: Boogle 6-0, EXT_ELEM_PROP_7: Boogle 7-0, EXT_ELEM_PROP_8: Boogle 8-0, EXT_ELEM_PROP_9: Boogle 9-0} + +ELEM_PROP_1: -0.101 +ELEM_PROP_2: -0.201 +ELEM_PROP_3: -0.301 +ELEM_PROP_4: -0.401 +ELEM_PROP_5: -0.501 +[ -1, -2, -3 ] +[ -11, -12, -13 ] +[ -21, -22, -23 ] +[ -31, -32, -33 ] +[ -41, -42, -43 ] + + +-------------------- + 1 +-------------------- +{EXT_ELEM_PROP_10: Boogle 10-1, EXT_ELEM_PROP_6: Boogle 6-1, EXT_ELEM_PROP_7: Boogle 7-1, EXT_ELEM_PROP_8: Boogle 8-1, EXT_ELEM_PROP_9: Boogle 9-1} + +ELEM_PROP_1: -100.101 +ELEM_PROP_2: -100.201 +ELEM_PROP_3: -100.301 +ELEM_PROP_4: -100.401 +ELEM_PROP_5: -100.501 +[ -101, -102, -103 ] +[ -111, -112, -113 ] +[ -121, -122, -123 ] +[ -131, -132, -133 ] +[ -141, -142, -143 ] + + +-------------------- + 2 +-------------------- +{EXT_ELEM_PROP_10: Boogle 10-2, EXT_ELEM_PROP_6: Boogle 6-2, EXT_ELEM_PROP_7: Boogle 7-2, EXT_ELEM_PROP_8: Boogle 8-2, EXT_ELEM_PROP_9: Boogle 9-2} + +ELEM_PROP_1: -200.101 +ELEM_PROP_2: -200.201 +ELEM_PROP_3: -200.301 +ELEM_PROP_4: -200.401 +ELEM_PROP_5: -200.501 +[ -201, -202, -203 ] +[ -211, -212, -213 ] +[ -221, -222, -223 ] +[ -231, -232, -233 ] +[ -241, -242, -243 ] + + +-------------------- + 3 +-------------------- +{EXT_ELEM_PROP_10: Boogle 10-3, EXT_ELEM_PROP_6: Boogle 6-3, EXT_ELEM_PROP_7: Boogle 7-3, EXT_ELEM_PROP_8: Boogle 8-3, EXT_ELEM_PROP_9: Boogle 9-3} + +ELEM_PROP_1: -300.101 +ELEM_PROP_2: -300.201 +ELEM_PROP_3: -300.301 +ELEM_PROP_4: -300.401 +ELEM_PROP_5: -300.501 +[ -301, -302, -303 ] +[ -311, -312, -313 ] +[ -321, -322, -323 ] +[ -331, -332, -333 ] +[ -341, -342, -343 ] + + +-------------------- + 4 +-------------------- +{EXT_ELEM_PROP_10: Boogle 10-4, EXT_ELEM_PROP_6: Boogle 6-4, EXT_ELEM_PROP_7: Boogle 7-4, EXT_ELEM_PROP_8: Boogle 8-4, EXT_ELEM_PROP_9: Boogle 9-4} + +ELEM_PROP_1: -400.101 +ELEM_PROP_2: -400.201 +ELEM_PROP_3: -400.301 +ELEM_PROP_4: -400.401 +ELEM_PROP_5: -400.501 +[ -401, -402, -403 ] +[ -411, -412, -413 ] +[ -421, -422, -423 ] +[ -431, -432, -433 ] +[ -441, -442, -443 ] + + + +set.num_elem_props(): 5 +set.elem_prop_index(ELEM_PROP_4): 3 +set.has_extend_elem_prop(EXT_ELEM_PROP_7): 0 +set.num_props(): 6 + + +------------------------------------- + 5 MODFICATIONS +------------------------------------- + +PROP_1: 1.101 +PROP_2: 2.201 +PROP_4: 4.401 +PROP_5: 5.501 +PROP_6: 984 + +-------------------- + 0 +-------------------- +{EXT_ELEM_PROP_1: Ooogle 1-0, EXT_ELEM_PROP_2: Ooogle 2-0, EXT_ELEM_PROP_3: Ooogle 3-0, EXT_ELEM_PROP_4: Ooogle 4-0, EXT_ELEM_PROP_5: Ooogle 5-0} + +ELEM_PROP_1: 0.101 +ELEM_PROP_2: 669 +ELEM_PROP_3: 0.301 +ELEM_PROP_4: 0.401 +ELEM_PROP_5: 0.501 +[ 1, 2, 3 ] +[ 11, 12, 13 ] +[ 21, 22, 23 ] +[ 31, 32, 33 ] +[ 41, 42, 43 ] + + +-------------------- + 1 +-------------------- +{EXT_ELEM_PROP_1: NaN, EXT_ELEM_PROP_2: NaN, EXT_ELEM_PROP_3: NaN, EXT_ELEM_PROP_4: NaN, EXT_ELEM_PROP_5: NaN} + +ELEM_PROP_1: 1009 +ELEM_PROP_2: 669 +ELEM_PROP_3: 1009 +ELEM_PROP_4: 1009 +ELEM_PROP_5: 1009 +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] + + +-------------------- + 2 +-------------------- +{EXT_ELEM_PROP_1: Ooogle 1-1, EXT_ELEM_PROP_2: Ooogle 2-1, EXT_ELEM_PROP_3: Ooogle 3-1, EXT_ELEM_PROP_4: Ooogle 4-1, EXT_ELEM_PROP_5: Ooogle 5-1} + +ELEM_PROP_1: 100.101 +ELEM_PROP_2: 669 +ELEM_PROP_3: 100.301 +ELEM_PROP_4: 100.401 +ELEM_PROP_5: 100.501 +[ 101, 102, 103 ] +[ 111, 112, 113 ] +[ 121, 122, 123 ] +[ 131, 132, 133 ] +[ 141, 142, 143 ] + + +-------------------- + 3 +-------------------- +{EXT_ELEM_PROP_1: Ooogle 1-2, EXT_ELEM_PROP_2: Ooogle 2-2, EXT_ELEM_PROP_3: Ooogle 3-2, EXT_ELEM_PROP_4: Ooogle 4-2, EXT_ELEM_PROP_5: Ooogle 5-2} + +ELEM_PROP_1: 200.101 +ELEM_PROP_2: 669 +ELEM_PROP_3: 200.301 +ELEM_PROP_4: 200.401 +ELEM_PROP_5: 200.501 +[ 201, 202, 203 ] +[ 211, 212, 213 ] +[ 221, 222, 223 ] +[ 231, 232, 233 ] +[ 241, 242, 243 ] + + +-------------------- + 4 +-------------------- +{EXT_ELEM_PROP_1: Ooogle 1-3, EXT_ELEM_PROP_2: Ooogle 2-3, EXT_ELEM_PROP_3: Ooogle 3-3, EXT_ELEM_PROP_4: Ooogle 4-3, EXT_ELEM_PROP_5: Ooogle 5-3} + +ELEM_PROP_1: 300.101 +ELEM_PROP_2: 669 +ELEM_PROP_3: 300.301 +ELEM_PROP_4: 300.401 +ELEM_PROP_5: 300.501 +[ 301, 302, 303 ] +[ 311, 312, 313 ] +[ 321, 322, 323 ] +[ 331, 332, 333 ] +[ 341, 342, 343 ] + + +-------------------- + 5 +-------------------- +{EXT_ELEM_PROP_1: Ooogle 1-4, EXT_ELEM_PROP_2: Ooogle 2-4, EXT_ELEM_PROP_3: Ooogle 3-4, EXT_ELEM_PROP_4: Ooogle 4-4, EXT_ELEM_PROP_5: Ooogle 5-4} + +ELEM_PROP_1: 400.101 +ELEM_PROP_2: 669 +ELEM_PROP_3: 400.301 +ELEM_PROP_4: 400.401 +ELEM_PROP_5: 400.501 +[ 401, 402, 403 ] +[ 411, 412, 413 ] +[ 421, 422, 423 ] +[ 431, 432, 433 ] +[ 441, 442, 443 ] + + + +set.bsize(): 120 +set.size(): 6 +set.num_extend_elem_props(): 5 +set.prop(PROP_9): 419 +set.elem_prop_keys(): [ ELEM_PROP_1 ELEM_PROP_2 ELEM_PROP_3 ELEM_PROP_4 ELEM_PROP_5 ] + + +------------------------------------- + 10 MODFICATIONS +------------------------------------- + +PROP_1: 1.101 +PROP_2: 2.201 +PROP_4: 4.401 +PROP_5: 5.501 +PROP_6: 984 +PROP_9: 419 + +-------------------- + 0 +-------------------- +{EXT_ELEM_PROP_1: Ooogle 1-0, EXT_ELEM_PROP_2: Ooogle 2-0, EXT_ELEM_PROP_3: Ooogle 3-0, EXT_ELEM_PROP_4: Ooogle 4-0, EXT_ELEM_PROP_5: Ooogle 5-0} + +ELEM_PROP_1: 0.101 +ELEM_PROP_2: 669 +ELEM_PROP_3: 0.301 +ELEM_PROP_4: 463 +ELEM_PROP_5: 661 +[ 1, 2, 3 ] +[ 11, 12, 13 ] +[ 21, 22, 23 ] +[ 31, 32, 33 ] +[ 41, 42, 43 ] + + +-------------------- + 1 +-------------------- +{EXT_ELEM_PROP_1: NaN, EXT_ELEM_PROP_2: NaN, EXT_ELEM_PROP_3: NaN, EXT_ELEM_PROP_4: NaN, EXT_ELEM_PROP_5: NaN} + +ELEM_PROP_1: 1009 +ELEM_PROP_2: 669 +ELEM_PROP_3: 1009 +ELEM_PROP_4: 463 +ELEM_PROP_5: 661 +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] + + +-------------------- + 2 +-------------------- +{EXT_ELEM_PROP_1: NaN, EXT_ELEM_PROP_2: NaN, EXT_ELEM_PROP_3: NaN, EXT_ELEM_PROP_4: NaN, EXT_ELEM_PROP_5: NaN} + +ELEM_PROP_1: 100.101 +ELEM_PROP_2: 669 +ELEM_PROP_3: 100.301 +ELEM_PROP_4: 463 +ELEM_PROP_5: 661 +[ 101, 102, 103 ] +[ 111, 112, 113 ] +[ 121, 122, 123 ] +[ 131, 132, 133 ] +[ 141, 142, 143 ] + + +-------------------- + 3 +-------------------- +{EXT_ELEM_PROP_1: Ooogle 1-2, EXT_ELEM_PROP_2: Ooogle 2-2, EXT_ELEM_PROP_3: Ooogle 3-2, EXT_ELEM_PROP_4: Ooogle 4-2, EXT_ELEM_PROP_5: Ooogle 5-2} + +ELEM_PROP_1: 200.101 +ELEM_PROP_2: 669 +ELEM_PROP_3: 200.301 +ELEM_PROP_4: 463 +ELEM_PROP_5: 661 +[ 201, 202, 203 ] +[ 211, 212, 213 ] +[ 221, 222, 223 ] +[ 231, 232, 233 ] +[ 241, 242, 243 ] + + +-------------------- + 4 +-------------------- +{EXT_ELEM_PROP_1: Ooogle 1-3, EXT_ELEM_PROP_2: Ooogle 2-3, EXT_ELEM_PROP_3: Ooogle 3-3, EXT_ELEM_PROP_4: Ooogle 4-3, EXT_ELEM_PROP_5: Ooogle 5-3} + +ELEM_PROP_1: 300.101 +ELEM_PROP_2: 669 +ELEM_PROP_3: 300.301 +ELEM_PROP_4: 463 +ELEM_PROP_5: 661 +[ 301, 302, 303 ] +[ 311, 312, 313 ] +[ 321, 322, 323 ] +[ 331, 332, 333 ] +[ 341, 342, 343 ] + + +-------------------- + 5 +-------------------- +{EXT_ELEM_PROP_1: Ooogle 1-4, EXT_ELEM_PROP_2: Ooogle 2-4, EXT_ELEM_PROP_3: Ooogle 3-4, EXT_ELEM_PROP_4: Ooogle 4-4, EXT_ELEM_PROP_5: Ooogle 5-4} + +ELEM_PROP_1: 400.101 +ELEM_PROP_2: 669 +ELEM_PROP_3: 400.301 +ELEM_PROP_4: 463 +ELEM_PROP_5: 661 +[ 401, 402, 403 ] +[ 411, 412, 413 ] +[ 421, 422, 423 ] +[ 431, 432, 433 ] +[ 441, 442, 443 ] + + + +set.prop_index(PROP_2): 1 +set.vsize(): 158 +set.num_props(): 6 +set.num_extend_elem_props(): 5 +set.prop_index(PROP_2): 1 + + +------------------------------------- + 15 MODFICATIONS +------------------------------------- + +PROP_1: 1.101 +PROP_2: 2.201 +PROP_4: 4.401 +PROP_5: 5.501 +PROP_6: 984 +PROP_7: 434 +PROP_9: 419 + +-------------------- + 0 +-------------------- +{EXT_ELEM_PROP_1: Ooogle 1-0, EXT_ELEM_PROP_2: Ooogle 2-0, EXT_ELEM_PROP_3: Ooogle 3-0, EXT_ELEM_PROP_4: Ooogle 4-0, EXT_ELEM_PROP_5: Ooogle 5-0} + +ELEM_PROP_1: 0.101 +ELEM_PROP_2: 669 +ELEM_PROP_3: 0.301 +ELEM_PROP_4: 815 +ELEM_PROP_5: 661 +[ 1, 2, 3 ] +[ 11, 12, 13 ] +[ 21, 22, 23 ] +[ 31, 32, 33 ] +[ 41, 42, 43 ] + + +-------------------- + 1 +-------------------- +{EXT_ELEM_PROP_1: NaN, EXT_ELEM_PROP_2: NaN, EXT_ELEM_PROP_3: NaN, EXT_ELEM_PROP_4: NaN, EXT_ELEM_PROP_5: NaN} + +ELEM_PROP_1: 1009 +ELEM_PROP_2: 1009 +ELEM_PROP_3: 1009 +ELEM_PROP_4: 1009 +ELEM_PROP_5: 1009 +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] + + +-------------------- + 2 +-------------------- +{EXT_ELEM_PROP_1: NaN, EXT_ELEM_PROP_2: NaN, EXT_ELEM_PROP_3: NaN, EXT_ELEM_PROP_4: NaN, EXT_ELEM_PROP_5: NaN} + +ELEM_PROP_1: 100.101 +ELEM_PROP_2: 669 +ELEM_PROP_3: 100.301 +ELEM_PROP_4: 815 +ELEM_PROP_5: 661 +[ 101, 102, 103 ] +[ 111, 112, 113 ] +[ 121, 122, 123 ] +[ 131, 132, 133 ] +[ 141, 142, 143 ] + + +-------------------- + 3 +-------------------- +{EXT_ELEM_PROP_1: Ooogle 1-2, EXT_ELEM_PROP_2: Ooogle 2-2, EXT_ELEM_PROP_3: Ooogle 3-2, EXT_ELEM_PROP_4: Ooogle 4-2, EXT_ELEM_PROP_5: Ooogle 5-2} + +ELEM_PROP_1: 200.101 +ELEM_PROP_2: 669 +ELEM_PROP_3: 200.301 +ELEM_PROP_4: 815 +ELEM_PROP_5: 661 +[ 201, 202, 203 ] +[ 211, 212, 213 ] +[ 221, 222, 223 ] +[ 231, 232, 233 ] +[ 241, 242, 243 ] + + +-------------------- + 4 +-------------------- +{EXT_ELEM_PROP_1: Ooogle 1-3, EXT_ELEM_PROP_2: Ooogle 2-3, EXT_ELEM_PROP_3: Ooogle 3-3, EXT_ELEM_PROP_4: Ooogle 4-3, EXT_ELEM_PROP_5: Ooogle 5-3} + +ELEM_PROP_1: 300.101 +ELEM_PROP_2: 669 +ELEM_PROP_3: 300.301 +ELEM_PROP_4: 815 +ELEM_PROP_5: 661 +[ 301, 302, 303 ] +[ 311, 312, 313 ] +[ 321, 322, 323 ] +[ 331, 332, 333 ] +[ 341, 342, 343 ] + + +-------------------- + 5 +-------------------- +{EXT_ELEM_PROP_1: Ooogle 1-4, EXT_ELEM_PROP_2: Ooogle 2-4, EXT_ELEM_PROP_3: Ooogle 3-4, EXT_ELEM_PROP_4: Ooogle 4-4, EXT_ELEM_PROP_5: Ooogle 5-4} + +ELEM_PROP_1: 400.101 +ELEM_PROP_2: 669 +ELEM_PROP_3: 400.301 +ELEM_PROP_4: 815 +ELEM_PROP_5: 661 +[ 401, 402, 403 ] +[ 411, 412, 413 ] +[ 421, 422, 423 ] +[ 431, 432, 433 ] +[ 441, 442, 443 ] + + +-------------------- + 6 +-------------------- +{EXT_ELEM_PROP_1: 1.141, EXT_ELEM_PROP_2: 2.241, EXT_ELEM_PROP_3: 3.341, EXT_ELEM_PROP_4: 4.441, EXT_ELEM_PROP_5: 5.541} + +ELEM_PROP_1: 1001 +ELEM_PROP_2: 1001 +ELEM_PROP_3: 1001 +ELEM_PROP_4: 815 +ELEM_PROP_5: 1001 +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] + + + +set.get_extend_elem_prop_header(): [ EXT_ELEM_PROP_1 EXT_ELEM_PROP_2 EXT_ELEM_PROP_3 EXT_ELEM_PROP_4 EXT_ELEM_PROP_5 ] +set.prop_keys(): [ PROP_1 PROP_2 PROP_4 PROP_5 PROP_6 PROP_7 PROP_9 ] +set.prop_keys(): [ PROP_1 PROP_2 PROP_4 PROP_5 PROP_6 PROP_7 PROP_9 ] +set.elem_prop_keys(): [ ELEM_PROP_1 ELEM_PROP_2 ELEM_PROP_3 ELEM_PROP_4 ELEM_PROP_5 ] + + +------------------------------------- + 20 MODFICATIONS +------------------------------------- + +PROP_1: 1.101 +PROP_2: 2.201 +PROP_4: 4.401 +PROP_5: 5.501 +PROP_6: 984 +PROP_7: 434 +PROP_9: 419 + +-------------------- + 0 +-------------------- +{EXT_ELEM_PROP_1: Ooogle 1-0, EXT_ELEM_PROP_2: Ooogle 2-0, EXT_ELEM_PROP_3: Ooogle 3-0, EXT_ELEM_PROP_4: Ooogle 4-0, EXT_ELEM_PROP_5: Ooogle 5-0} + +ELEM_PROP_1: 0.101 +ELEM_PROP_2: 669 +ELEM_PROP_3: 0.301 +ELEM_PROP_4: 815 +ELEM_PROP_5: 661 +[ 1, 2, 3 ] +[ 11, 12, 13 ] +[ 21, 22, 23 ] +[ 31, 32, 33 ] +[ 41, 42, 43 ] + + +-------------------- + 1 +-------------------- +{EXT_ELEM_PROP_1: NaN, EXT_ELEM_PROP_2: NaN, EXT_ELEM_PROP_3: NaN, EXT_ELEM_PROP_4: NaN, EXT_ELEM_PROP_5: NaN} + +ELEM_PROP_1: 1009 +ELEM_PROP_2: 1009 +ELEM_PROP_3: 1009 +ELEM_PROP_4: 1009 +ELEM_PROP_5: 1009 +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] + + +-------------------- + 2 +-------------------- +{EXT_ELEM_PROP_1: Ooogle 1-2, EXT_ELEM_PROP_2: Ooogle 2-2, EXT_ELEM_PROP_3: Ooogle 3-2, EXT_ELEM_PROP_4: Ooogle 4-2, EXT_ELEM_PROP_5: Ooogle 5-2} + +ELEM_PROP_1: 200.101 +ELEM_PROP_2: 669 +ELEM_PROP_3: 200.301 +ELEM_PROP_4: 815 +ELEM_PROP_5: 661 +[ 201, 202, 203 ] +[ 211, 212, 213 ] +[ 221, 222, 223 ] +[ 231, 232, 233 ] +[ 241, 242, 243 ] + + +-------------------- + 3 +-------------------- +{EXT_ELEM_PROP_1: 1.141, EXT_ELEM_PROP_2: 2.241, EXT_ELEM_PROP_3: 3.341, EXT_ELEM_PROP_4: 4.441, EXT_ELEM_PROP_5: 5.541} + +ELEM_PROP_1: 300.101 +ELEM_PROP_2: 669 +ELEM_PROP_3: 300.301 +ELEM_PROP_4: 815 +ELEM_PROP_5: 661 +[ 301, 302, 303 ] +[ 311, 312, 313 ] +[ 321, 322, 323 ] +[ 331, 332, 333 ] +[ 341, 342, 343 ] + + +-------------------- + 4 +-------------------- +{EXT_ELEM_PROP_1: Ooogle 1-4, EXT_ELEM_PROP_2: Ooogle 2-4, EXT_ELEM_PROP_3: Ooogle 3-4, EXT_ELEM_PROP_4: Ooogle 4-4, EXT_ELEM_PROP_5: Ooogle 5-4} + +ELEM_PROP_1: 400.101 +ELEM_PROP_2: 669 +ELEM_PROP_3: 400.301 +ELEM_PROP_4: 815 +ELEM_PROP_5: 661 +[ 401, 402, 403 ] +[ 411, 412, 413 ] +[ 421, 422, 423 ] +[ 431, 432, 433 ] +[ 441, 442, 443 ] + + +-------------------- + 5 +-------------------- +{EXT_ELEM_PROP_1: 1.141, EXT_ELEM_PROP_2: 2.241, EXT_ELEM_PROP_3: 3.341, EXT_ELEM_PROP_4: 4.441, EXT_ELEM_PROP_5: 5.541} + +ELEM_PROP_1: 1001 +ELEM_PROP_2: 1001 +ELEM_PROP_3: 1001 +ELEM_PROP_4: 815 +ELEM_PROP_5: 1001 +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] + + +-------------------- + 6 +-------------------- +{EXT_ELEM_PROP_1: 1.181, EXT_ELEM_PROP_2: 2.281, EXT_ELEM_PROP_3: 3.381, EXT_ELEM_PROP_4: 4.481, EXT_ELEM_PROP_5: 5.581} + +ELEM_PROP_1: 1007 +ELEM_PROP_2: 1007 +ELEM_PROP_3: 1007 +ELEM_PROP_4: 1007 +ELEM_PROP_5: 1007 +[ 1007, 1007, 1007 ] +[ 1007, 1007, 1007 ] +[ 1007, 1007, 1007 ] +[ 1007, 1007, 1007 ] +[ 1007, 1007, 1007 ] + + + +set.elem_prop_index(ELEM_PROP_4): 3 +set.elem_prop_index(ELEM_PROP_4): 3 + + +------------------------------------- + 25 MODFICATIONS +------------------------------------- + +PROP_1: 1.101 +PROP_2: 2.201 +PROP_4: 4.401 +PROP_5: 5.501 +PROP_6: 984 +PROP_7: 434 +PROP_9: 419 + +-------------------- + 0 +-------------------- +{EXT_ELEM_PROP_1: Ooogle 1-0, EXT_ELEM_PROP_2: Ooogle 2-0, EXT_ELEM_PROP_3: Ooogle 3-0, EXT_ELEM_PROP_4: Ooogle 4-0, EXT_ELEM_PROP_5: Ooogle 5-0} + +ELEM_PROP_1: 0.101 +ELEM_PROP_2: 669 +ELEM_PROP_3: 0.301 +ELEM_PROP_4: 815 +ELEM_PROP_5: 661 +[ 1, 2, 3 ] +[ 11, 12, 13 ] +[ 21, 22, 23 ] +[ 31, 32, 33 ] +[ 41, 42, 43 ] +[ 511, 511, 511 ] +[ 511, 511, 511 ] + + +-------------------- + 1 +-------------------- +{EXT_ELEM_PROP_1: NaN, EXT_ELEM_PROP_2: NaN, EXT_ELEM_PROP_3: NaN, EXT_ELEM_PROP_4: NaN, EXT_ELEM_PROP_5: NaN} + +ELEM_PROP_1: 1003 +ELEM_PROP_2: 1003 +ELEM_PROP_3: 1003 +ELEM_PROP_4: 1003 +ELEM_PROP_5: 1003 +[ 511, 511, 511 ] +[ 511, 511, 511 ] +[ 511, 511, 511 ] +[ 511, 511, 511 ] +[ 511, 511, 511 ] +[ 511, 511, 511 ] +[ 511, 511, 511 ] + + + +set.prop(PROP_4): 4.401 + + +------------------------------------- + 30 MODFICATIONS +------------------------------------- + +PROP_1: 1.101 +PROP_2: 2.201 +PROP_4: 4.401 +PROP_5: 5.501 +PROP_6: 984 +PROP_7: 434 +PROP_9: 419 + +-------------------- + 0 +-------------------- +{EXT_ELEM_PROP_1: Ooogle 1-0, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_2: Ooogle 2-0, EXT_ELEM_PROP_3: Ooogle 3-0, EXT_ELEM_PROP_4: Ooogle 4-0, EXT_ELEM_PROP_5: Ooogle 5-0, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +ELEM_PROP_1: 0.101 +ELEM_PROP_2: 669 +ELEM_PROP_3: 0.301 +ELEM_PROP_4: 734 +ELEM_PROP_5: 661 +[ 1, 2, 3 ] +[ 11, 12, 13 ] +[ 21, 22, 23 ] +[ 31, 32, 33 ] +[ 41, 42, 43 ] +[ 511, 511, 511 ] +[ 511, 511, 511 ] +[ 886, 886, 886 ] + + +-------------------- + 1 +-------------------- +{EXT_ELEM_PROP_1: NaN, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_2: NaN, EXT_ELEM_PROP_3: NaN, EXT_ELEM_PROP_4: NaN, EXT_ELEM_PROP_5: NaN, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +ELEM_PROP_1: 1003 +ELEM_PROP_2: 1003 +ELEM_PROP_3: 1003 +ELEM_PROP_4: 734 +ELEM_PROP_5: 1003 +[ 511, 511, 511 ] +[ 511, 511, 511 ] +[ 511, 511, 511 ] +[ 511, 511, 511 ] +[ 511, 511, 511 ] +[ 511, 511, 511 ] +[ 511, 511, 511 ] +[ 886, 886, 886 ] + + +-------------------- + 2 +-------------------- +{EXT_ELEM_PROP_1: NaN, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_2: NaN, EXT_ELEM_PROP_3: NaN, EXT_ELEM_PROP_4: NaN, EXT_ELEM_PROP_5: NaN, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +ELEM_PROP_1: 1009 +ELEM_PROP_2: 1009 +ELEM_PROP_3: 1009 +ELEM_PROP_4: 734 +ELEM_PROP_5: 1009 +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 886, 886, 886 ] + + + +set.num_extend_elem_props(): 10 +set.num_props(): 7 +set.num_extend_elem_props(): 10 + + +------------------------------------- + 35 MODFICATIONS +------------------------------------- + +PROP_1: 1.101 +PROP_2: 2.201 +PROP_4: 4.401 +PROP_5: 5.501 +PROP_6: 984 +PROP_7: 434 +PROP_9: 419 + +-------------------- + 0 +-------------------- +{EXT_ELEM_PROP_1: Ooogle 1-0, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_2: Ooogle 2-0, EXT_ELEM_PROP_3: 733, EXT_ELEM_PROP_4: Ooogle 4-0, EXT_ELEM_PROP_5: Ooogle 5-0, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +ELEM_PROP_1: 0.101 +ELEM_PROP_2: 669 +ELEM_PROP_4: 734 +ELEM_PROP_5: 661 +[ 1, 2, 3 ] +[ 11, 12, 13 ] +[ 21, 22, 23 ] +[ 31, 32, 33 ] +[ 41, 42, 43 ] +[ 511, 511, 511 ] +[ 511, 511, 511 ] +[ 886, 886, 886 ] + + +-------------------- + 1 +-------------------- +{EXT_ELEM_PROP_1: NaN, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_2: NaN, EXT_ELEM_PROP_3: NaN, EXT_ELEM_PROP_4: NaN, EXT_ELEM_PROP_5: NaN, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +ELEM_PROP_1: 1006 +ELEM_PROP_2: 1006 +ELEM_PROP_4: 1006 +ELEM_PROP_5: 1006 +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] + + +-------------------- + 2 +-------------------- +{EXT_ELEM_PROP_1: NaN, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_2: NaN, EXT_ELEM_PROP_3: NaN, EXT_ELEM_PROP_4: NaN, EXT_ELEM_PROP_5: NaN, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +ELEM_PROP_1: 1005 +ELEM_PROP_2: 1005 +ELEM_PROP_4: 1005 +ELEM_PROP_5: 1005 +[ 1005, 1005, 1005 ] +[ 1005, 1005, 1005 ] +[ 1005, 1005, 1005 ] +[ 1005, 1005, 1005 ] +[ 1005, 1005, 1005 ] +[ 1005, 1005, 1005 ] +[ 1005, 1005, 1005 ] +[ 1005, 1005, 1005 ] + + +-------------------- + 3 +-------------------- +{EXT_ELEM_PROP_1: NaN, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_2: NaN, EXT_ELEM_PROP_3: NaN, EXT_ELEM_PROP_4: NaN, EXT_ELEM_PROP_5: NaN, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +ELEM_PROP_1: 1003 +ELEM_PROP_2: 1003 +ELEM_PROP_4: 734 +ELEM_PROP_5: 1003 +[ 511, 511, 511 ] +[ 511, 511, 511 ] +[ 511, 511, 511 ] +[ 511, 511, 511 ] +[ 511, 511, 511 ] +[ 511, 511, 511 ] +[ 511, 511, 511 ] +[ 886, 886, 886 ] + + +-------------------- + 4 +-------------------- +{EXT_ELEM_PROP_1: NaN, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_2: NaN, EXT_ELEM_PROP_3: NaN, EXT_ELEM_PROP_4: NaN, EXT_ELEM_PROP_5: NaN, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +ELEM_PROP_1: 1009 +ELEM_PROP_2: 1009 +ELEM_PROP_4: 734 +ELEM_PROP_5: 1009 +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 886, 886, 886 ] + + + +set.prop(PROP_7): 434 + + +------------------------------------- + 40 MODFICATIONS +------------------------------------- + +PROP_1: 1.101 +PROP_2: 2.201 +PROP_4: 4.401 +PROP_5: 5.501 +PROP_6: 984 +PROP_7: 434 +PROP_9: 419 + +-------------------- + 0 +-------------------- +{EXT_ELEM_PROP_1: NaN, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_2: NaN, EXT_ELEM_PROP_3: NaN, EXT_ELEM_PROP_4: NaN, EXT_ELEM_PROP_5: NaN, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +ELEM_PROP_1: 1006 +ELEM_PROP_2: 1006 +ELEM_PROP_4: 1006 +ELEM_PROP_5: 1006 +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] + + +-------------------- + 1 +-------------------- +{EXT_ELEM_PROP_1: NaN, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_2: NaN, EXT_ELEM_PROP_3: NaN, EXT_ELEM_PROP_4: NaN, EXT_ELEM_PROP_5: NaN, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +ELEM_PROP_1: 1009 +ELEM_PROP_2: 1009 +ELEM_PROP_4: 734 +ELEM_PROP_5: 1009 +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 886, 886, 886 ] + + + +set.num_props(): 7 +set.get_extend_elem_prop(EXT_ELEM_PROP_9,0): NaN +set.has_elem_prop(ELEM_PROP_9): 0 + + +------------------------------------- + 45 MODFICATIONS +------------------------------------- + +PROP_1: 1.101 +PROP_2: 2.201 +PROP_4: 4.401 +PROP_5: 5.501 +PROP_6: 984 +PROP_7: 434 +PROP_9: 419 + +-------------------- + 0 +-------------------- +{EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_2: NaN, EXT_ELEM_PROP_3: NaN, EXT_ELEM_PROP_4: NaN, EXT_ELEM_PROP_5: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +ELEM_PROP_1: 1006 +ELEM_PROP_2: 1006 +ELEM_PROP_4: 1006 +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] + + +-------------------- + 1 +-------------------- +{EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_2: NaN, EXT_ELEM_PROP_3: NaN, EXT_ELEM_PROP_4: NaN, EXT_ELEM_PROP_5: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +ELEM_PROP_1: 1009 +ELEM_PROP_2: 1009 +ELEM_PROP_4: 734 +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 886, 886, 886 ] + + + +set.vsize(): 61 +set.elem_prop_index(ELEM_PROP_4): 1 +set.vsize(): 59 + + +------------------------------------- + 50 MODFICATIONS +------------------------------------- + +PROP_1: 1.101 +PROP_2: 2.201 +PROP_4: 4.401 +PROP_5: 5.501 +PROP_6: 984 +PROP_7: 434 +PROP_9: 419 + +-------------------- + 0 +-------------------- +{EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_3: NaN, EXT_ELEM_PROP_4: NaN, EXT_ELEM_PROP_5: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_9: NaN} + +ELEM_PROP_2: 1006 +ELEM_PROP_4: 1006 +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] + + +-------------------- + 1 +-------------------- +{EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_3: NaN, EXT_ELEM_PROP_4: NaN, EXT_ELEM_PROP_5: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_9: NaN} + +ELEM_PROP_2: 1009 +ELEM_PROP_4: 734 +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 886, 886, 886 ] + + +-------------------- + 2 +-------------------- +{EXT_ELEM_PROP_10: -99, EXT_ELEM_PROP_3: NaN, EXT_ELEM_PROP_4: NaN, EXT_ELEM_PROP_5: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_9: NaN} + +ELEM_PROP_2: 1008 +ELEM_PROP_4: 1008 +[ 1008, 1008, 1008 ] +[ 1008, 1008, 1008 ] +[ 1008, 1008, 1008 ] +[ 1008, 1008, 1008 ] +[ 1008, 1008, 1008 ] +[ 1008, 1008, 1008 ] +[ 1008, 1008, 1008 ] +[ 1008, 1008, 1008 ] + + + + + +------------------------------------- + 55 MODFICATIONS +------------------------------------- + +PROP_1: 1.101 +PROP_2: 2.201 +PROP_4: 4.401 +PROP_5: 5.501 +PROP_6: 984 +PROP_7: 434 +PROP_9: 419 + +-------------------- + 0 +-------------------- +{EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_3: NaN, EXT_ELEM_PROP_4: NaN, EXT_ELEM_PROP_5: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_9: NaN} + +ELEM_PROP_2: 1006 +ELEM_PROP_4: 776 +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] + + +-------------------- + 1 +-------------------- +{EXT_ELEM_PROP_10: Boogle 10-1, EXT_ELEM_PROP_3: NaN, EXT_ELEM_PROP_4: NaN, EXT_ELEM_PROP_5: NaN, EXT_ELEM_PROP_7: Boogle 7-1, EXT_ELEM_PROP_9: Boogle 9-1} + +ELEM_PROP_2: 1009 +ELEM_PROP_4: 776 +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] + + +-------------------- + 2 +-------------------- +{EXT_ELEM_PROP_10: 11.031, EXT_ELEM_PROP_3: 3.331, EXT_ELEM_PROP_4: 4.431, EXT_ELEM_PROP_5: 5.531, EXT_ELEM_PROP_7: 7.731, EXT_ELEM_PROP_9: 9.931} + +ELEM_PROP_2: 1009 +ELEM_PROP_4: 1009 +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] + + + +set.size(): 3 +set.num_props(): 7 +set.num_extend_elem_props(): 7 +set.has_elem_prop(ELEM_PROP_7): 0 + + +------------------------------------- + 60 MODFICATIONS +------------------------------------- + +PROP_1: 1.101 +PROP_2: 2.201 +PROP_4: 4.401 +PROP_5: 5.501 +PROP_6: 984 +PROP_7: 434 +PROP_9: 419 + +-------------------- + 0 +-------------------- +{EXT_ELEM_PROP_10: 11.011, EXT_ELEM_PROP_3: 3.311, EXT_ELEM_PROP_4: 4.411, EXT_ELEM_PROP_5: 5.511, EXT_ELEM_PROP_7: 7.711, EXT_ELEM_PROP_8: 8.811, EXT_ELEM_PROP_9: 9.911} + +ELEM_PROP_2: 1005 +ELEM_PROP_4: 1005 +[ 1005, 1005, 1005 ] +[ 1005, 1005, 1005 ] + + +-------------------- + 1 +-------------------- +{EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_3: NaN, EXT_ELEM_PROP_4: NaN, EXT_ELEM_PROP_5: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: -99, EXT_ELEM_PROP_9: NaN} + +ELEM_PROP_2: 1006 +ELEM_PROP_4: 776 +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] + + +-------------------- + 2 +-------------------- +{EXT_ELEM_PROP_10: Boogle 10-1, EXT_ELEM_PROP_3: NaN, EXT_ELEM_PROP_4: NaN, EXT_ELEM_PROP_5: NaN, EXT_ELEM_PROP_7: Boogle 7-1, EXT_ELEM_PROP_8: -99, EXT_ELEM_PROP_9: Boogle 9-1} + +ELEM_PROP_2: 1009 +ELEM_PROP_4: 776 +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] + + +-------------------- + 3 +-------------------- +{EXT_ELEM_PROP_10: 11.031, EXT_ELEM_PROP_3: 3.331, EXT_ELEM_PROP_4: 4.431, EXT_ELEM_PROP_5: 5.531, EXT_ELEM_PROP_7: 7.731, EXT_ELEM_PROP_8: -99, EXT_ELEM_PROP_9: 9.931} + +ELEM_PROP_2: 1009 +ELEM_PROP_4: 1009 +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] + + +-------------------- + 4 +-------------------- +{EXT_ELEM_PROP_10: -99, EXT_ELEM_PROP_3: NaN, EXT_ELEM_PROP_4: NaN, EXT_ELEM_PROP_5: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: -99, EXT_ELEM_PROP_9: NaN} + +ELEM_PROP_2: 1003 +ELEM_PROP_4: 1003 +[ 1003, 1003, 1003 ] +[ 1003, 1003, 1003 ] + + + +set.get_extend_elem_prop(EXT_ELEM_PROP_3,3): 3.331 +set.num_elem_props(): 2 +set.vsize(): 42 + + +------------------------------------- + 65 MODFICATIONS +------------------------------------- + +PROP_1: 1.101 +PROP_2: 2.201 +PROP_4: 4.401 +PROP_5: 5.501 +PROP_6: 984 +PROP_7: 434 +PROP_9: 419 + +-------------------- + 0 +-------------------- +{EXT_ELEM_PROP_10: 11.011, EXT_ELEM_PROP_3: 3.311, EXT_ELEM_PROP_4: 4.411, EXT_ELEM_PROP_5: 5.511, EXT_ELEM_PROP_7: 7.711, EXT_ELEM_PROP_8: 8.811, EXT_ELEM_PROP_9: 9.911} + +[ 1005, 1005, 1005 ] +[ 1005, 1005, 1005 ] + + +-------------------- + 1 +-------------------- +{EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_3: NaN, EXT_ELEM_PROP_4: NaN, EXT_ELEM_PROP_5: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: -99, EXT_ELEM_PROP_9: NaN} + +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] + + +-------------------- + 2 +-------------------- +{EXT_ELEM_PROP_10: Boogle 10-0, EXT_ELEM_PROP_3: NaN, EXT_ELEM_PROP_4: NaN, EXT_ELEM_PROP_5: NaN, EXT_ELEM_PROP_7: Boogle 7-0, EXT_ELEM_PROP_8: Boogle 8-0, EXT_ELEM_PROP_9: Boogle 9-0} + +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] + + +-------------------- + 3 +-------------------- +{EXT_ELEM_PROP_10: 11.031, EXT_ELEM_PROP_3: 3.331, EXT_ELEM_PROP_4: 4.431, EXT_ELEM_PROP_5: 5.531, EXT_ELEM_PROP_7: 7.731, EXT_ELEM_PROP_8: -99, EXT_ELEM_PROP_9: 9.931} + +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] + + +-------------------- + 4 +-------------------- +{EXT_ELEM_PROP_10: -99, EXT_ELEM_PROP_3: NaN, EXT_ELEM_PROP_4: NaN, EXT_ELEM_PROP_5: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: -99, EXT_ELEM_PROP_9: NaN} + +[ 1003, 1003, 1003 ] +[ 1003, 1003, 1003 ] + + + +set.get_extend_elem_prop_header(): [ EXT_ELEM_PROP_10 EXT_ELEM_PROP_3 EXT_ELEM_PROP_4 EXT_ELEM_PROP_5 EXT_ELEM_PROP_7 EXT_ELEM_PROP_8 EXT_ELEM_PROP_9 ] +set.prop_index(PROP_4): 2 +set.num_elem_props(): 0 +set.bsize(): 30 +set.has_extend_elem_prop(EXT_ELEM_PROP_3): 1 +set.num_extend_elem_props(): 6 +set.num_props(): 7 + + +------------------------------------- + 70 MODFICATIONS +------------------------------------- + +PROP_1: 1.101 +PROP_2: 2.201 +PROP_4: 4.401 +PROP_5: 5.501 +PROP_6: 984 +PROP_7: 434 +PROP_9: 419 + +-------------------- + 0 +-------------------- +{EXT_ELEM_PROP_10: 11.011, EXT_ELEM_PROP_3: 3.311, EXT_ELEM_PROP_4: 4.411, EXT_ELEM_PROP_5: 5.511, EXT_ELEM_PROP_8: 8.811, EXT_ELEM_PROP_9: 9.911} + +[ 1005, 1005, 1005 ] +[ 1005, 1005, 1005 ] + + +-------------------- + 1 +-------------------- +{EXT_ELEM_PROP_10: 11.011, EXT_ELEM_PROP_3: 3.311, EXT_ELEM_PROP_4: 4.411, EXT_ELEM_PROP_5: 5.511, EXT_ELEM_PROP_8: 8.811, EXT_ELEM_PROP_9: 9.911} + +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] + + +-------------------- + 2 +-------------------- +{EXT_ELEM_PROP_10: Boogle 10-0, EXT_ELEM_PROP_3: NaN, EXT_ELEM_PROP_4: NaN, EXT_ELEM_PROP_5: NaN, EXT_ELEM_PROP_8: Boogle 8-0, EXT_ELEM_PROP_9: Boogle 9-0} + +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] + + +-------------------- + 3 +-------------------- +{EXT_ELEM_PROP_10: 11.031, EXT_ELEM_PROP_3: 3.331, EXT_ELEM_PROP_4: 4.431, EXT_ELEM_PROP_5: 5.531, EXT_ELEM_PROP_8: -99, EXT_ELEM_PROP_9: 9.931} + +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] + + +-------------------- + 4 +-------------------- +{EXT_ELEM_PROP_10: -99, EXT_ELEM_PROP_3: NaN, EXT_ELEM_PROP_4: NaN, EXT_ELEM_PROP_5: NaN, EXT_ELEM_PROP_8: -99, EXT_ELEM_PROP_9: NaN} + +[ 1003, 1003, 1003 ] +[ 1003, 1003, 1003 ] + + + +set.has_extend_elem_prop(EXT_ELEM_PROP_8): 1 +set.vsize(): 55 + + +------------------------------------- + 75 MODFICATIONS +------------------------------------- + +PROP_1: 1.101 +PROP_2: 2.201 +PROP_4: 4.401 +PROP_5: 5.501 +PROP_6: 984 +PROP_7: 434 +PROP_9: 419 + +-------------------- + 0 +-------------------- +{EXT_ELEM_PROP_10: 11.011, EXT_ELEM_PROP_3: 3.311, EXT_ELEM_PROP_4: 4.411, EXT_ELEM_PROP_5: 5.511, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: 8.811, EXT_ELEM_PROP_9: 9.911} + +[ 1005, 1005, 1005 ] +[ 1005, 1005, 1005 ] + + +-------------------- + 1 +-------------------- +{EXT_ELEM_PROP_10: 11.011, EXT_ELEM_PROP_3: 3.311, EXT_ELEM_PROP_4: 4.411, EXT_ELEM_PROP_5: 5.511, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: 8.811, EXT_ELEM_PROP_9: 9.911} + +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] + + +-------------------- + 2 +-------------------- +{EXT_ELEM_PROP_10: Boogle 10-4, EXT_ELEM_PROP_3: NaN, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: NaN, EXT_ELEM_PROP_6: Boogle 6-4, EXT_ELEM_PROP_7: Boogle 7-4, EXT_ELEM_PROP_8: Boogle 8-4, EXT_ELEM_PROP_9: Boogle 9-4} + +[ 1008, 1008, 1008 ] +[ 1008, 1008, 1008 ] +[ 1008, 1008, 1008 ] +[ 1008, 1008, 1008 ] +[ 1008, 1008, 1008 ] +[ 1008, 1008, 1008 ] + + +-------------------- + 3 +-------------------- +{EXT_ELEM_PROP_10: Boogle 10-0, EXT_ELEM_PROP_3: NaN, EXT_ELEM_PROP_4: NaN, EXT_ELEM_PROP_5: NaN, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: Boogle 8-0, EXT_ELEM_PROP_9: Boogle 9-0} + +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] + + +-------------------- + 4 +-------------------- +{EXT_ELEM_PROP_10: 11.031, EXT_ELEM_PROP_3: 3.331, EXT_ELEM_PROP_4: 4.431, EXT_ELEM_PROP_5: 5.531, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: -99, EXT_ELEM_PROP_9: 9.931} + +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] + + +-------------------- + 5 +-------------------- +{EXT_ELEM_PROP_10: Boogle 10-3, EXT_ELEM_PROP_3: NaN, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: NaN, EXT_ELEM_PROP_6: Boogle 6-3, EXT_ELEM_PROP_7: Boogle 7-3, EXT_ELEM_PROP_8: Boogle 8-3, EXT_ELEM_PROP_9: Boogle 9-3} + +[ 1003, 1003, 1003 ] +[ 1003, 1003, 1003 ] + + + +set.num_props(): 7 + + +------------------------------------- + 80 MODFICATIONS +------------------------------------- + +PROP_1: 1.101 +PROP_2: 2.201 +PROP_4: 4.401 +PROP_5: 5.501 +PROP_6: 984 +PROP_7: 434 +PROP_8: 140 +PROP_9: 419 + +-------------------- + 0 +-------------------- +{EXT_ELEM_PROP_10: 11.011, EXT_ELEM_PROP_3: 3.311, EXT_ELEM_PROP_4: 4.411, EXT_ELEM_PROP_5: 5.511, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: 8.811, EXT_ELEM_PROP_9: 9.911} + +[ 1005, 1005, 1005 ] +[ 1005, 1005, 1005 ] + + +-------------------- + 1 +-------------------- +{EXT_ELEM_PROP_10: 11.011, EXT_ELEM_PROP_3: 3.311, EXT_ELEM_PROP_4: 4.411, EXT_ELEM_PROP_5: 5.511, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: 8.811, EXT_ELEM_PROP_9: 9.911} + +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] + + +-------------------- + 2 +-------------------- +{EXT_ELEM_PROP_10: Boogle 10-4, EXT_ELEM_PROP_3: NaN, EXT_ELEM_PROP_4: 138, EXT_ELEM_PROP_5: NaN, EXT_ELEM_PROP_6: Boogle 6-4, EXT_ELEM_PROP_7: Boogle 7-4, EXT_ELEM_PROP_8: Boogle 8-4, EXT_ELEM_PROP_9: Boogle 9-4} + +[ 1008, 1008, 1008 ] +[ 1008, 1008, 1008 ] +[ 1008, 1008, 1008 ] +[ 1008, 1008, 1008 ] +[ 1008, 1008, 1008 ] +[ 1008, 1008, 1008 ] + + +-------------------- + 3 +-------------------- +{EXT_ELEM_PROP_10: Boogle 10-0, EXT_ELEM_PROP_3: NaN, EXT_ELEM_PROP_4: NaN, EXT_ELEM_PROP_5: NaN, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: Boogle 8-0, EXT_ELEM_PROP_9: Boogle 9-0} + +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] + + +-------------------- + 4 +-------------------- +{EXT_ELEM_PROP_10: 11.031, EXT_ELEM_PROP_3: 3.331, EXT_ELEM_PROP_4: 4.431, EXT_ELEM_PROP_5: 5.531, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: -99, EXT_ELEM_PROP_9: 9.931} + +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] + + +-------------------- + 5 +-------------------- +{EXT_ELEM_PROP_10: 11.061, EXT_ELEM_PROP_3: 3.361, EXT_ELEM_PROP_4: 4.461, EXT_ELEM_PROP_5: 5.561, EXT_ELEM_PROP_6: 6.661, EXT_ELEM_PROP_7: 7.761, EXT_ELEM_PROP_8: 8.861, EXT_ELEM_PROP_9: 9.961} + +[ 1003, 1003, 1003 ] +[ 1003, 1003, 1003 ] + + + +set.get_extend_elem_prop_header(): [ EXT_ELEM_PROP_10 EXT_ELEM_PROP_3 EXT_ELEM_PROP_4 EXT_ELEM_PROP_5 EXT_ELEM_PROP_6 EXT_ELEM_PROP_7 EXT_ELEM_PROP_8 EXT_ELEM_PROP_9 ] + + +------------------------------------- + 85 MODFICATIONS +------------------------------------- + +PROP_1: 1.101 +PROP_2: 2.201 +PROP_4: 4.401 +PROP_6: 984 +PROP_7: 434 +PROP_8: 140 +PROP_9: 419 + +-------------------- + 0 +-------------------- +{EXT_ELEM_PROP_10: 11.011, EXT_ELEM_PROP_2: -99, EXT_ELEM_PROP_3: 3.311, EXT_ELEM_PROP_4: 4.411, EXT_ELEM_PROP_5: 5.511, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: 8.811, EXT_ELEM_PROP_9: 9.911} + +[ 1005, 1005, 1005 ] +[ 1005, 1005, 1005 ] + + +-------------------- + 1 +-------------------- +{EXT_ELEM_PROP_10: 11.011, EXT_ELEM_PROP_2: -99, EXT_ELEM_PROP_3: 3.311, EXT_ELEM_PROP_4: 4.411, EXT_ELEM_PROP_5: 5.511, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: 8.811, EXT_ELEM_PROP_9: 9.911} + +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] + + +-------------------- + 2 +-------------------- +{EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_2: -99, EXT_ELEM_PROP_3: NaN, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: NaN, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 1003, 1003, 1003 ] + + +-------------------- + 3 +-------------------- +{EXT_ELEM_PROP_10: Boogle 10-4, EXT_ELEM_PROP_2: -99, EXT_ELEM_PROP_3: NaN, EXT_ELEM_PROP_4: 138, EXT_ELEM_PROP_5: 667, EXT_ELEM_PROP_6: Boogle 6-4, EXT_ELEM_PROP_7: Boogle 7-4, EXT_ELEM_PROP_8: Boogle 8-4, EXT_ELEM_PROP_9: Boogle 9-4} + +[ 1008, 1008, 1008 ] +[ 1008, 1008, 1008 ] +[ 1008, 1008, 1008 ] +[ 1008, 1008, 1008 ] +[ 1008, 1008, 1008 ] +[ 1008, 1008, 1008 ] + + +-------------------- + 4 +-------------------- +{EXT_ELEM_PROP_10: Boogle 10-0, EXT_ELEM_PROP_2: -99, EXT_ELEM_PROP_3: NaN, EXT_ELEM_PROP_4: NaN, EXT_ELEM_PROP_5: NaN, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: Boogle 8-0, EXT_ELEM_PROP_9: Boogle 9-0} + +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] + + +-------------------- + 5 +-------------------- +{EXT_ELEM_PROP_10: 11.031, EXT_ELEM_PROP_2: -99, EXT_ELEM_PROP_3: 3.331, EXT_ELEM_PROP_4: 4.431, EXT_ELEM_PROP_5: 5.531, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: -99, EXT_ELEM_PROP_9: 9.931} + +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] + + +-------------------- + 6 +-------------------- +{EXT_ELEM_PROP_10: 11.061, EXT_ELEM_PROP_2: -99, EXT_ELEM_PROP_3: 3.361, EXT_ELEM_PROP_4: 4.461, EXT_ELEM_PROP_5: 5.561, EXT_ELEM_PROP_6: 6.661, EXT_ELEM_PROP_7: 7.761, EXT_ELEM_PROP_8: 8.861, EXT_ELEM_PROP_9: 9.961} + +[ 1003, 1003, 1003 ] +[ 1003, 1003, 1003 ] + + + +set.num_extend_elem_props(): 8 + + +------------------------------------- + 90 MODFICATIONS +------------------------------------- + +PROP_1: 1.101 +PROP_2: 2.201 +PROP_4: 4.401 +PROP_6: 984 +PROP_7: 434 +PROP_8: 140 +PROP_9: 419 + +-------------------- + 0 +-------------------- +{EXT_ELEM_PROP_10: 11.011, EXT_ELEM_PROP_2: -99, EXT_ELEM_PROP_3: 3.311, EXT_ELEM_PROP_4: 4.411, EXT_ELEM_PROP_5: 5.511, EXT_ELEM_PROP_6: -99, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: 8.811, EXT_ELEM_PROP_9: 9.911} + +[ 1005, 1005, 1005 ] +[ 1005, 1005, 1005 ] + + + +set.elem_prop_keys(): [] +set.get_extend_elem_prop_header(): [ EXT_ELEM_PROP_10 EXT_ELEM_PROP_2 EXT_ELEM_PROP_3 EXT_ELEM_PROP_4 EXT_ELEM_PROP_5 EXT_ELEM_PROP_6 EXT_ELEM_PROP_7 EXT_ELEM_PROP_8 EXT_ELEM_PROP_9 ] + + +------------------------------------- + 95 MODFICATIONS +------------------------------------- + +PROP_1: 1.101 +PROP_2: 2.201 +PROP_6: 984 +PROP_7: 434 +PROP_8: 140 +PROP_9: 419 + + +set.num_extend_elem_props(): 7 +set.vsize(): 32 +set.prop_index(PROP_9): 7 +set.num_extend_elem_props(): 7 + + +------------------------------------- + 100 MODFICATIONS +------------------------------------- + +PROP_1: 1.101 +PROP_10: 182 +PROP_2: 2.201 +PROP_4: 779 +PROP_5: 902 +PROP_6: 984 +PROP_7: 434 +PROP_8: 140 +PROP_9: 419 + +-------------------- + 0 +-------------------- +{EXT_ELEM_PROP_10: 11.031, EXT_ELEM_PROP_2: 2.231, EXT_ELEM_PROP_3: 3.331, EXT_ELEM_PROP_4: 4.431, EXT_ELEM_PROP_6: 6.631, EXT_ELEM_PROP_7: 7.731, EXT_ELEM_PROP_8: 8.831} + +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] + + + +set.prop_keys(): [ PROP_1 PROP_10 PROP_2 PROP_4 PROP_5 PROP_6 PROP_7 PROP_8 PROP_9 ] +set.has_extend_elem_prop(EXT_ELEM_PROP_2): 1 +set.num_elem_props(): 0 +set.has_extend_elem_prop(EXT_ELEM_PROP_10): 1 +set.num_props(): 10 +set.get_extend_elem_prop(EXT_ELEM_PROP_10,2): NaN + + +------------------------------------- + 105 MODFICATIONS +------------------------------------- + +PROP_1: 1.101 +PROP_10: 182 +PROP_2: 2.201 +PROP_3: 22 +PROP_4: 779 +PROP_5: 902 +PROP_6: 984 +PROP_7: 434 +PROP_8: 140 +PROP_9: 419 + +-------------------- + 0 +-------------------- +{EXT_ELEM_PROP_10: 11.031, EXT_ELEM_PROP_2: 2.231, EXT_ELEM_PROP_3: 3.331, EXT_ELEM_PROP_4: 4.431, EXT_ELEM_PROP_6: 6.631, EXT_ELEM_PROP_7: 7.731, EXT_ELEM_PROP_8: 308} + +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] + + + +set.get_extend_elem_prop(EXT_ELEM_PROP_3,0): 3.331 +set.prop_keys(): [ PROP_1 PROP_10 PROP_2 PROP_3 PROP_4 PROP_5 PROP_6 PROP_7 PROP_8 PROP_9 ] +set.size(): 2 +set.num_extend_elem_props(): 7 +set.prop(PROP_1): 1.101 +set.size(): 2 +set.bsize(): 48 +set.elem_prop_keys(): [] + + +------------------------------------- + 110 MODFICATIONS +------------------------------------- + +PROP_1: 1.101 +PROP_10: 182 +PROP_2: 2.201 +PROP_3: 22 +PROP_4: 779 +PROP_5: 902 +PROP_6: 984 +PROP_7: 434 +PROP_8: 140 +PROP_9: 419 + +-------------------- + 0 +-------------------- +{EXT_ELEM_PROP_10: 11.031, EXT_ELEM_PROP_2: 2.231, EXT_ELEM_PROP_3: 3.331, EXT_ELEM_PROP_4: 4.431, EXT_ELEM_PROP_6: 6.631, EXT_ELEM_PROP_7: 7.731, EXT_ELEM_PROP_8: 308} + +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 179, 179, 179 ] + + +-------------------- + 1 +-------------------- +{EXT_ELEM_PROP_10: 11.051, EXT_ELEM_PROP_2: 2.251, EXT_ELEM_PROP_3: 3.351, EXT_ELEM_PROP_4: 4.451, EXT_ELEM_PROP_6: 6.651, EXT_ELEM_PROP_7: 7.751, EXT_ELEM_PROP_8: 8.851} + +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] +[ 179, 179, 179 ] + + + +set.get_extend_elem_prop(EXT_ELEM_PROP_10,1): 11.051 +set.bsize(): 54 +set.prop(PROP_3): 22 +set.num_extend_elem_props(): 7 +set.num_extend_elem_props(): 7 +set.num_props(): 10 + + +------------------------------------- + 115 MODFICATIONS +------------------------------------- + +PROP_1: 1.101 +PROP_10: 182 +PROP_3: 22 +PROP_4: 779 +PROP_5: 902 +PROP_6: 984 +PROP_7: 434 +PROP_8: 140 +PROP_9: 419 + +-------------------- + 0 +-------------------- +{EXT_ELEM_PROP_10: 11.051, EXT_ELEM_PROP_2: 2.251, EXT_ELEM_PROP_3: 3.351, EXT_ELEM_PROP_4: 4.451, EXT_ELEM_PROP_6: 6.651, EXT_ELEM_PROP_7: 7.751, EXT_ELEM_PROP_8: 8.851} + +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] +[ 179, 179, 179 ] + + +-------------------- + 1 +-------------------- +{EXT_ELEM_PROP_10: 11.041, EXT_ELEM_PROP_2: 2.241, EXT_ELEM_PROP_3: 3.341, EXT_ELEM_PROP_4: 4.441, EXT_ELEM_PROP_6: 6.641, EXT_ELEM_PROP_7: 7.741, EXT_ELEM_PROP_8: 8.841} + +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] + + +-------------------- + 2 +-------------------- +{EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_2: -99, EXT_ELEM_PROP_3: NaN, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_6: -99, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: -99} + +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] + + + +set.elem_prop_keys(): [] + + +------------------------------------- + 120 MODFICATIONS +------------------------------------- + +PROP_1: 1.101 +PROP_10: 182 +PROP_3: 22 +PROP_4: 779 +PROP_5: 902 +PROP_6: 984 +PROP_7: 434 +PROP_8: 140 +PROP_9: 419 + +-------------------- + 0 +-------------------- +{EXT_ELEM_PROP_10: 11.041, EXT_ELEM_PROP_2: 2.241, EXT_ELEM_PROP_3: 3.341, EXT_ELEM_PROP_4: 4.441, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: 6.641, EXT_ELEM_PROP_7: 7.741, EXT_ELEM_PROP_8: 8.841} + +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] + + +-------------------- + 1 +-------------------- +{EXT_ELEM_PROP_10: Boogle 10-4, EXT_ELEM_PROP_2: -99, EXT_ELEM_PROP_3: NaN, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: Boogle 6-4, EXT_ELEM_PROP_7: Boogle 7-4, EXT_ELEM_PROP_8: Boogle 8-4} + +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] + + + +set.num_elem_props(): 0 +set.prop_index(PROP_10): 1 +set.size(): 2 + + +------------------------------------- + 125 MODFICATIONS +------------------------------------- + +PROP_1: 1.101 +PROP_10: 182 +PROP_3: 22 +PROP_4: 779 +PROP_5: 902 +PROP_6: 984 +PROP_7: 434 +PROP_9: 419 + +-------------------- + 0 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: 11.041, EXT_ELEM_PROP_2: 2.241, EXT_ELEM_PROP_3: 3.341, EXT_ELEM_PROP_4: 4.441, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: 6.641, EXT_ELEM_PROP_8: 8.841} + +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] + + +-------------------- + 1 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: Boogle 10-4, EXT_ELEM_PROP_2: -99, EXT_ELEM_PROP_3: NaN, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: Boogle 6-4, EXT_ELEM_PROP_8: Boogle 8-4} + +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] + + + +set.size(): 2 +set.get_extend_elem_prop(EXT_ELEM_PROP_2,0): 2.241 + + +------------------------------------- + 130 MODFICATIONS +------------------------------------- + +PROP_1: 1.101 +PROP_10: 182 +PROP_3: 22 +PROP_4: 779 +PROP_5: 902 +PROP_6: 984 +PROP_7: 434 +PROP_9: 419 + +-------------------- + 0 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: 11.041, EXT_ELEM_PROP_2: 2.241, EXT_ELEM_PROP_4: 4.441, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: 6.641, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: 8.841, EXT_ELEM_PROP_9: NaN} + +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] + + +-------------------- + 1 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_2: -99, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 1004, 1004, 1004 ] +[ 1004, 1004, 1004 ] +[ 1004, 1004, 1004 ] +[ 1004, 1004, 1004 ] +[ 1004, 1004, 1004 ] + + +-------------------- + 2 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: Boogle 10-4, EXT_ELEM_PROP_2: -99, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: Boogle 6-4, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: Boogle 8-4, EXT_ELEM_PROP_9: NaN} + +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] + + + +set.num_elem_props(): 0 +set.size(): 3 +set.num_elem_props(): 0 +set.elem_prop_keys(): [] + + +------------------------------------- + 135 MODFICATIONS +------------------------------------- + +PROP_1: 1.101 +PROP_10: 182 +PROP_3: 22 +PROP_4: 779 +PROP_5: 902 +PROP_6: 984 +PROP_7: 434 +PROP_9: 419 + +-------------------- + 0 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: 11.041, EXT_ELEM_PROP_2: 2.241, EXT_ELEM_PROP_4: 4.441, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: 6.641, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: 8.841, EXT_ELEM_PROP_9: NaN} + +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 192, 192, 192 ] +[ 192, 192, 192 ] +[ 192, 192, 192 ] + + +-------------------- + 1 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_2: -99, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 1010, 1010, 1010 ] +[ 1010, 1010, 1010 ] +[ 1010, 1010, 1010 ] +[ 1010, 1010, 1010 ] +[ 1010, 1010, 1010 ] +[ 1010, 1010, 1010 ] +[ 1010, 1010, 1010 ] + + +-------------------- + 2 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_2: -99, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 1004, 1004, 1004 ] +[ 1004, 1004, 1004 ] +[ 1004, 1004, 1004 ] +[ 1004, 1004, 1004 ] +[ 1004, 1004, 1004 ] +[ 192, 192, 192 ] +[ 192, 192, 192 ] + + +-------------------- + 3 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: Boogle 10-4, EXT_ELEM_PROP_2: -99, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: Boogle 6-4, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: Boogle 8-4, EXT_ELEM_PROP_9: NaN} + +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 192, 192, 192 ] +[ 192, 192, 192 ] +[ 192, 192, 192 ] + + +-------------------- + 4 +-------------------- +{EXT_ELEM_PROP_1: 1.141, EXT_ELEM_PROP_10: 11.041, EXT_ELEM_PROP_2: 2.241, EXT_ELEM_PROP_4: 4.441, EXT_ELEM_PROP_5: 5.541, EXT_ELEM_PROP_6: 6.641, EXT_ELEM_PROP_7: 7.741, EXT_ELEM_PROP_8: 8.841, EXT_ELEM_PROP_9: 9.941} + +[ 1008, 1008, 1008 ] +[ 1008, 1008, 1008 ] +[ 1008, 1008, 1008 ] +[ 1008, 1008, 1008 ] +[ 192, 192, 192 ] +[ 192, 192, 192 ] +[ 192, 192, 192 ] + + +-------------------- + 5 +-------------------- +{EXT_ELEM_PROP_1: 1.181, EXT_ELEM_PROP_10: 11.081, EXT_ELEM_PROP_2: 2.281, EXT_ELEM_PROP_4: 4.481, EXT_ELEM_PROP_5: 5.581, EXT_ELEM_PROP_6: 6.681, EXT_ELEM_PROP_7: 7.781, EXT_ELEM_PROP_8: 8.881, EXT_ELEM_PROP_9: 9.981} + +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 192, 192, 192 ] +[ 192, 192, 192 ] +[ 192, 192, 192 ] + + +-------------------- + 6 +-------------------- +{EXT_ELEM_PROP_1: 1.131, EXT_ELEM_PROP_10: 11.031, EXT_ELEM_PROP_2: 2.231, EXT_ELEM_PROP_4: 4.431, EXT_ELEM_PROP_5: 5.531, EXT_ELEM_PROP_6: 6.631, EXT_ELEM_PROP_7: 7.731, EXT_ELEM_PROP_8: 8.831, EXT_ELEM_PROP_9: 9.931} + +[ 1007, 1007, 1007 ] +[ 1007, 1007, 1007 ] +[ 1007, 1007, 1007 ] +[ 1007, 1007, 1007 ] +[ 1007, 1007, 1007 ] +[ 1007, 1007, 1007 ] +[ 192, 192, 192 ] + + + +set.prop(PROP_3): 22 +set.get_extend_elem_prop_header(): [ EXT_ELEM_PROP_1 EXT_ELEM_PROP_10 EXT_ELEM_PROP_2 EXT_ELEM_PROP_4 EXT_ELEM_PROP_5 EXT_ELEM_PROP_6 EXT_ELEM_PROP_7 EXT_ELEM_PROP_8 EXT_ELEM_PROP_9 ] +set.size(): 7 +set.has_elem_prop(ELEM_PROP_3): 0 +set.vsize(): 176 +set.bsize(): 168 +set.prop(PROP_5): 902 +set.has_extend_elem_prop(EXT_ELEM_PROP_4): 1 +set.bsize(): 168 + + +------------------------------------- + 140 MODFICATIONS +------------------------------------- + +PROP_1: 1.101 +PROP_10: 182 +PROP_3: 22 +PROP_4: 779 +PROP_5: 902 +PROP_6: 984 +PROP_7: 434 +PROP_9: 419 + +-------------------- + 0 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_2: -99, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] + + +-------------------- + 1 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: 11.041, EXT_ELEM_PROP_2: 2.241, EXT_ELEM_PROP_4: 4.441, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: 6.641, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: 8.841, EXT_ELEM_PROP_9: NaN} + +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 192, 192, 192 ] +[ 192, 192, 192 ] + + +-------------------- + 2 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_2: -99, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 1010, 1010, 1010 ] +[ 1010, 1010, 1010 ] +[ 1010, 1010, 1010 ] +[ 1010, 1010, 1010 ] +[ 1010, 1010, 1010 ] +[ 1010, 1010, 1010 ] + + +-------------------- + 3 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_2: -99, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 1004, 1004, 1004 ] +[ 1004, 1004, 1004 ] +[ 1004, 1004, 1004 ] +[ 1004, 1004, 1004 ] +[ 1004, 1004, 1004 ] +[ 192, 192, 192 ] + + +-------------------- + 4 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: Boogle 10-4, EXT_ELEM_PROP_2: -99, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: Boogle 6-4, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: Boogle 8-4, EXT_ELEM_PROP_9: NaN} + +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 192, 192, 192 ] +[ 192, 192, 192 ] + + +-------------------- + 5 +-------------------- +{EXT_ELEM_PROP_1: 1.141, EXT_ELEM_PROP_10: 11.041, EXT_ELEM_PROP_2: 2.241, EXT_ELEM_PROP_4: 4.441, EXT_ELEM_PROP_5: 5.541, EXT_ELEM_PROP_6: 6.641, EXT_ELEM_PROP_7: 7.741, EXT_ELEM_PROP_8: 8.841, EXT_ELEM_PROP_9: 9.941} + +[ 1008, 1008, 1008 ] +[ 1008, 1008, 1008 ] +[ 1008, 1008, 1008 ] +[ 1008, 1008, 1008 ] +[ 192, 192, 192 ] +[ 192, 192, 192 ] + + +-------------------- + 6 +-------------------- +{EXT_ELEM_PROP_1: 1.181, EXT_ELEM_PROP_10: 11.081, EXT_ELEM_PROP_2: 2.281, EXT_ELEM_PROP_4: 4.481, EXT_ELEM_PROP_5: 5.581, EXT_ELEM_PROP_6: 6.681, EXT_ELEM_PROP_7: 7.781, EXT_ELEM_PROP_8: 8.881, EXT_ELEM_PROP_9: 9.981} + +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 192, 192, 192 ] +[ 192, 192, 192 ] + + +-------------------- + 7 +-------------------- +{EXT_ELEM_PROP_1: 1.131, EXT_ELEM_PROP_10: 11.031, EXT_ELEM_PROP_2: 2.231, EXT_ELEM_PROP_4: 4.431, EXT_ELEM_PROP_5: 5.531, EXT_ELEM_PROP_6: 6.631, EXT_ELEM_PROP_7: 7.731, EXT_ELEM_PROP_8: 8.831, EXT_ELEM_PROP_9: 9.931} + +[ 1007, 1007, 1007 ] +[ 1007, 1007, 1007 ] +[ 1007, 1007, 1007 ] +[ 1007, 1007, 1007 ] +[ 1007, 1007, 1007 ] +[ 1007, 1007, 1007 ] + + + +set.get_extend_elem_prop_header(): [ EXT_ELEM_PROP_1 EXT_ELEM_PROP_10 EXT_ELEM_PROP_2 EXT_ELEM_PROP_4 EXT_ELEM_PROP_5 EXT_ELEM_PROP_6 EXT_ELEM_PROP_7 EXT_ELEM_PROP_8 EXT_ELEM_PROP_9 ] +set.num_extend_elem_props(): 9 +set.elem_prop_keys(): [] +set.prop_index(PROP_3): 2 + + +------------------------------------- + 145 MODFICATIONS +------------------------------------- + +PROP_1: 1.101 +PROP_10: 182 +PROP_3: 22 +PROP_4: 779 +PROP_5: 902 +PROP_6: 984 +PROP_7: 434 +PROP_9: 419 + +-------------------- + 0 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_2: -99, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] + + +-------------------- + 1 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: 11.041, EXT_ELEM_PROP_2: 2.241, EXT_ELEM_PROP_4: 4.441, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: 6.641, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: 8.841, EXT_ELEM_PROP_9: NaN} + +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 192, 192, 192 ] +[ 192, 192, 192 ] + + +-------------------- + 2 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_2: -99, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 1010, 1010, 1010 ] +[ 1010, 1010, 1010 ] +[ 1010, 1010, 1010 ] +[ 1010, 1010, 1010 ] +[ 1010, 1010, 1010 ] +[ 1010, 1010, 1010 ] + + +-------------------- + 3 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_2: -99, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 1004, 1004, 1004 ] +[ 1004, 1004, 1004 ] +[ 1004, 1004, 1004 ] +[ 1004, 1004, 1004 ] +[ 1004, 1004, 1004 ] +[ 192, 192, 192 ] + + +-------------------- + 4 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: Boogle 10-4, EXT_ELEM_PROP_2: -99, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: Boogle 6-4, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: Boogle 8-4, EXT_ELEM_PROP_9: NaN} + +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 192, 192, 192 ] +[ 192, 192, 192 ] + + +-------------------- + 5 +-------------------- +{EXT_ELEM_PROP_1: 1.141, EXT_ELEM_PROP_10: 11.041, EXT_ELEM_PROP_2: 2.241, EXT_ELEM_PROP_4: 4.441, EXT_ELEM_PROP_5: 5.541, EXT_ELEM_PROP_6: 6.641, EXT_ELEM_PROP_7: 7.741, EXT_ELEM_PROP_8: 8.841, EXT_ELEM_PROP_9: 9.941} + +[ 1008, 1008, 1008 ] +[ 1008, 1008, 1008 ] +[ 1008, 1008, 1008 ] +[ 1008, 1008, 1008 ] +[ 192, 192, 192 ] +[ 192, 192, 192 ] + + +-------------------- + 6 +-------------------- +{EXT_ELEM_PROP_1: 1.111, EXT_ELEM_PROP_10: 11.011, EXT_ELEM_PROP_2: 2.211, EXT_ELEM_PROP_4: 4.411, EXT_ELEM_PROP_5: 5.511, EXT_ELEM_PROP_6: 6.611, EXT_ELEM_PROP_7: 7.711, EXT_ELEM_PROP_8: 8.811, EXT_ELEM_PROP_9: 9.911} + +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 192, 192, 192 ] +[ 192, 192, 192 ] + + +-------------------- + 7 +-------------------- +{EXT_ELEM_PROP_1: 1.131, EXT_ELEM_PROP_10: 11.031, EXT_ELEM_PROP_2: 2.231, EXT_ELEM_PROP_4: 4.431, EXT_ELEM_PROP_5: 5.531, EXT_ELEM_PROP_6: 6.631, EXT_ELEM_PROP_7: 7.731, EXT_ELEM_PROP_8: 8.831, EXT_ELEM_PROP_9: 9.931} + +[ 1007, 1007, 1007 ] +[ 1007, 1007, 1007 ] +[ 1007, 1007, 1007 ] +[ 1007, 1007, 1007 ] +[ 1007, 1007, 1007 ] +[ 1007, 1007, 1007 ] + + +-------------------- + 8 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_2: -99, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 561, 561, 561 ] +[ 561, 561, 561 ] +[ 561, 561, 561 ] +[ 561, 561, 561 ] +[ 561, 561, 561 ] +[ 561, 561, 561 ] + + +-------------------- + 9 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_2: -99, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] + + + +set.num_props(): 8 + + +------------------------------------- + 150 MODFICATIONS +------------------------------------- + +PROP_1: 1.101 +PROP_10: 182 +PROP_3: 22 +PROP_4: 779 +PROP_5: 902 +PROP_6: 984 +PROP_7: 434 +PROP_9: 419 + +-------------------- + 0 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_2: -99, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] + + +-------------------- + 1 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: 11.041, EXT_ELEM_PROP_2: 2.241, EXT_ELEM_PROP_4: 4.441, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: 6.641, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: 8.841, EXT_ELEM_PROP_9: NaN} + +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 192, 192, 192 ] +[ 192, 192, 192 ] + + +-------------------- + 2 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_2: -99, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 1010, 1010, 1010 ] +[ 1010, 1010, 1010 ] +[ 1010, 1010, 1010 ] +[ 1010, 1010, 1010 ] +[ 1010, 1010, 1010 ] +[ 1010, 1010, 1010 ] + + +-------------------- + 3 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_2: -99, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 1004, 1004, 1004 ] +[ 1004, 1004, 1004 ] +[ 1004, 1004, 1004 ] +[ 1004, 1004, 1004 ] +[ 1004, 1004, 1004 ] +[ 192, 192, 192 ] + + +-------------------- + 4 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: Boogle 10-4, EXT_ELEM_PROP_2: -99, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: Boogle 6-4, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: Boogle 8-4, EXT_ELEM_PROP_9: NaN} + +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 192, 192, 192 ] +[ 192, 192, 192 ] + + +-------------------- + 5 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_2: -99, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] + + +-------------------- + 6 +-------------------- +{EXT_ELEM_PROP_1: 1.141, EXT_ELEM_PROP_10: 11.041, EXT_ELEM_PROP_2: 2.241, EXT_ELEM_PROP_4: 4.441, EXT_ELEM_PROP_5: 5.541, EXT_ELEM_PROP_6: 6.641, EXT_ELEM_PROP_7: 7.741, EXT_ELEM_PROP_8: 8.841, EXT_ELEM_PROP_9: 9.941} + +[ 1008, 1008, 1008 ] +[ 1008, 1008, 1008 ] +[ 1008, 1008, 1008 ] +[ 1008, 1008, 1008 ] +[ 192, 192, 192 ] +[ 192, 192, 192 ] + + +-------------------- + 7 +-------------------- +{EXT_ELEM_PROP_1: 1.111, EXT_ELEM_PROP_10: 11.011, EXT_ELEM_PROP_2: 2.211, EXT_ELEM_PROP_4: 4.411, EXT_ELEM_PROP_5: 5.511, EXT_ELEM_PROP_6: 6.611, EXT_ELEM_PROP_7: 7.711, EXT_ELEM_PROP_8: 8.811, EXT_ELEM_PROP_9: 9.911} + +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 192, 192, 192 ] +[ 192, 192, 192 ] + + +-------------------- + 8 +-------------------- +{EXT_ELEM_PROP_1: 1.131, EXT_ELEM_PROP_10: 11.031, EXT_ELEM_PROP_2: 2.231, EXT_ELEM_PROP_4: 4.431, EXT_ELEM_PROP_5: 5.531, EXT_ELEM_PROP_6: 6.631, EXT_ELEM_PROP_7: 7.731, EXT_ELEM_PROP_8: 8.831, EXT_ELEM_PROP_9: 9.931} + +[ 1007, 1007, 1007 ] +[ 1007, 1007, 1007 ] +[ 1007, 1007, 1007 ] +[ 1007, 1007, 1007 ] +[ 1007, 1007, 1007 ] +[ 1007, 1007, 1007 ] + + +-------------------- + 9 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_2: -99, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 561, 561, 561 ] +[ 561, 561, 561 ] +[ 561, 561, 561 ] +[ 561, 561, 561 ] +[ 561, 561, 561 ] +[ 561, 561, 561 ] + + +-------------------- + 10 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_2: -99, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] + + +-------------------- + 11 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_2: -99, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 1008, 1008, 1008 ] +[ 1008, 1008, 1008 ] +[ 1008, 1008, 1008 ] +[ 1008, 1008, 1008 ] +[ 1008, 1008, 1008 ] +[ 1008, 1008, 1008 ] + + +-------------------- + 12 +-------------------- +{EXT_ELEM_PROP_1: 1.151, EXT_ELEM_PROP_10: 11.051, EXT_ELEM_PROP_2: 2.251, EXT_ELEM_PROP_4: 4.451, EXT_ELEM_PROP_5: 5.551, EXT_ELEM_PROP_6: 6.651, EXT_ELEM_PROP_7: 7.751, EXT_ELEM_PROP_8: 8.851, EXT_ELEM_PROP_9: 9.951} + +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] + + + +set.elem_prop_keys(): [] +set.has_elem_prop(ELEM_PROP_10): 0 +set.vsize(): 242 +set.has_prop(PROP_8): 0 + + +------------------------------------- + 155 MODFICATIONS +------------------------------------- + +PROP_1: 1.101 +PROP_10: 182 +PROP_2: 692 +PROP_3: 22 +PROP_4: 779 +PROP_5: 902 +PROP_6: 984 +PROP_7: 434 +PROP_8: 147 +PROP_9: 419 + +-------------------- + 0 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_2: -99, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] + + +-------------------- + 1 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: 11.041, EXT_ELEM_PROP_2: 2.241, EXT_ELEM_PROP_4: 4.441, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: 6.641, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: 8.841, EXT_ELEM_PROP_9: NaN} + +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] + + +-------------------- + 2 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_2: -99, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 1010, 1010, 1010 ] +[ 1010, 1010, 1010 ] + + +-------------------- + 3 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_2: -99, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 1004, 1004, 1004 ] +[ 1004, 1004, 1004 ] + + +-------------------- + 4 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: Boogle 10-4, EXT_ELEM_PROP_2: -99, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: Boogle 6-4, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: Boogle 8-4, EXT_ELEM_PROP_9: NaN} + +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] + + +-------------------- + 5 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_2: -99, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 245, 245, 245 ] +[ 245, 245, 245 ] + + +-------------------- + 6 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_2: -99, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 245, 245, 245 ] +[ 245, 245, 245 ] + + +-------------------- + 7 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_2: -99, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 245, 245, 245 ] +[ 245, 245, 245 ] + + + +set.get_extend_elem_prop(EXT_ELEM_PROP_5,3): -99 + + +------------------------------------- + 160 MODFICATIONS +------------------------------------- + +PROP_1: 1.101 +PROP_10: 182 +PROP_2: 692 +PROP_3: 22 +PROP_4: 779 +PROP_5: 902 +PROP_6: 984 +PROP_7: 434 +PROP_8: 147 +PROP_9: 419 + +-------------------- + 0 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_2: 640, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] + + +-------------------- + 1 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: 11.041, EXT_ELEM_PROP_2: 2.241, EXT_ELEM_PROP_4: 4.441, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: 6.641, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] + + +-------------------- + 2 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_2: -99, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 1010, 1010, 1010 ] +[ 1010, 1010, 1010 ] + + +-------------------- + 3 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_2: -99, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 1004, 1004, 1004 ] +[ 1004, 1004, 1004 ] + + +-------------------- + 4 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: Boogle 10-4, EXT_ELEM_PROP_2: -99, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: Boogle 6-4, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] + + +-------------------- + 5 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_2: -99, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 245, 245, 245 ] +[ 245, 245, 245 ] + + +-------------------- + 6 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_2: -99, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 245, 245, 245 ] +[ 245, 245, 245 ] + + +-------------------- + 7 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_2: -99, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 245, 245, 245 ] +[ 245, 245, 245 ] + + + +set.num_props(): 10 +set.has_extend_elem_prop(EXT_ELEM_PROP_9): 1 +set.elem_prop_keys(): [] +set.prop_keys(): [ PROP_1 PROP_10 PROP_2 PROP_3 PROP_4 PROP_5 PROP_6 PROP_7 PROP_8 PROP_9 ] +set.prop(PROP_9): 419 +set.size(): 8 + + +------------------------------------- + 165 MODFICATIONS +------------------------------------- + +PROP_1: 1.101 +PROP_10: 182 +PROP_2: 692 +PROP_3: 22 +PROP_4: 779 +PROP_5: 902 +PROP_6: 984 +PROP_7: 434 +PROP_8: 147 +PROP_9: 419 + +-------------------- + 0 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] + + +-------------------- + 1 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: 11.041, EXT_ELEM_PROP_4: 4.441, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: 6.641, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] + + +-------------------- + 2 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 1010, 1010, 1010 ] +[ 1010, 1010, 1010 ] + + +-------------------- + 3 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 1004, 1004, 1004 ] +[ 1004, 1004, 1004 ] + + +-------------------- + 4 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: Boogle 10-4, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: Boogle 6-4, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] + + +-------------------- + 5 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 245, 245, 245 ] +[ 245, 245, 245 ] + + +-------------------- + 6 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 245, 245, 245 ] +[ 245, 245, 245 ] + + +-------------------- + 7 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 245, 245, 245 ] +[ 245, 245, 245 ] + + + + + +------------------------------------- + 170 MODFICATIONS +------------------------------------- + +PROP_1: 1.101 +PROP_10: 182 +PROP_2: 692 +PROP_3: 22 +PROP_4: 779 +PROP_5: 902 +PROP_6: 984 +PROP_7: 434 + +-------------------- + 0 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] + + +-------------------- + 1 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: 11.041, EXT_ELEM_PROP_4: 4.441, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] + + +-------------------- + 2 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 1010, 1010, 1010 ] +[ 1010, 1010, 1010 ] + + +-------------------- + 3 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 1004, 1004, 1004 ] +[ 1004, 1004, 1004 ] + + +-------------------- + 4 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: Boogle 10-4, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] + + +-------------------- + 5 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 245, 245, 245 ] +[ 245, 245, 245 ] + + +-------------------- + 6 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 245, 245, 245 ] +[ 245, 245, 245 ] + + +-------------------- + 7 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 245, 245, 245 ] +[ 245, 245, 245 ] + + +-------------------- + 8 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 1007, 1007, 1007 ] +[ 1007, 1007, 1007 ] + + + +set.num_props(): 8 +set.size(): 1 +set.prop_index(PROP_3): 3 +set.get_extend_elem_prop_header(): [ EXT_ELEM_PROP_1 EXT_ELEM_PROP_10 EXT_ELEM_PROP_4 EXT_ELEM_PROP_5 EXT_ELEM_PROP_7 EXT_ELEM_PROP_8 EXT_ELEM_PROP_9 ] + + +------------------------------------- + 175 MODFICATIONS +------------------------------------- + +PROP_1: 1.101 +PROP_10: 182 +PROP_2: 692 +PROP_3: 22 +PROP_4: 779 +PROP_5: 902 +PROP_6: 984 +PROP_7: 434 + + +set.num_extend_elem_props(): 6 + + +------------------------------------- + 180 MODFICATIONS +------------------------------------- + +PROP_1: 1.101 +PROP_10: 182 +PROP_2: 692 +PROP_3: 22 +PROP_4: 779 +PROP_5: 902 +PROP_6: 984 +PROP_7: 434 + + +set.bsize(): 0 +set.elem_prop_keys(): [] +set.bsize(): 0 +set.size(): 0 +set.prop_keys(): [ PROP_1 PROP_10 PROP_2 PROP_3 PROP_4 PROP_5 PROP_6 PROP_7 ] +set.elem_prop_keys(): [] +set.prop_keys(): [ PROP_1 PROP_10 PROP_2 PROP_3 PROP_4 PROP_5 PROP_6 PROP_7 PROP_8 PROP_9 ] + + +------------------------------------- + 185 MODFICATIONS +------------------------------------- + +PROP_1: 1.101 +PROP_10: 182 +PROP_2: 692 +PROP_3: 22 +PROP_4: 779 +PROP_5: 902 +PROP_6: 984 +PROP_7: 434 +PROP_8: 859 +PROP_9: 835 + + +set.has_prop(PROP_9): 1 +set.get_extend_elem_prop_header(): [ EXT_ELEM_PROP_1 EXT_ELEM_PROP_10 EXT_ELEM_PROP_5 EXT_ELEM_PROP_8 EXT_ELEM_PROP_9 ] +set.has_prop(PROP_2): 1 +set.has_extend_elem_prop(EXT_ELEM_PROP_8): 1 +set.has_extend_elem_prop(EXT_ELEM_PROP_3): 0 +set.num_extend_elem_props(): 5 +set.bsize(): 0 +set.get_extend_elem_prop(EXT_ELEM_PROP_9,6): NaN + + +------------------------------------- + 190 MODFICATIONS +------------------------------------- + +PROP_1: 1.101 +PROP_10: 182 +PROP_2: 692 +PROP_3: 22 +PROP_4: 779 +PROP_5: 902 +PROP_6: 984 +PROP_7: 434 +PROP_8: 859 +PROP_9: 835 + +-------------------- + 0 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_7: -99, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] + + +-------------------- + 1 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_7: -99, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 1005, 1005, 1005 ] +[ 1005, 1005, 1005 ] +[ 1005, 1005, 1005 ] +[ 1005, 1005, 1005 ] + + +-------------------- + 2 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_7: -99, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] + + +-------------------- + 3 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_7: -99, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] + + +-------------------- + 4 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_7: -99, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] + + +-------------------- + 5 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_7: -99, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] + + +-------------------- + 6 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_7: -99, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] + + +-------------------- + 7 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_7: -99, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] + + +-------------------- + 8 +-------------------- +{EXT_ELEM_PROP_1: 1.171, EXT_ELEM_PROP_10: 11.071, EXT_ELEM_PROP_5: 5.571, EXT_ELEM_PROP_7: 7.771, EXT_ELEM_PROP_8: 8.871, EXT_ELEM_PROP_9: 9.971} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] + + +-------------------- + 9 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_7: -99, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] + + + +set.bsize(): 270 +set.prop_keys(): [ PROP_1 PROP_10 PROP_2 PROP_3 PROP_4 PROP_5 PROP_6 PROP_7 PROP_8 PROP_9 ] + + +------------------------------------- + 195 MODFICATIONS +------------------------------------- + +PROP_1: 1.101 +PROP_10: 182 +PROP_2: 692 +PROP_3: 22 +PROP_4: 779 +PROP_5: 902 +PROP_6: 153 +PROP_7: 434 +PROP_8: 859 +PROP_9: 835 + +-------------------- + 0 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_7: -99, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] + + +-------------------- + 1 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_7: -99, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 1005, 1005, 1005 ] +[ 1005, 1005, 1005 ] +[ 1005, 1005, 1005 ] +[ 1005, 1005, 1005 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] + + +-------------------- + 2 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_7: 493, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] + + +-------------------- + 3 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_7: -99, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] + + +-------------------- + 4 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_7: -99, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] + + +-------------------- + 5 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_7: -99, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] + + +-------------------- + 6 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_7: -99, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] + + +-------------------- + 7 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_7: -99, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] + + +-------------------- + 8 +-------------------- +{EXT_ELEM_PROP_1: 1.171, EXT_ELEM_PROP_10: 11.071, EXT_ELEM_PROP_5: 5.571, EXT_ELEM_PROP_7: 7.771, EXT_ELEM_PROP_8: 8.871, EXT_ELEM_PROP_9: 9.971} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] + + +-------------------- + 9 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_7: -99, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] + + + +set.num_extend_elem_props(): 6 +set.prop_index(PROP_3): 3 +set.get_extend_elem_prop(EXT_ELEM_PROP_5,4): -99 +set.prop_index(PROP_10): 1 + + +------------------------------------- + 200 MODFICATIONS +------------------------------------- + +PROP_1: 1.101 +PROP_10: 182 +PROP_2: 692 +PROP_3: 22 +PROP_4: 779 +PROP_5: 902 +PROP_6: 153 +PROP_7: 434 +PROP_8: 859 +PROP_9: 835 + +-------------------- + 0 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: -99, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] + + +-------------------- + 1 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: -99, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 1005, 1005, 1005 ] +[ 1005, 1005, 1005 ] +[ 1005, 1005, 1005 ] +[ 1005, 1005, 1005 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] + + +-------------------- + 2 +-------------------- +{EXT_ELEM_PROP_1: 1.111, EXT_ELEM_PROP_10: 11.011, EXT_ELEM_PROP_5: 5.511, EXT_ELEM_PROP_6: 6.611, EXT_ELEM_PROP_7: 7.711, EXT_ELEM_PROP_8: 8.811, EXT_ELEM_PROP_9: 9.911} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] + + +-------------------- + 3 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: -99, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] + + +-------------------- + 4 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: -99, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] + + +-------------------- + 5 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: -99, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] + + +-------------------- + 6 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: -99, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] + + +-------------------- + 7 +-------------------- +{EXT_ELEM_PROP_1: 1.171, EXT_ELEM_PROP_10: 11.071, EXT_ELEM_PROP_5: 5.571, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: 7.771, EXT_ELEM_PROP_8: 8.871, EXT_ELEM_PROP_9: 9.971} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] + + + +set.num_props(): 10 +set.size(): 8 +set.has_extend_elem_prop(EXT_ELEM_PROP_2): 0 +set.has_extend_elem_prop(EXT_ELEM_PROP_1): 1 +set.get_extend_elem_prop(EXT_ELEM_PROP_9,3): NaN +set.get_extend_elem_prop_header(): [ EXT_ELEM_PROP_1 EXT_ELEM_PROP_10 EXT_ELEM_PROP_5 EXT_ELEM_PROP_6 EXT_ELEM_PROP_7 EXT_ELEM_PROP_8 EXT_ELEM_PROP_9 ] +set.has_prop(PROP_2): 1 +set.num_elem_props(): 0 +set.has_prop(PROP_1): 1 +set.num_extend_elem_props(): 7 +set.get_extend_elem_prop_header(): [ EXT_ELEM_PROP_1 EXT_ELEM_PROP_10 EXT_ELEM_PROP_5 EXT_ELEM_PROP_6 EXT_ELEM_PROP_7 EXT_ELEM_PROP_8 EXT_ELEM_PROP_9 ] +set.num_props(): 10 +set.elem_prop_keys(): [] +set.num_elem_props(): 0 + + +------------------------------------- + 205 MODFICATIONS +------------------------------------- + +PROP_1: 1.101 +PROP_10: 182 +PROP_2: 692 +PROP_3: 22 +PROP_4: 779 +PROP_5: 902 +PROP_6: 153 +PROP_7: 434 +PROP_8: 859 +PROP_9: 835 + +-------------------- + 0 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: -99, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] + + +-------------------- + 1 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: Boogle 10-0, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: Boogle 6-0, EXT_ELEM_PROP_7: Boogle 7-0, EXT_ELEM_PROP_8: Boogle 8-0, EXT_ELEM_PROP_9: Boogle 9-0} + +[ 1005, 1005, 1005 ] +[ 1005, 1005, 1005 ] +[ 1005, 1005, 1005 ] +[ 1005, 1005, 1005 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] + + +-------------------- + 2 +-------------------- +{EXT_ELEM_PROP_1: 1.111, EXT_ELEM_PROP_10: 11.011, EXT_ELEM_PROP_5: 5.511, EXT_ELEM_PROP_6: 6.611, EXT_ELEM_PROP_7: 7.711, EXT_ELEM_PROP_8: 8.811, EXT_ELEM_PROP_9: 9.911} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] + + +-------------------- + 3 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: -99, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] + + +-------------------- + 4 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: -99, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] + + +-------------------- + 5 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: -99, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] + + +-------------------- + 6 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: -99, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] + + +-------------------- + 7 +-------------------- +{EXT_ELEM_PROP_1: 1.171, EXT_ELEM_PROP_10: 11.071, EXT_ELEM_PROP_5: 5.571, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: 7.771, EXT_ELEM_PROP_8: 8.871, EXT_ELEM_PROP_9: 9.971} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] + + + +set.num_elem_props(): 0 + + +------------------------------------- + 210 MODFICATIONS +------------------------------------- + +PROP_1: 1.101 +PROP_10: 182 +PROP_2: 692 +PROP_3: 22 +PROP_4: 779 +PROP_5: 902 +PROP_6: 153 +PROP_7: 434 +PROP_8: 859 +PROP_9: 835 + +-------------------- + 0 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: -99, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] + + +-------------------- + 1 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: Boogle 6-0, EXT_ELEM_PROP_7: Boogle 7-0, EXT_ELEM_PROP_8: Boogle 8-0, EXT_ELEM_PROP_9: Boogle 9-0} + +[ 1005, 1005, 1005 ] +[ 1005, 1005, 1005 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] + + +-------------------- + 2 +-------------------- +{EXT_ELEM_PROP_1: 1.111, EXT_ELEM_PROP_5: 5.511, EXT_ELEM_PROP_6: 6.611, EXT_ELEM_PROP_7: 7.711, EXT_ELEM_PROP_8: 8.811, EXT_ELEM_PROP_9: 9.911} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] + + +-------------------- + 3 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: -99, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] + + +-------------------- + 4 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: -99, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] + + +-------------------- + 5 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: -99, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] + + +-------------------- + 6 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: -99, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] + + +-------------------- + 7 +-------------------- +{EXT_ELEM_PROP_1: 1.171, EXT_ELEM_PROP_5: 5.571, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: 7.771, EXT_ELEM_PROP_8: 8.871, EXT_ELEM_PROP_9: 9.971} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] + + +-------------------- + 8 +-------------------- +{EXT_ELEM_PROP_1: 1.141, EXT_ELEM_PROP_5: 5.541, EXT_ELEM_PROP_6: 6.641, EXT_ELEM_PROP_7: 7.741, EXT_ELEM_PROP_8: 8.841, EXT_ELEM_PROP_9: 9.941} + +[ 1007, 1007, 1007 ] +[ 1007, 1007, 1007 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] + + + +set.bsize(): 135 +set.vsize(): 145 +set.has_extend_elem_prop(EXT_ELEM_PROP_1): 1 +set.num_extend_elem_props(): 6 +set.prop_index(PROP_7): 7 +set.num_extend_elem_props(): 6 +set.num_elem_props(): 0 +set.num_extend_elem_props(): 6 + + +------------------------------------- + 215 MODFICATIONS +------------------------------------- + +PROP_1: 1.101 +PROP_10: 182 +PROP_2: 692 +PROP_3: 22 +PROP_5: 902 +PROP_6: 153 +PROP_7: 434 +PROP_8: 859 +PROP_9: 835 + +-------------------- + 0 +-------------------- +{EXT_ELEM_PROP_1: 1.141, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_5: 5.541, EXT_ELEM_PROP_6: 6.641, EXT_ELEM_PROP_7: 7.741, EXT_ELEM_PROP_8: 8.841, EXT_ELEM_PROP_9: 9.941} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] + + +-------------------- + 1 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: Boogle 6-0, EXT_ELEM_PROP_7: Boogle 7-0, EXT_ELEM_PROP_8: Boogle 8-0, EXT_ELEM_PROP_9: Boogle 9-0} + +[ 1005, 1005, 1005 ] +[ 1005, 1005, 1005 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] + + +-------------------- + 2 +-------------------- +{EXT_ELEM_PROP_1: 1.111, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_5: 5.511, EXT_ELEM_PROP_6: 6.611, EXT_ELEM_PROP_7: 7.711, EXT_ELEM_PROP_8: 8.811, EXT_ELEM_PROP_9: 9.911} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] + + +-------------------- + 3 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: -99, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] + + +-------------------- + 4 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: -99, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] + + +-------------------- + 5 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 1008, 1008, 1008 ] +[ 1008, 1008, 1008 ] +[ 1008, 1008, 1008 ] +[ 1008, 1008, 1008 ] +[ 1008, 1008, 1008 ] +[ 1008, 1008, 1008 ] + + +-------------------- + 6 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: -99, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] + + +-------------------- + 7 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: -99, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] + + +-------------------- + 8 +-------------------- +{EXT_ELEM_PROP_1: 1.171, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_5: 5.571, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: 7.771, EXT_ELEM_PROP_8: 8.871, EXT_ELEM_PROP_9: 9.971} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] + + +-------------------- + 9 +-------------------- +{EXT_ELEM_PROP_1: 1.141, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_5: 5.541, EXT_ELEM_PROP_6: 6.641, EXT_ELEM_PROP_7: 7.741, EXT_ELEM_PROP_8: 8.841, EXT_ELEM_PROP_9: 9.941} + +[ 1007, 1007, 1007 ] +[ 1007, 1007, 1007 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] + + + +set.num_elem_props(): 0 + + +------------------------------------- + 220 MODFICATIONS +------------------------------------- + +PROP_1: 1.101 +PROP_10: 182 +PROP_2: 692 +PROP_3: 22 +PROP_5: 902 +PROP_6: 153 +PROP_8: 859 +PROP_9: 835 + +-------------------- + 0 +-------------------- +{EXT_ELEM_PROP_1: 1.141, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_5: 5.541, EXT_ELEM_PROP_6: 6.641, EXT_ELEM_PROP_7: 7.741, EXT_ELEM_PROP_8: 8.841, EXT_ELEM_PROP_9: 9.941} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] + + +-------------------- + 1 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: Boogle 6-0, EXT_ELEM_PROP_7: Boogle 7-0, EXT_ELEM_PROP_8: Boogle 8-0, EXT_ELEM_PROP_9: Boogle 9-0} + +[ 1005, 1005, 1005 ] +[ 1005, 1005, 1005 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] + + +-------------------- + 2 +-------------------- +{EXT_ELEM_PROP_1: 1.111, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_5: 5.511, EXT_ELEM_PROP_6: 6.611, EXT_ELEM_PROP_7: 7.711, EXT_ELEM_PROP_8: 8.811, EXT_ELEM_PROP_9: 9.911} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] + + +-------------------- + 3 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: -99, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] + + + +set.size(): 4 + + +------------------------------------- + 225 MODFICATIONS +------------------------------------- + +PROP_1: 1.101 +PROP_10: 182 +PROP_2: 692 +PROP_3: 22 +PROP_4: 364 +PROP_5: 902 +PROP_6: 153 +PROP_7: 495 +PROP_8: 859 +PROP_9: 835 + +-------------------- + 0 +-------------------- +{EXT_ELEM_PROP_1: 1.141, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_5: 5.541, EXT_ELEM_PROP_6: 6.641, EXT_ELEM_PROP_7: 7.741, EXT_ELEM_PROP_8: 8.841, EXT_ELEM_PROP_9: 9.941} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] + + +-------------------- + 1 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: Boogle 6-0, EXT_ELEM_PROP_7: Boogle 7-0, EXT_ELEM_PROP_8: Boogle 8-0, EXT_ELEM_PROP_9: Boogle 9-0} + +[ 1005, 1005, 1005 ] +[ 1005, 1005, 1005 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] + + +-------------------- + 2 +-------------------- +{EXT_ELEM_PROP_1: 1.111, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_5: 5.511, EXT_ELEM_PROP_6: 6.611, EXT_ELEM_PROP_7: 7.711, EXT_ELEM_PROP_8: 8.811, EXT_ELEM_PROP_9: 9.911} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] + + +-------------------- + 3 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: -99, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] + + +-------------------- + 4 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 1007, 1007, 1007 ] +[ 1007, 1007, 1007 ] +[ 1007, 1007, 1007 ] +[ 1007, 1007, 1007 ] +[ 1007, 1007, 1007 ] +[ 1007, 1007, 1007 ] + + + +set.size(): 5 +set.vsize(): 88 +set.get_extend_elem_prop(EXT_ELEM_PROP_5,3): -99 +set.prop_keys(): [ PROP_1 PROP_10 PROP_2 PROP_3 PROP_4 PROP_5 PROP_6 PROP_7 PROP_8 PROP_9 ] +set.bsize(): 78 +set.get_extend_elem_prop_header(): [ EXT_ELEM_PROP_1 EXT_ELEM_PROP_10 EXT_ELEM_PROP_5 EXT_ELEM_PROP_6 EXT_ELEM_PROP_7 EXT_ELEM_PROP_8 EXT_ELEM_PROP_9 ] +set.prop(PROP_10): 182 + + +------------------------------------- + 230 MODFICATIONS +------------------------------------- + +PROP_1: 1.101 +PROP_10: 182 +PROP_2: 692 +PROP_3: 22 +PROP_4: 364 +PROP_5: 902 +PROP_6: 153 +PROP_7: 495 +PROP_8: 859 +PROP_9: 835 + +-------------------- + 0 +-------------------- +{EXT_ELEM_PROP_1: 1.141, EXT_ELEM_PROP_10: Boogle 10-0, EXT_ELEM_PROP_5: 5.541, EXT_ELEM_PROP_6: Boogle 6-0, EXT_ELEM_PROP_7: Boogle 7-0, EXT_ELEM_PROP_8: Boogle 8-0, EXT_ELEM_PROP_9: Boogle 9-0} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] + + +-------------------- + 1 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: Boogle 10-1, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: Boogle 6-1, EXT_ELEM_PROP_7: Boogle 7-1, EXT_ELEM_PROP_8: Boogle 8-1, EXT_ELEM_PROP_9: Boogle 9-1} + +[ 1005, 1005, 1005 ] +[ 1005, 1005, 1005 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] + + +-------------------- + 2 +-------------------- +{EXT_ELEM_PROP_1: 1.111, EXT_ELEM_PROP_10: Boogle 10-2, EXT_ELEM_PROP_5: 5.511, EXT_ELEM_PROP_6: Boogle 6-2, EXT_ELEM_PROP_7: Boogle 7-2, EXT_ELEM_PROP_8: Boogle 8-2, EXT_ELEM_PROP_9: Boogle 9-2} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] + + +-------------------- + 3 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: Boogle 10-3, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: Boogle 6-3, EXT_ELEM_PROP_7: Boogle 7-3, EXT_ELEM_PROP_8: Boogle 8-3, EXT_ELEM_PROP_9: Boogle 9-3} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] + + +-------------------- + 4 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: Boogle 10-3, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: Boogle 6-3, EXT_ELEM_PROP_7: Boogle 7-3, EXT_ELEM_PROP_8: Boogle 8-3, EXT_ELEM_PROP_9: Boogle 9-3} + +[ 1007, 1007, 1007 ] +[ 1007, 1007, 1007 ] +[ 1007, 1007, 1007 ] +[ 1007, 1007, 1007 ] +[ 1007, 1007, 1007 ] +[ 1007, 1007, 1007 ] + + +-------------------- + 5 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + + + + +set.prop_index(PROP_10): 1 +set.has_elem_prop(ELEM_PROP_8): 0 +set.bsize(): 78 +set.bsize(): 78 + + +------------------------------------- + FINAL PRINT +------------------------------------- + +PROP_1: 1.101 +PROP_10: 182 +PROP_2: 692 +PROP_3: 22 +PROP_4: 364 +PROP_5: 902 +PROP_6: 153 +PROP_7: 495 +PROP_8: 859 +PROP_9: 835 + +-------------------- + 0 +-------------------- +{EXT_ELEM_PROP_1: 1.141, EXT_ELEM_PROP_10: Boogle 10-0, EXT_ELEM_PROP_5: 5.541, EXT_ELEM_PROP_6: Boogle 6-0, EXT_ELEM_PROP_7: Boogle 7-0, EXT_ELEM_PROP_8: Boogle 8-0, EXT_ELEM_PROP_9: Boogle 9-0} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] + + +-------------------- + 1 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: 898, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: Boogle 6-1, EXT_ELEM_PROP_7: Boogle 7-1, EXT_ELEM_PROP_8: Boogle 8-1, EXT_ELEM_PROP_9: Boogle 9-1} + +[ 1005, 1005, 1005 ] +[ 1005, 1005, 1005 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] + + +-------------------- + 2 +-------------------- +{EXT_ELEM_PROP_1: 1.111, EXT_ELEM_PROP_10: Boogle 10-2, EXT_ELEM_PROP_5: 5.511, EXT_ELEM_PROP_6: Boogle 6-2, EXT_ELEM_PROP_7: Boogle 7-2, EXT_ELEM_PROP_8: Boogle 8-2, EXT_ELEM_PROP_9: Boogle 9-2} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] + + +-------------------- + 3 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: Boogle 10-3, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: Boogle 6-3, EXT_ELEM_PROP_7: Boogle 7-3, EXT_ELEM_PROP_8: Boogle 8-3, EXT_ELEM_PROP_9: Boogle 9-3} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] + + +-------------------- + 4 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: Boogle 10-3, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: Boogle 6-3, EXT_ELEM_PROP_7: Boogle 7-3, EXT_ELEM_PROP_8: Boogle 8-3, EXT_ELEM_PROP_9: Boogle 9-3} + +[ 1007, 1007, 1007 ] +[ 1007, 1007, 1007 ] +[ 1007, 1007, 1007 ] +[ 1007, 1007, 1007 ] +[ 1007, 1007, 1007 ] +[ 1007, 1007, 1007 ] + + +-------------------- + 5 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + + + diff --git a/python/fibre/base/test/output/python_output.txt b/python/fibre/base/test/output/python_output.txt new file mode 100644 index 0000000..b885816 --- /dev/null +++ b/python/fibre/base/test/output/python_output.txt @@ -0,0 +1,4273 @@ + + +------------------------------------- + INITIAL SET +------------------------------------- + +PROP_1: 1.101 +PROP_2: 2.201 +PROP_3: 3.301 +PROP_4: 4.401 +PROP_5: 5.501 + +-------------------- + 0 +-------------------- +{EXT_ELEM_PROP_1: Ooogle 1-0, EXT_ELEM_PROP_2: Ooogle 2-0, EXT_ELEM_PROP_3: Ooogle 3-0, EXT_ELEM_PROP_4: Ooogle 4-0, EXT_ELEM_PROP_5: Ooogle 5-0} + +ELEM_PROP_1: 0.101 +ELEM_PROP_2: 0.201 +ELEM_PROP_3: 0.301 +ELEM_PROP_4: 0.401 +ELEM_PROP_5: 0.501 +[ 1, 2, 3 ] +[ 11, 12, 13 ] +[ 21, 22, 23 ] +[ 31, 32, 33 ] +[ 41, 42, 43 ] + + +-------------------- + 1 +-------------------- +{EXT_ELEM_PROP_1: Ooogle 1-1, EXT_ELEM_PROP_2: Ooogle 2-1, EXT_ELEM_PROP_3: Ooogle 3-1, EXT_ELEM_PROP_4: Ooogle 4-1, EXT_ELEM_PROP_5: Ooogle 5-1} + +ELEM_PROP_1: 100.101 +ELEM_PROP_2: 100.201 +ELEM_PROP_3: 100.301 +ELEM_PROP_4: 100.401 +ELEM_PROP_5: 100.501 +[ 101, 102, 103 ] +[ 111, 112, 113 ] +[ 121, 122, 123 ] +[ 131, 132, 133 ] +[ 141, 142, 143 ] + + +-------------------- + 2 +-------------------- +{EXT_ELEM_PROP_1: Ooogle 1-2, EXT_ELEM_PROP_2: Ooogle 2-2, EXT_ELEM_PROP_3: Ooogle 3-2, EXT_ELEM_PROP_4: Ooogle 4-2, EXT_ELEM_PROP_5: Ooogle 5-2} + +ELEM_PROP_1: 200.101 +ELEM_PROP_2: 200.201 +ELEM_PROP_3: 200.301 +ELEM_PROP_4: 200.401 +ELEM_PROP_5: 200.501 +[ 201, 202, 203 ] +[ 211, 212, 213 ] +[ 221, 222, 223 ] +[ 231, 232, 233 ] +[ 241, 242, 243 ] + + +-------------------- + 3 +-------------------- +{EXT_ELEM_PROP_1: Ooogle 1-3, EXT_ELEM_PROP_2: Ooogle 2-3, EXT_ELEM_PROP_3: Ooogle 3-3, EXT_ELEM_PROP_4: Ooogle 4-3, EXT_ELEM_PROP_5: Ooogle 5-3} + +ELEM_PROP_1: 300.101 +ELEM_PROP_2: 300.201 +ELEM_PROP_3: 300.301 +ELEM_PROP_4: 300.401 +ELEM_PROP_5: 300.501 +[ 301, 302, 303 ] +[ 311, 312, 313 ] +[ 321, 322, 323 ] +[ 331, 332, 333 ] +[ 341, 342, 343 ] + + +-------------------- + 4 +-------------------- +{EXT_ELEM_PROP_1: Ooogle 1-4, EXT_ELEM_PROP_2: Ooogle 2-4, EXT_ELEM_PROP_3: Ooogle 3-4, EXT_ELEM_PROP_4: Ooogle 4-4, EXT_ELEM_PROP_5: Ooogle 5-4} + +ELEM_PROP_1: 400.101 +ELEM_PROP_2: 400.201 +ELEM_PROP_3: 400.301 +ELEM_PROP_4: 400.401 +ELEM_PROP_5: 400.501 +[ 401, 402, 403 ] +[ 411, 412, 413 ] +[ 421, 422, 423 ] +[ 431, 432, 433 ] +[ 441, 442, 443 ] + + + + + +------------------------------------- + SECOND SET +------------------------------------- + +PROP_1: -1.101 +PROP_2: -2.201 +PROP_3: -3.301 +PROP_4: -4.401 +PROP_5: -5.501 + +-------------------- + 0 +-------------------- +{EXT_ELEM_PROP_10: Boogle 10-0, EXT_ELEM_PROP_6: Boogle 6-0, EXT_ELEM_PROP_7: Boogle 7-0, EXT_ELEM_PROP_8: Boogle 8-0, EXT_ELEM_PROP_9: Boogle 9-0} + +ELEM_PROP_1: -0.101 +ELEM_PROP_2: -0.201 +ELEM_PROP_3: -0.301 +ELEM_PROP_4: -0.401 +ELEM_PROP_5: -0.501 +[ -1, -2, -3 ] +[ -11, -12, -13 ] +[ -21, -22, -23 ] +[ -31, -32, -33 ] +[ -41, -42, -43 ] + + +-------------------- + 1 +-------------------- +{EXT_ELEM_PROP_10: Boogle 10-1, EXT_ELEM_PROP_6: Boogle 6-1, EXT_ELEM_PROP_7: Boogle 7-1, EXT_ELEM_PROP_8: Boogle 8-1, EXT_ELEM_PROP_9: Boogle 9-1} + +ELEM_PROP_1: -100.101 +ELEM_PROP_2: -100.201 +ELEM_PROP_3: -100.301 +ELEM_PROP_4: -100.401 +ELEM_PROP_5: -100.501 +[ -101, -102, -103 ] +[ -111, -112, -113 ] +[ -121, -122, -123 ] +[ -131, -132, -133 ] +[ -141, -142, -143 ] + + +-------------------- + 2 +-------------------- +{EXT_ELEM_PROP_10: Boogle 10-2, EXT_ELEM_PROP_6: Boogle 6-2, EXT_ELEM_PROP_7: Boogle 7-2, EXT_ELEM_PROP_8: Boogle 8-2, EXT_ELEM_PROP_9: Boogle 9-2} + +ELEM_PROP_1: -200.101 +ELEM_PROP_2: -200.201 +ELEM_PROP_3: -200.301 +ELEM_PROP_4: -200.401 +ELEM_PROP_5: -200.501 +[ -201, -202, -203 ] +[ -211, -212, -213 ] +[ -221, -222, -223 ] +[ -231, -232, -233 ] +[ -241, -242, -243 ] + + +-------------------- + 3 +-------------------- +{EXT_ELEM_PROP_10: Boogle 10-3, EXT_ELEM_PROP_6: Boogle 6-3, EXT_ELEM_PROP_7: Boogle 7-3, EXT_ELEM_PROP_8: Boogle 8-3, EXT_ELEM_PROP_9: Boogle 9-3} + +ELEM_PROP_1: -300.101 +ELEM_PROP_2: -300.201 +ELEM_PROP_3: -300.301 +ELEM_PROP_4: -300.401 +ELEM_PROP_5: -300.501 +[ -301, -302, -303 ] +[ -311, -312, -313 ] +[ -321, -322, -323 ] +[ -331, -332, -333 ] +[ -341, -342, -343 ] + + +-------------------- + 4 +-------------------- +{EXT_ELEM_PROP_10: Boogle 10-4, EXT_ELEM_PROP_6: Boogle 6-4, EXT_ELEM_PROP_7: Boogle 7-4, EXT_ELEM_PROP_8: Boogle 8-4, EXT_ELEM_PROP_9: Boogle 9-4} + +ELEM_PROP_1: -400.101 +ELEM_PROP_2: -400.201 +ELEM_PROP_3: -400.301 +ELEM_PROP_4: -400.401 +ELEM_PROP_5: -400.501 +[ -401, -402, -403 ] +[ -411, -412, -413 ] +[ -421, -422, -423 ] +[ -431, -432, -433 ] +[ -441, -442, -443 ] + + + +set.num_elem_props(): 5 +set.elem_prop_index(ELEM_PROP_4): 3 +set.has_extend_elem_prop(EXT_ELEM_PROP_7): 0 +set.num_props(): 6 + + +------------------------------------- + 5 MODFICATIONS +------------------------------------- + +PROP_1: 1.101 +PROP_2: 2.201 +PROP_4: 4.401 +PROP_5: 5.501 +PROP_6: 984 + +-------------------- + 0 +-------------------- +{EXT_ELEM_PROP_1: Ooogle 1-0, EXT_ELEM_PROP_2: Ooogle 2-0, EXT_ELEM_PROP_3: Ooogle 3-0, EXT_ELEM_PROP_4: Ooogle 4-0, EXT_ELEM_PROP_5: Ooogle 5-0} + +ELEM_PROP_1: 0.101 +ELEM_PROP_2: 669 +ELEM_PROP_3: 0.301 +ELEM_PROP_4: 0.401 +ELEM_PROP_5: 0.501 +[ 1, 2, 3 ] +[ 11, 12, 13 ] +[ 21, 22, 23 ] +[ 31, 32, 33 ] +[ 41, 42, 43 ] + + +-------------------- + 1 +-------------------- +{EXT_ELEM_PROP_1: NaN, EXT_ELEM_PROP_2: NaN, EXT_ELEM_PROP_3: NaN, EXT_ELEM_PROP_4: NaN, EXT_ELEM_PROP_5: NaN} + +ELEM_PROP_1: 1009 +ELEM_PROP_2: 669 +ELEM_PROP_3: 1009 +ELEM_PROP_4: 1009 +ELEM_PROP_5: 1009 +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] + + +-------------------- + 2 +-------------------- +{EXT_ELEM_PROP_1: Ooogle 1-1, EXT_ELEM_PROP_2: Ooogle 2-1, EXT_ELEM_PROP_3: Ooogle 3-1, EXT_ELEM_PROP_4: Ooogle 4-1, EXT_ELEM_PROP_5: Ooogle 5-1} + +ELEM_PROP_1: 100.101 +ELEM_PROP_2: 669 +ELEM_PROP_3: 100.301 +ELEM_PROP_4: 100.401 +ELEM_PROP_5: 100.501 +[ 101, 102, 103 ] +[ 111, 112, 113 ] +[ 121, 122, 123 ] +[ 131, 132, 133 ] +[ 141, 142, 143 ] + + +-------------------- + 3 +-------------------- +{EXT_ELEM_PROP_1: Ooogle 1-2, EXT_ELEM_PROP_2: Ooogle 2-2, EXT_ELEM_PROP_3: Ooogle 3-2, EXT_ELEM_PROP_4: Ooogle 4-2, EXT_ELEM_PROP_5: Ooogle 5-2} + +ELEM_PROP_1: 200.101 +ELEM_PROP_2: 669 +ELEM_PROP_3: 200.301 +ELEM_PROP_4: 200.401 +ELEM_PROP_5: 200.501 +[ 201, 202, 203 ] +[ 211, 212, 213 ] +[ 221, 222, 223 ] +[ 231, 232, 233 ] +[ 241, 242, 243 ] + + +-------------------- + 4 +-------------------- +{EXT_ELEM_PROP_1: Ooogle 1-3, EXT_ELEM_PROP_2: Ooogle 2-3, EXT_ELEM_PROP_3: Ooogle 3-3, EXT_ELEM_PROP_4: Ooogle 4-3, EXT_ELEM_PROP_5: Ooogle 5-3} + +ELEM_PROP_1: 300.101 +ELEM_PROP_2: 669 +ELEM_PROP_3: 300.301 +ELEM_PROP_4: 300.401 +ELEM_PROP_5: 300.501 +[ 301, 302, 303 ] +[ 311, 312, 313 ] +[ 321, 322, 323 ] +[ 331, 332, 333 ] +[ 341, 342, 343 ] + + +-------------------- + 5 +-------------------- +{EXT_ELEM_PROP_1: Ooogle 1-4, EXT_ELEM_PROP_2: Ooogle 2-4, EXT_ELEM_PROP_3: Ooogle 3-4, EXT_ELEM_PROP_4: Ooogle 4-4, EXT_ELEM_PROP_5: Ooogle 5-4} + +ELEM_PROP_1: 400.101 +ELEM_PROP_2: 669 +ELEM_PROP_3: 400.301 +ELEM_PROP_4: 400.401 +ELEM_PROP_5: 400.501 +[ 401, 402, 403 ] +[ 411, 412, 413 ] +[ 421, 422, 423 ] +[ 431, 432, 433 ] +[ 441, 442, 443 ] + + + +set.bsize(): 120 +set.size(): 6 +set.num_extend_elem_props(): 5 +set.prop(PROP_9): 419 +set.elem_prop_keys(): [ ELEM_PROP_1 ELEM_PROP_2 ELEM_PROP_3 ELEM_PROP_4 ELEM_PROP_5 ] + + +------------------------------------- + 10 MODFICATIONS +------------------------------------- + +PROP_1: 1.101 +PROP_2: 2.201 +PROP_4: 4.401 +PROP_5: 5.501 +PROP_6: 984 +PROP_9: 419 + +-------------------- + 0 +-------------------- +{EXT_ELEM_PROP_1: Ooogle 1-0, EXT_ELEM_PROP_2: Ooogle 2-0, EXT_ELEM_PROP_3: Ooogle 3-0, EXT_ELEM_PROP_4: Ooogle 4-0, EXT_ELEM_PROP_5: Ooogle 5-0} + +ELEM_PROP_1: 0.101 +ELEM_PROP_2: 669 +ELEM_PROP_3: 0.301 +ELEM_PROP_4: 463 +ELEM_PROP_5: 661 +[ 1, 2, 3 ] +[ 11, 12, 13 ] +[ 21, 22, 23 ] +[ 31, 32, 33 ] +[ 41, 42, 43 ] + + +-------------------- + 1 +-------------------- +{EXT_ELEM_PROP_1: NaN, EXT_ELEM_PROP_2: NaN, EXT_ELEM_PROP_3: NaN, EXT_ELEM_PROP_4: NaN, EXT_ELEM_PROP_5: NaN} + +ELEM_PROP_1: 1009 +ELEM_PROP_2: 669 +ELEM_PROP_3: 1009 +ELEM_PROP_4: 463 +ELEM_PROP_5: 661 +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] + + +-------------------- + 2 +-------------------- +{EXT_ELEM_PROP_1: NaN, EXT_ELEM_PROP_2: NaN, EXT_ELEM_PROP_3: NaN, EXT_ELEM_PROP_4: NaN, EXT_ELEM_PROP_5: NaN} + +ELEM_PROP_1: 100.101 +ELEM_PROP_2: 669 +ELEM_PROP_3: 100.301 +ELEM_PROP_4: 463 +ELEM_PROP_5: 661 +[ 101, 102, 103 ] +[ 111, 112, 113 ] +[ 121, 122, 123 ] +[ 131, 132, 133 ] +[ 141, 142, 143 ] + + +-------------------- + 3 +-------------------- +{EXT_ELEM_PROP_1: Ooogle 1-2, EXT_ELEM_PROP_2: Ooogle 2-2, EXT_ELEM_PROP_3: Ooogle 3-2, EXT_ELEM_PROP_4: Ooogle 4-2, EXT_ELEM_PROP_5: Ooogle 5-2} + +ELEM_PROP_1: 200.101 +ELEM_PROP_2: 669 +ELEM_PROP_3: 200.301 +ELEM_PROP_4: 463 +ELEM_PROP_5: 661 +[ 201, 202, 203 ] +[ 211, 212, 213 ] +[ 221, 222, 223 ] +[ 231, 232, 233 ] +[ 241, 242, 243 ] + + +-------------------- + 4 +-------------------- +{EXT_ELEM_PROP_1: Ooogle 1-3, EXT_ELEM_PROP_2: Ooogle 2-3, EXT_ELEM_PROP_3: Ooogle 3-3, EXT_ELEM_PROP_4: Ooogle 4-3, EXT_ELEM_PROP_5: Ooogle 5-3} + +ELEM_PROP_1: 300.101 +ELEM_PROP_2: 669 +ELEM_PROP_3: 300.301 +ELEM_PROP_4: 463 +ELEM_PROP_5: 661 +[ 301, 302, 303 ] +[ 311, 312, 313 ] +[ 321, 322, 323 ] +[ 331, 332, 333 ] +[ 341, 342, 343 ] + + +-------------------- + 5 +-------------------- +{EXT_ELEM_PROP_1: Ooogle 1-4, EXT_ELEM_PROP_2: Ooogle 2-4, EXT_ELEM_PROP_3: Ooogle 3-4, EXT_ELEM_PROP_4: Ooogle 4-4, EXT_ELEM_PROP_5: Ooogle 5-4} + +ELEM_PROP_1: 400.101 +ELEM_PROP_2: 669 +ELEM_PROP_3: 400.301 +ELEM_PROP_4: 463 +ELEM_PROP_5: 661 +[ 401, 402, 403 ] +[ 411, 412, 413 ] +[ 421, 422, 423 ] +[ 431, 432, 433 ] +[ 441, 442, 443 ] + + + +set.prop_index(PROP_2): 1 +set.vsize(): 158 +set.num_props(): 6 +set.num_extend_elem_props(): 5 +set.prop_index(PROP_2): 1 + + +------------------------------------- + 15 MODFICATIONS +------------------------------------- + +PROP_1: 1.101 +PROP_2: 2.201 +PROP_4: 4.401 +PROP_5: 5.501 +PROP_6: 984 +PROP_7: 434 +PROP_9: 419 + +-------------------- + 0 +-------------------- +{EXT_ELEM_PROP_1: Ooogle 1-0, EXT_ELEM_PROP_2: Ooogle 2-0, EXT_ELEM_PROP_3: Ooogle 3-0, EXT_ELEM_PROP_4: Ooogle 4-0, EXT_ELEM_PROP_5: Ooogle 5-0} + +ELEM_PROP_1: 0.101 +ELEM_PROP_2: 669 +ELEM_PROP_3: 0.301 +ELEM_PROP_4: 815 +ELEM_PROP_5: 661 +[ 1, 2, 3 ] +[ 11, 12, 13 ] +[ 21, 22, 23 ] +[ 31, 32, 33 ] +[ 41, 42, 43 ] + + +-------------------- + 1 +-------------------- +{EXT_ELEM_PROP_1: NaN, EXT_ELEM_PROP_2: NaN, EXT_ELEM_PROP_3: NaN, EXT_ELEM_PROP_4: NaN, EXT_ELEM_PROP_5: NaN} + +ELEM_PROP_1: 1009 +ELEM_PROP_2: 1009 +ELEM_PROP_3: 1009 +ELEM_PROP_4: 1009 +ELEM_PROP_5: 1009 +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] + + +-------------------- + 2 +-------------------- +{EXT_ELEM_PROP_1: NaN, EXT_ELEM_PROP_2: NaN, EXT_ELEM_PROP_3: NaN, EXT_ELEM_PROP_4: NaN, EXT_ELEM_PROP_5: NaN} + +ELEM_PROP_1: 100.101 +ELEM_PROP_2: 669 +ELEM_PROP_3: 100.301 +ELEM_PROP_4: 815 +ELEM_PROP_5: 661 +[ 101, 102, 103 ] +[ 111, 112, 113 ] +[ 121, 122, 123 ] +[ 131, 132, 133 ] +[ 141, 142, 143 ] + + +-------------------- + 3 +-------------------- +{EXT_ELEM_PROP_1: Ooogle 1-2, EXT_ELEM_PROP_2: Ooogle 2-2, EXT_ELEM_PROP_3: Ooogle 3-2, EXT_ELEM_PROP_4: Ooogle 4-2, EXT_ELEM_PROP_5: Ooogle 5-2} + +ELEM_PROP_1: 200.101 +ELEM_PROP_2: 669 +ELEM_PROP_3: 200.301 +ELEM_PROP_4: 815 +ELEM_PROP_5: 661 +[ 201, 202, 203 ] +[ 211, 212, 213 ] +[ 221, 222, 223 ] +[ 231, 232, 233 ] +[ 241, 242, 243 ] + + +-------------------- + 4 +-------------------- +{EXT_ELEM_PROP_1: Ooogle 1-3, EXT_ELEM_PROP_2: Ooogle 2-3, EXT_ELEM_PROP_3: Ooogle 3-3, EXT_ELEM_PROP_4: Ooogle 4-3, EXT_ELEM_PROP_5: Ooogle 5-3} + +ELEM_PROP_1: 300.101 +ELEM_PROP_2: 669 +ELEM_PROP_3: 300.301 +ELEM_PROP_4: 815 +ELEM_PROP_5: 661 +[ 301, 302, 303 ] +[ 311, 312, 313 ] +[ 321, 322, 323 ] +[ 331, 332, 333 ] +[ 341, 342, 343 ] + + +-------------------- + 5 +-------------------- +{EXT_ELEM_PROP_1: Ooogle 1-4, EXT_ELEM_PROP_2: Ooogle 2-4, EXT_ELEM_PROP_3: Ooogle 3-4, EXT_ELEM_PROP_4: Ooogle 4-4, EXT_ELEM_PROP_5: Ooogle 5-4} + +ELEM_PROP_1: 400.101 +ELEM_PROP_2: 669 +ELEM_PROP_3: 400.301 +ELEM_PROP_4: 815 +ELEM_PROP_5: 661 +[ 401, 402, 403 ] +[ 411, 412, 413 ] +[ 421, 422, 423 ] +[ 431, 432, 433 ] +[ 441, 442, 443 ] + + +-------------------- + 6 +-------------------- +{EXT_ELEM_PROP_1: 1.141, EXT_ELEM_PROP_2: 2.241, EXT_ELEM_PROP_3: 3.341, EXT_ELEM_PROP_4: 4.441, EXT_ELEM_PROP_5: 5.541} + +ELEM_PROP_1: 1001 +ELEM_PROP_2: 1001 +ELEM_PROP_3: 1001 +ELEM_PROP_4: 815 +ELEM_PROP_5: 1001 +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] + + + +set.get_extend_elem_prop_header(): [ EXT_ELEM_PROP_1 EXT_ELEM_PROP_2 EXT_ELEM_PROP_3 EXT_ELEM_PROP_4 EXT_ELEM_PROP_5 ] +set.prop_keys(): [ PROP_1 PROP_2 PROP_4 PROP_5 PROP_6 PROP_7 PROP_9 ] +set.prop_keys(): [ PROP_1 PROP_2 PROP_4 PROP_5 PROP_6 PROP_7 PROP_9 ] +set.elem_prop_keys(): [ ELEM_PROP_1 ELEM_PROP_2 ELEM_PROP_3 ELEM_PROP_4 ELEM_PROP_5 ] + + +------------------------------------- + 20 MODFICATIONS +------------------------------------- + +PROP_1: 1.101 +PROP_2: 2.201 +PROP_4: 4.401 +PROP_5: 5.501 +PROP_6: 984 +PROP_7: 434 +PROP_9: 419 + +-------------------- + 0 +-------------------- +{EXT_ELEM_PROP_1: Ooogle 1-0, EXT_ELEM_PROP_2: Ooogle 2-0, EXT_ELEM_PROP_3: Ooogle 3-0, EXT_ELEM_PROP_4: Ooogle 4-0, EXT_ELEM_PROP_5: Ooogle 5-0} + +ELEM_PROP_1: 0.101 +ELEM_PROP_2: 669 +ELEM_PROP_3: 0.301 +ELEM_PROP_4: 815 +ELEM_PROP_5: 661 +[ 1, 2, 3 ] +[ 11, 12, 13 ] +[ 21, 22, 23 ] +[ 31, 32, 33 ] +[ 41, 42, 43 ] + + +-------------------- + 1 +-------------------- +{EXT_ELEM_PROP_1: NaN, EXT_ELEM_PROP_2: NaN, EXT_ELEM_PROP_3: NaN, EXT_ELEM_PROP_4: NaN, EXT_ELEM_PROP_5: NaN} + +ELEM_PROP_1: 1009 +ELEM_PROP_2: 1009 +ELEM_PROP_3: 1009 +ELEM_PROP_4: 1009 +ELEM_PROP_5: 1009 +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] + + +-------------------- + 2 +-------------------- +{EXT_ELEM_PROP_1: Ooogle 1-2, EXT_ELEM_PROP_2: Ooogle 2-2, EXT_ELEM_PROP_3: Ooogle 3-2, EXT_ELEM_PROP_4: Ooogle 4-2, EXT_ELEM_PROP_5: Ooogle 5-2} + +ELEM_PROP_1: 200.101 +ELEM_PROP_2: 669 +ELEM_PROP_3: 200.301 +ELEM_PROP_4: 815 +ELEM_PROP_5: 661 +[ 201, 202, 203 ] +[ 211, 212, 213 ] +[ 221, 222, 223 ] +[ 231, 232, 233 ] +[ 241, 242, 243 ] + + +-------------------- + 3 +-------------------- +{EXT_ELEM_PROP_1: 1.141, EXT_ELEM_PROP_2: 2.241, EXT_ELEM_PROP_3: 3.341, EXT_ELEM_PROP_4: 4.441, EXT_ELEM_PROP_5: 5.541} + +ELEM_PROP_1: 300.101 +ELEM_PROP_2: 669 +ELEM_PROP_3: 300.301 +ELEM_PROP_4: 815 +ELEM_PROP_5: 661 +[ 301, 302, 303 ] +[ 311, 312, 313 ] +[ 321, 322, 323 ] +[ 331, 332, 333 ] +[ 341, 342, 343 ] + + +-------------------- + 4 +-------------------- +{EXT_ELEM_PROP_1: Ooogle 1-4, EXT_ELEM_PROP_2: Ooogle 2-4, EXT_ELEM_PROP_3: Ooogle 3-4, EXT_ELEM_PROP_4: Ooogle 4-4, EXT_ELEM_PROP_5: Ooogle 5-4} + +ELEM_PROP_1: 400.101 +ELEM_PROP_2: 669 +ELEM_PROP_3: 400.301 +ELEM_PROP_4: 815 +ELEM_PROP_5: 661 +[ 401, 402, 403 ] +[ 411, 412, 413 ] +[ 421, 422, 423 ] +[ 431, 432, 433 ] +[ 441, 442, 443 ] + + +-------------------- + 5 +-------------------- +{EXT_ELEM_PROP_1: 1.141, EXT_ELEM_PROP_2: 2.241, EXT_ELEM_PROP_3: 3.341, EXT_ELEM_PROP_4: 4.441, EXT_ELEM_PROP_5: 5.541} + +ELEM_PROP_1: 1001 +ELEM_PROP_2: 1001 +ELEM_PROP_3: 1001 +ELEM_PROP_4: 815 +ELEM_PROP_5: 1001 +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] + + +-------------------- + 6 +-------------------- +{EXT_ELEM_PROP_1: 1.181, EXT_ELEM_PROP_2: 2.281, EXT_ELEM_PROP_3: 3.381, EXT_ELEM_PROP_4: 4.481, EXT_ELEM_PROP_5: 5.581} + +ELEM_PROP_1: 1007 +ELEM_PROP_2: 1007 +ELEM_PROP_3: 1007 +ELEM_PROP_4: 1007 +ELEM_PROP_5: 1007 +[ 1007, 1007, 1007 ] +[ 1007, 1007, 1007 ] +[ 1007, 1007, 1007 ] +[ 1007, 1007, 1007 ] +[ 1007, 1007, 1007 ] + + + +set.elem_prop_index(ELEM_PROP_4): 3 +set.elem_prop_index(ELEM_PROP_4): 3 + + +------------------------------------- + 25 MODFICATIONS +------------------------------------- + +PROP_1: 1.101 +PROP_2: 2.201 +PROP_4: 4.401 +PROP_5: 5.501 +PROP_6: 984 +PROP_7: 434 +PROP_9: 419 + +-------------------- + 0 +-------------------- +{EXT_ELEM_PROP_1: Ooogle 1-0, EXT_ELEM_PROP_2: Ooogle 2-0, EXT_ELEM_PROP_3: Ooogle 3-0, EXT_ELEM_PROP_4: Ooogle 4-0, EXT_ELEM_PROP_5: Ooogle 5-0} + +ELEM_PROP_1: 0.101 +ELEM_PROP_2: 669 +ELEM_PROP_3: 0.301 +ELEM_PROP_4: 815 +ELEM_PROP_5: 661 +[ 1, 2, 3 ] +[ 11, 12, 13 ] +[ 21, 22, 23 ] +[ 31, 32, 33 ] +[ 41, 42, 43 ] +[ 511, 511, 511 ] +[ 511, 511, 511 ] + + +-------------------- + 1 +-------------------- +{EXT_ELEM_PROP_1: NaN, EXT_ELEM_PROP_2: NaN, EXT_ELEM_PROP_3: NaN, EXT_ELEM_PROP_4: NaN, EXT_ELEM_PROP_5: NaN} + +ELEM_PROP_1: 1003 +ELEM_PROP_2: 1003 +ELEM_PROP_3: 1003 +ELEM_PROP_4: 1003 +ELEM_PROP_5: 1003 +[ 511, 511, 511 ] +[ 511, 511, 511 ] +[ 511, 511, 511 ] +[ 511, 511, 511 ] +[ 511, 511, 511 ] +[ 511, 511, 511 ] +[ 511, 511, 511 ] + + + +set.prop(PROP_4): 4.401 + + +------------------------------------- + 30 MODFICATIONS +------------------------------------- + +PROP_1: 1.101 +PROP_2: 2.201 +PROP_4: 4.401 +PROP_5: 5.501 +PROP_6: 984 +PROP_7: 434 +PROP_9: 419 + +-------------------- + 0 +-------------------- +{EXT_ELEM_PROP_1: Ooogle 1-0, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_2: Ooogle 2-0, EXT_ELEM_PROP_3: Ooogle 3-0, EXT_ELEM_PROP_4: Ooogle 4-0, EXT_ELEM_PROP_5: Ooogle 5-0, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +ELEM_PROP_1: 0.101 +ELEM_PROP_2: 669 +ELEM_PROP_3: 0.301 +ELEM_PROP_4: 734 +ELEM_PROP_5: 661 +[ 1, 2, 3 ] +[ 11, 12, 13 ] +[ 21, 22, 23 ] +[ 31, 32, 33 ] +[ 41, 42, 43 ] +[ 511, 511, 511 ] +[ 511, 511, 511 ] +[ 886, 886, 886 ] + + +-------------------- + 1 +-------------------- +{EXT_ELEM_PROP_1: NaN, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_2: NaN, EXT_ELEM_PROP_3: NaN, EXT_ELEM_PROP_4: NaN, EXT_ELEM_PROP_5: NaN, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +ELEM_PROP_1: 1003 +ELEM_PROP_2: 1003 +ELEM_PROP_3: 1003 +ELEM_PROP_4: 734 +ELEM_PROP_5: 1003 +[ 511, 511, 511 ] +[ 511, 511, 511 ] +[ 511, 511, 511 ] +[ 511, 511, 511 ] +[ 511, 511, 511 ] +[ 511, 511, 511 ] +[ 511, 511, 511 ] +[ 886, 886, 886 ] + + +-------------------- + 2 +-------------------- +{EXT_ELEM_PROP_1: NaN, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_2: NaN, EXT_ELEM_PROP_3: NaN, EXT_ELEM_PROP_4: NaN, EXT_ELEM_PROP_5: NaN, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +ELEM_PROP_1: 1009 +ELEM_PROP_2: 1009 +ELEM_PROP_3: 1009 +ELEM_PROP_4: 734 +ELEM_PROP_5: 1009 +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 886, 886, 886 ] + + + +set.num_extend_elem_props(): 10 +set.num_props(): 7 +set.num_extend_elem_props(): 10 + + +------------------------------------- + 35 MODFICATIONS +------------------------------------- + +PROP_1: 1.101 +PROP_2: 2.201 +PROP_4: 4.401 +PROP_5: 5.501 +PROP_6: 984 +PROP_7: 434 +PROP_9: 419 + +-------------------- + 0 +-------------------- +{EXT_ELEM_PROP_1: Ooogle 1-0, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_2: Ooogle 2-0, EXT_ELEM_PROP_3: 733, EXT_ELEM_PROP_4: Ooogle 4-0, EXT_ELEM_PROP_5: Ooogle 5-0, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +ELEM_PROP_1: 0.101 +ELEM_PROP_2: 669 +ELEM_PROP_4: 734 +ELEM_PROP_5: 661 +[ 1, 2, 3 ] +[ 11, 12, 13 ] +[ 21, 22, 23 ] +[ 31, 32, 33 ] +[ 41, 42, 43 ] +[ 511, 511, 511 ] +[ 511, 511, 511 ] +[ 886, 886, 886 ] + + +-------------------- + 1 +-------------------- +{EXT_ELEM_PROP_1: NaN, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_2: NaN, EXT_ELEM_PROP_3: NaN, EXT_ELEM_PROP_4: NaN, EXT_ELEM_PROP_5: NaN, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +ELEM_PROP_1: 1006 +ELEM_PROP_2: 1006 +ELEM_PROP_4: 1006 +ELEM_PROP_5: 1006 +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] + + +-------------------- + 2 +-------------------- +{EXT_ELEM_PROP_1: NaN, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_2: NaN, EXT_ELEM_PROP_3: NaN, EXT_ELEM_PROP_4: NaN, EXT_ELEM_PROP_5: NaN, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +ELEM_PROP_1: 1005 +ELEM_PROP_2: 1005 +ELEM_PROP_4: 1005 +ELEM_PROP_5: 1005 +[ 1005, 1005, 1005 ] +[ 1005, 1005, 1005 ] +[ 1005, 1005, 1005 ] +[ 1005, 1005, 1005 ] +[ 1005, 1005, 1005 ] +[ 1005, 1005, 1005 ] +[ 1005, 1005, 1005 ] +[ 1005, 1005, 1005 ] + + +-------------------- + 3 +-------------------- +{EXT_ELEM_PROP_1: NaN, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_2: NaN, EXT_ELEM_PROP_3: NaN, EXT_ELEM_PROP_4: NaN, EXT_ELEM_PROP_5: NaN, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +ELEM_PROP_1: 1003 +ELEM_PROP_2: 1003 +ELEM_PROP_4: 734 +ELEM_PROP_5: 1003 +[ 511, 511, 511 ] +[ 511, 511, 511 ] +[ 511, 511, 511 ] +[ 511, 511, 511 ] +[ 511, 511, 511 ] +[ 511, 511, 511 ] +[ 511, 511, 511 ] +[ 886, 886, 886 ] + + +-------------------- + 4 +-------------------- +{EXT_ELEM_PROP_1: NaN, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_2: NaN, EXT_ELEM_PROP_3: NaN, EXT_ELEM_PROP_4: NaN, EXT_ELEM_PROP_5: NaN, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +ELEM_PROP_1: 1009 +ELEM_PROP_2: 1009 +ELEM_PROP_4: 734 +ELEM_PROP_5: 1009 +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 886, 886, 886 ] + + + +set.prop(PROP_7): 434 + + +------------------------------------- + 40 MODFICATIONS +------------------------------------- + +PROP_1: 1.101 +PROP_2: 2.201 +PROP_4: 4.401 +PROP_5: 5.501 +PROP_6: 984 +PROP_7: 434 +PROP_9: 419 + +-------------------- + 0 +-------------------- +{EXT_ELEM_PROP_1: NaN, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_2: NaN, EXT_ELEM_PROP_3: NaN, EXT_ELEM_PROP_4: NaN, EXT_ELEM_PROP_5: NaN, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +ELEM_PROP_1: 1006 +ELEM_PROP_2: 1006 +ELEM_PROP_4: 1006 +ELEM_PROP_5: 1006 +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] + + +-------------------- + 1 +-------------------- +{EXT_ELEM_PROP_1: NaN, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_2: NaN, EXT_ELEM_PROP_3: NaN, EXT_ELEM_PROP_4: NaN, EXT_ELEM_PROP_5: NaN, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +ELEM_PROP_1: 1009 +ELEM_PROP_2: 1009 +ELEM_PROP_4: 734 +ELEM_PROP_5: 1009 +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 886, 886, 886 ] + + + +set.num_props(): 7 +set.get_extend_elem_prop(EXT_ELEM_PROP_9,0): NaN +set.has_elem_prop(ELEM_PROP_9): 0 + + +------------------------------------- + 45 MODFICATIONS +------------------------------------- + +PROP_1: 1.101 +PROP_2: 2.201 +PROP_4: 4.401 +PROP_5: 5.501 +PROP_6: 984 +PROP_7: 434 +PROP_9: 419 + +-------------------- + 0 +-------------------- +{EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_2: NaN, EXT_ELEM_PROP_3: NaN, EXT_ELEM_PROP_4: NaN, EXT_ELEM_PROP_5: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +ELEM_PROP_1: 1006 +ELEM_PROP_2: 1006 +ELEM_PROP_4: 1006 +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] + + +-------------------- + 1 +-------------------- +{EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_2: NaN, EXT_ELEM_PROP_3: NaN, EXT_ELEM_PROP_4: NaN, EXT_ELEM_PROP_5: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +ELEM_PROP_1: 1009 +ELEM_PROP_2: 1009 +ELEM_PROP_4: 734 +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 886, 886, 886 ] + + + +set.vsize(): 61 +set.elem_prop_index(ELEM_PROP_4): 1 +set.vsize(): 59 + + +------------------------------------- + 50 MODFICATIONS +------------------------------------- + +PROP_1: 1.101 +PROP_2: 2.201 +PROP_4: 4.401 +PROP_5: 5.501 +PROP_6: 984 +PROP_7: 434 +PROP_9: 419 + +-------------------- + 0 +-------------------- +{EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_3: NaN, EXT_ELEM_PROP_4: NaN, EXT_ELEM_PROP_5: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_9: NaN} + +ELEM_PROP_2: 1006 +ELEM_PROP_4: 1006 +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] + + +-------------------- + 1 +-------------------- +{EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_3: NaN, EXT_ELEM_PROP_4: NaN, EXT_ELEM_PROP_5: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_9: NaN} + +ELEM_PROP_2: 1009 +ELEM_PROP_4: 734 +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 886, 886, 886 ] + + +-------------------- + 2 +-------------------- +{EXT_ELEM_PROP_10: -99, EXT_ELEM_PROP_3: NaN, EXT_ELEM_PROP_4: NaN, EXT_ELEM_PROP_5: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_9: NaN} + +ELEM_PROP_2: 1008 +ELEM_PROP_4: 1008 +[ 1008, 1008, 1008 ] +[ 1008, 1008, 1008 ] +[ 1008, 1008, 1008 ] +[ 1008, 1008, 1008 ] +[ 1008, 1008, 1008 ] +[ 1008, 1008, 1008 ] +[ 1008, 1008, 1008 ] +[ 1008, 1008, 1008 ] + + + + + +------------------------------------- + 55 MODFICATIONS +------------------------------------- + +PROP_1: 1.101 +PROP_2: 2.201 +PROP_4: 4.401 +PROP_5: 5.501 +PROP_6: 984 +PROP_7: 434 +PROP_9: 419 + +-------------------- + 0 +-------------------- +{EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_3: NaN, EXT_ELEM_PROP_4: NaN, EXT_ELEM_PROP_5: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_9: NaN} + +ELEM_PROP_2: 1006 +ELEM_PROP_4: 776 +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] + + +-------------------- + 1 +-------------------- +{EXT_ELEM_PROP_10: Boogle 10-1, EXT_ELEM_PROP_3: NaN, EXT_ELEM_PROP_4: NaN, EXT_ELEM_PROP_5: NaN, EXT_ELEM_PROP_7: Boogle 7-1, EXT_ELEM_PROP_9: Boogle 9-1} + +ELEM_PROP_2: 1009 +ELEM_PROP_4: 776 +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] + + +-------------------- + 2 +-------------------- +{EXT_ELEM_PROP_10: 11.031, EXT_ELEM_PROP_3: 3.331, EXT_ELEM_PROP_4: 4.431, EXT_ELEM_PROP_5: 5.531, EXT_ELEM_PROP_7: 7.731, EXT_ELEM_PROP_9: 9.931} + +ELEM_PROP_2: 1009 +ELEM_PROP_4: 1009 +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] + + + +set.size(): 3 +set.num_props(): 7 +set.num_extend_elem_props(): 7 +set.has_elem_prop(ELEM_PROP_7): 0 + + +------------------------------------- + 60 MODFICATIONS +------------------------------------- + +PROP_1: 1.101 +PROP_2: 2.201 +PROP_4: 4.401 +PROP_5: 5.501 +PROP_6: 984 +PROP_7: 434 +PROP_9: 419 + +-------------------- + 0 +-------------------- +{EXT_ELEM_PROP_10: 11.011, EXT_ELEM_PROP_3: 3.311, EXT_ELEM_PROP_4: 4.411, EXT_ELEM_PROP_5: 5.511, EXT_ELEM_PROP_7: 7.711, EXT_ELEM_PROP_8: 8.811, EXT_ELEM_PROP_9: 9.911} + +ELEM_PROP_2: 1005 +ELEM_PROP_4: 1005 +[ 1005, 1005, 1005 ] +[ 1005, 1005, 1005 ] + + +-------------------- + 1 +-------------------- +{EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_3: NaN, EXT_ELEM_PROP_4: NaN, EXT_ELEM_PROP_5: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: -99, EXT_ELEM_PROP_9: NaN} + +ELEM_PROP_2: 1006 +ELEM_PROP_4: 776 +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] + + +-------------------- + 2 +-------------------- +{EXT_ELEM_PROP_10: Boogle 10-1, EXT_ELEM_PROP_3: NaN, EXT_ELEM_PROP_4: NaN, EXT_ELEM_PROP_5: NaN, EXT_ELEM_PROP_7: Boogle 7-1, EXT_ELEM_PROP_8: -99, EXT_ELEM_PROP_9: Boogle 9-1} + +ELEM_PROP_2: 1009 +ELEM_PROP_4: 776 +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] + + +-------------------- + 3 +-------------------- +{EXT_ELEM_PROP_10: 11.031, EXT_ELEM_PROP_3: 3.331, EXT_ELEM_PROP_4: 4.431, EXT_ELEM_PROP_5: 5.531, EXT_ELEM_PROP_7: 7.731, EXT_ELEM_PROP_8: -99, EXT_ELEM_PROP_9: 9.931} + +ELEM_PROP_2: 1009 +ELEM_PROP_4: 1009 +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] + + +-------------------- + 4 +-------------------- +{EXT_ELEM_PROP_10: -99, EXT_ELEM_PROP_3: NaN, EXT_ELEM_PROP_4: NaN, EXT_ELEM_PROP_5: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: -99, EXT_ELEM_PROP_9: NaN} + +ELEM_PROP_2: 1003 +ELEM_PROP_4: 1003 +[ 1003, 1003, 1003 ] +[ 1003, 1003, 1003 ] + + + +set.get_extend_elem_prop(EXT_ELEM_PROP_3,3): 3.331 +set.num_elem_props(): 2 +set.vsize(): 42 + + +------------------------------------- + 65 MODFICATIONS +------------------------------------- + +PROP_1: 1.101 +PROP_2: 2.201 +PROP_4: 4.401 +PROP_5: 5.501 +PROP_6: 984 +PROP_7: 434 +PROP_9: 419 + +-------------------- + 0 +-------------------- +{EXT_ELEM_PROP_10: 11.011, EXT_ELEM_PROP_3: 3.311, EXT_ELEM_PROP_4: 4.411, EXT_ELEM_PROP_5: 5.511, EXT_ELEM_PROP_7: 7.711, EXT_ELEM_PROP_8: 8.811, EXT_ELEM_PROP_9: 9.911} + +[ 1005, 1005, 1005 ] +[ 1005, 1005, 1005 ] + + +-------------------- + 1 +-------------------- +{EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_3: NaN, EXT_ELEM_PROP_4: NaN, EXT_ELEM_PROP_5: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: -99, EXT_ELEM_PROP_9: NaN} + +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] + + +-------------------- + 2 +-------------------- +{EXT_ELEM_PROP_10: Boogle 10-0, EXT_ELEM_PROP_3: NaN, EXT_ELEM_PROP_4: NaN, EXT_ELEM_PROP_5: NaN, EXT_ELEM_PROP_7: Boogle 7-0, EXT_ELEM_PROP_8: Boogle 8-0, EXT_ELEM_PROP_9: Boogle 9-0} + +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] + + +-------------------- + 3 +-------------------- +{EXT_ELEM_PROP_10: 11.031, EXT_ELEM_PROP_3: 3.331, EXT_ELEM_PROP_4: 4.431, EXT_ELEM_PROP_5: 5.531, EXT_ELEM_PROP_7: 7.731, EXT_ELEM_PROP_8: -99, EXT_ELEM_PROP_9: 9.931} + +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] + + +-------------------- + 4 +-------------------- +{EXT_ELEM_PROP_10: -99, EXT_ELEM_PROP_3: NaN, EXT_ELEM_PROP_4: NaN, EXT_ELEM_PROP_5: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: -99, EXT_ELEM_PROP_9: NaN} + +[ 1003, 1003, 1003 ] +[ 1003, 1003, 1003 ] + + + +set.get_extend_elem_prop_header(): [ EXT_ELEM_PROP_10 EXT_ELEM_PROP_3 EXT_ELEM_PROP_4 EXT_ELEM_PROP_5 EXT_ELEM_PROP_7 EXT_ELEM_PROP_8 EXT_ELEM_PROP_9 ] +set.prop_index(PROP_4): 2 +set.num_elem_props(): 0 +set.bsize(): 30 +set.has_extend_elem_prop(EXT_ELEM_PROP_3): 1 +set.num_extend_elem_props(): 6 +set.num_props(): 7 + + +------------------------------------- + 70 MODFICATIONS +------------------------------------- + +PROP_1: 1.101 +PROP_2: 2.201 +PROP_4: 4.401 +PROP_5: 5.501 +PROP_6: 984 +PROP_7: 434 +PROP_9: 419 + +-------------------- + 0 +-------------------- +{EXT_ELEM_PROP_10: 11.011, EXT_ELEM_PROP_3: 3.311, EXT_ELEM_PROP_4: 4.411, EXT_ELEM_PROP_5: 5.511, EXT_ELEM_PROP_8: 8.811, EXT_ELEM_PROP_9: 9.911} + +[ 1005, 1005, 1005 ] +[ 1005, 1005, 1005 ] + + +-------------------- + 1 +-------------------- +{EXT_ELEM_PROP_10: 11.011, EXT_ELEM_PROP_3: 3.311, EXT_ELEM_PROP_4: 4.411, EXT_ELEM_PROP_5: 5.511, EXT_ELEM_PROP_8: 8.811, EXT_ELEM_PROP_9: 9.911} + +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] + + +-------------------- + 2 +-------------------- +{EXT_ELEM_PROP_10: Boogle 10-0, EXT_ELEM_PROP_3: NaN, EXT_ELEM_PROP_4: NaN, EXT_ELEM_PROP_5: NaN, EXT_ELEM_PROP_8: Boogle 8-0, EXT_ELEM_PROP_9: Boogle 9-0} + +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] + + +-------------------- + 3 +-------------------- +{EXT_ELEM_PROP_10: 11.031, EXT_ELEM_PROP_3: 3.331, EXT_ELEM_PROP_4: 4.431, EXT_ELEM_PROP_5: 5.531, EXT_ELEM_PROP_8: -99, EXT_ELEM_PROP_9: 9.931} + +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] + + +-------------------- + 4 +-------------------- +{EXT_ELEM_PROP_10: -99, EXT_ELEM_PROP_3: NaN, EXT_ELEM_PROP_4: NaN, EXT_ELEM_PROP_5: NaN, EXT_ELEM_PROP_8: -99, EXT_ELEM_PROP_9: NaN} + +[ 1003, 1003, 1003 ] +[ 1003, 1003, 1003 ] + + + +set.has_extend_elem_prop(EXT_ELEM_PROP_8): 1 +set.vsize(): 55 + + +------------------------------------- + 75 MODFICATIONS +------------------------------------- + +PROP_1: 1.101 +PROP_2: 2.201 +PROP_4: 4.401 +PROP_5: 5.501 +PROP_6: 984 +PROP_7: 434 +PROP_9: 419 + +-------------------- + 0 +-------------------- +{EXT_ELEM_PROP_10: 11.011, EXT_ELEM_PROP_3: 3.311, EXT_ELEM_PROP_4: 4.411, EXT_ELEM_PROP_5: 5.511, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: 8.811, EXT_ELEM_PROP_9: 9.911} + +[ 1005, 1005, 1005 ] +[ 1005, 1005, 1005 ] + + +-------------------- + 1 +-------------------- +{EXT_ELEM_PROP_10: 11.011, EXT_ELEM_PROP_3: 3.311, EXT_ELEM_PROP_4: 4.411, EXT_ELEM_PROP_5: 5.511, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: 8.811, EXT_ELEM_PROP_9: 9.911} + +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] + + +-------------------- + 2 +-------------------- +{EXT_ELEM_PROP_10: Boogle 10-4, EXT_ELEM_PROP_3: NaN, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: NaN, EXT_ELEM_PROP_6: Boogle 6-4, EXT_ELEM_PROP_7: Boogle 7-4, EXT_ELEM_PROP_8: Boogle 8-4, EXT_ELEM_PROP_9: Boogle 9-4} + +[ 1008, 1008, 1008 ] +[ 1008, 1008, 1008 ] +[ 1008, 1008, 1008 ] +[ 1008, 1008, 1008 ] +[ 1008, 1008, 1008 ] +[ 1008, 1008, 1008 ] + + +-------------------- + 3 +-------------------- +{EXT_ELEM_PROP_10: Boogle 10-0, EXT_ELEM_PROP_3: NaN, EXT_ELEM_PROP_4: NaN, EXT_ELEM_PROP_5: NaN, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: Boogle 8-0, EXT_ELEM_PROP_9: Boogle 9-0} + +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] + + +-------------------- + 4 +-------------------- +{EXT_ELEM_PROP_10: 11.031, EXT_ELEM_PROP_3: 3.331, EXT_ELEM_PROP_4: 4.431, EXT_ELEM_PROP_5: 5.531, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: -99, EXT_ELEM_PROP_9: 9.931} + +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] + + +-------------------- + 5 +-------------------- +{EXT_ELEM_PROP_10: Boogle 10-3, EXT_ELEM_PROP_3: NaN, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: NaN, EXT_ELEM_PROP_6: Boogle 6-3, EXT_ELEM_PROP_7: Boogle 7-3, EXT_ELEM_PROP_8: Boogle 8-3, EXT_ELEM_PROP_9: Boogle 9-3} + +[ 1003, 1003, 1003 ] +[ 1003, 1003, 1003 ] + + + +set.num_props(): 7 + + +------------------------------------- + 80 MODFICATIONS +------------------------------------- + +PROP_1: 1.101 +PROP_2: 2.201 +PROP_4: 4.401 +PROP_5: 5.501 +PROP_6: 984 +PROP_7: 434 +PROP_8: 140 +PROP_9: 419 + +-------------------- + 0 +-------------------- +{EXT_ELEM_PROP_10: 11.011, EXT_ELEM_PROP_3: 3.311, EXT_ELEM_PROP_4: 4.411, EXT_ELEM_PROP_5: 5.511, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: 8.811, EXT_ELEM_PROP_9: 9.911} + +[ 1005, 1005, 1005 ] +[ 1005, 1005, 1005 ] + + +-------------------- + 1 +-------------------- +{EXT_ELEM_PROP_10: 11.011, EXT_ELEM_PROP_3: 3.311, EXT_ELEM_PROP_4: 4.411, EXT_ELEM_PROP_5: 5.511, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: 8.811, EXT_ELEM_PROP_9: 9.911} + +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] + + +-------------------- + 2 +-------------------- +{EXT_ELEM_PROP_10: Boogle 10-4, EXT_ELEM_PROP_3: NaN, EXT_ELEM_PROP_4: 138, EXT_ELEM_PROP_5: NaN, EXT_ELEM_PROP_6: Boogle 6-4, EXT_ELEM_PROP_7: Boogle 7-4, EXT_ELEM_PROP_8: Boogle 8-4, EXT_ELEM_PROP_9: Boogle 9-4} + +[ 1008, 1008, 1008 ] +[ 1008, 1008, 1008 ] +[ 1008, 1008, 1008 ] +[ 1008, 1008, 1008 ] +[ 1008, 1008, 1008 ] +[ 1008, 1008, 1008 ] + + +-------------------- + 3 +-------------------- +{EXT_ELEM_PROP_10: Boogle 10-0, EXT_ELEM_PROP_3: NaN, EXT_ELEM_PROP_4: NaN, EXT_ELEM_PROP_5: NaN, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: Boogle 8-0, EXT_ELEM_PROP_9: Boogle 9-0} + +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] + + +-------------------- + 4 +-------------------- +{EXT_ELEM_PROP_10: 11.031, EXT_ELEM_PROP_3: 3.331, EXT_ELEM_PROP_4: 4.431, EXT_ELEM_PROP_5: 5.531, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: -99, EXT_ELEM_PROP_9: 9.931} + +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] + + +-------------------- + 5 +-------------------- +{EXT_ELEM_PROP_10: 11.061, EXT_ELEM_PROP_3: 3.361, EXT_ELEM_PROP_4: 4.461, EXT_ELEM_PROP_5: 5.561, EXT_ELEM_PROP_6: 6.661, EXT_ELEM_PROP_7: 7.761, EXT_ELEM_PROP_8: 8.861, EXT_ELEM_PROP_9: 9.961} + +[ 1003, 1003, 1003 ] +[ 1003, 1003, 1003 ] + + + +set.get_extend_elem_prop_header(): [ EXT_ELEM_PROP_10 EXT_ELEM_PROP_3 EXT_ELEM_PROP_4 EXT_ELEM_PROP_5 EXT_ELEM_PROP_6 EXT_ELEM_PROP_7 EXT_ELEM_PROP_8 EXT_ELEM_PROP_9 ] + + +------------------------------------- + 85 MODFICATIONS +------------------------------------- + +PROP_1: 1.101 +PROP_2: 2.201 +PROP_4: 4.401 +PROP_6: 984 +PROP_7: 434 +PROP_8: 140 +PROP_9: 419 + +-------------------- + 0 +-------------------- +{EXT_ELEM_PROP_10: 11.011, EXT_ELEM_PROP_2: -99, EXT_ELEM_PROP_3: 3.311, EXT_ELEM_PROP_4: 4.411, EXT_ELEM_PROP_5: 5.511, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: 8.811, EXT_ELEM_PROP_9: 9.911} + +[ 1005, 1005, 1005 ] +[ 1005, 1005, 1005 ] + + +-------------------- + 1 +-------------------- +{EXT_ELEM_PROP_10: 11.011, EXT_ELEM_PROP_2: -99, EXT_ELEM_PROP_3: 3.311, EXT_ELEM_PROP_4: 4.411, EXT_ELEM_PROP_5: 5.511, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: 8.811, EXT_ELEM_PROP_9: 9.911} + +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] + + +-------------------- + 2 +-------------------- +{EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_2: -99, EXT_ELEM_PROP_3: NaN, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: NaN, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 1003, 1003, 1003 ] + + +-------------------- + 3 +-------------------- +{EXT_ELEM_PROP_10: Boogle 10-4, EXT_ELEM_PROP_2: -99, EXT_ELEM_PROP_3: NaN, EXT_ELEM_PROP_4: 138, EXT_ELEM_PROP_5: 667, EXT_ELEM_PROP_6: Boogle 6-4, EXT_ELEM_PROP_7: Boogle 7-4, EXT_ELEM_PROP_8: Boogle 8-4, EXT_ELEM_PROP_9: Boogle 9-4} + +[ 1008, 1008, 1008 ] +[ 1008, 1008, 1008 ] +[ 1008, 1008, 1008 ] +[ 1008, 1008, 1008 ] +[ 1008, 1008, 1008 ] +[ 1008, 1008, 1008 ] + + +-------------------- + 4 +-------------------- +{EXT_ELEM_PROP_10: Boogle 10-0, EXT_ELEM_PROP_2: -99, EXT_ELEM_PROP_3: NaN, EXT_ELEM_PROP_4: NaN, EXT_ELEM_PROP_5: NaN, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: Boogle 8-0, EXT_ELEM_PROP_9: Boogle 9-0} + +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] + + +-------------------- + 5 +-------------------- +{EXT_ELEM_PROP_10: 11.031, EXT_ELEM_PROP_2: -99, EXT_ELEM_PROP_3: 3.331, EXT_ELEM_PROP_4: 4.431, EXT_ELEM_PROP_5: 5.531, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: -99, EXT_ELEM_PROP_9: 9.931} + +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] + + +-------------------- + 6 +-------------------- +{EXT_ELEM_PROP_10: 11.061, EXT_ELEM_PROP_2: -99, EXT_ELEM_PROP_3: 3.361, EXT_ELEM_PROP_4: 4.461, EXT_ELEM_PROP_5: 5.561, EXT_ELEM_PROP_6: 6.661, EXT_ELEM_PROP_7: 7.761, EXT_ELEM_PROP_8: 8.861, EXT_ELEM_PROP_9: 9.961} + +[ 1003, 1003, 1003 ] +[ 1003, 1003, 1003 ] + + + +set.num_extend_elem_props(): 8 + + +------------------------------------- + 90 MODFICATIONS +------------------------------------- + +PROP_1: 1.101 +PROP_2: 2.201 +PROP_4: 4.401 +PROP_6: 984 +PROP_7: 434 +PROP_8: 140 +PROP_9: 419 + +-------------------- + 0 +-------------------- +{EXT_ELEM_PROP_10: 11.011, EXT_ELEM_PROP_2: -99, EXT_ELEM_PROP_3: 3.311, EXT_ELEM_PROP_4: 4.411, EXT_ELEM_PROP_5: 5.511, EXT_ELEM_PROP_6: -99, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: 8.811, EXT_ELEM_PROP_9: 9.911} + +[ 1005, 1005, 1005 ] +[ 1005, 1005, 1005 ] + + + +set.elem_prop_keys(): [] +set.get_extend_elem_prop_header(): [ EXT_ELEM_PROP_10 EXT_ELEM_PROP_2 EXT_ELEM_PROP_3 EXT_ELEM_PROP_4 EXT_ELEM_PROP_5 EXT_ELEM_PROP_6 EXT_ELEM_PROP_7 EXT_ELEM_PROP_8 EXT_ELEM_PROP_9 ] + + +------------------------------------- + 95 MODFICATIONS +------------------------------------- + +PROP_1: 1.101 +PROP_2: 2.201 +PROP_6: 984 +PROP_7: 434 +PROP_8: 140 +PROP_9: 419 + + +set.num_extend_elem_props(): 7 +set.vsize(): 32 +set.prop_index(PROP_9): 7 +set.num_extend_elem_props(): 7 + + +------------------------------------- + 100 MODFICATIONS +------------------------------------- + +PROP_1: 1.101 +PROP_10: 182 +PROP_2: 2.201 +PROP_4: 779 +PROP_5: 902 +PROP_6: 984 +PROP_7: 434 +PROP_8: 140 +PROP_9: 419 + +-------------------- + 0 +-------------------- +{EXT_ELEM_PROP_10: 11.031, EXT_ELEM_PROP_2: 2.231, EXT_ELEM_PROP_3: 3.331, EXT_ELEM_PROP_4: 4.431, EXT_ELEM_PROP_6: 6.631, EXT_ELEM_PROP_7: 7.731, EXT_ELEM_PROP_8: 8.831} + +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] + + + +set.prop_keys(): [ PROP_1 PROP_10 PROP_2 PROP_4 PROP_5 PROP_6 PROP_7 PROP_8 PROP_9 ] +set.has_extend_elem_prop(EXT_ELEM_PROP_2): 1 +set.num_elem_props(): 0 +set.has_extend_elem_prop(EXT_ELEM_PROP_10): 1 +set.num_props(): 10 +set.get_extend_elem_prop(EXT_ELEM_PROP_10,2): NaN + + +------------------------------------- + 105 MODFICATIONS +------------------------------------- + +PROP_1: 1.101 +PROP_10: 182 +PROP_2: 2.201 +PROP_3: 22 +PROP_4: 779 +PROP_5: 902 +PROP_6: 984 +PROP_7: 434 +PROP_8: 140 +PROP_9: 419 + +-------------------- + 0 +-------------------- +{EXT_ELEM_PROP_10: 11.031, EXT_ELEM_PROP_2: 2.231, EXT_ELEM_PROP_3: 3.331, EXT_ELEM_PROP_4: 4.431, EXT_ELEM_PROP_6: 6.631, EXT_ELEM_PROP_7: 7.731, EXT_ELEM_PROP_8: 308} + +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] + + + +set.get_extend_elem_prop(EXT_ELEM_PROP_3,0): 3.331 +set.prop_keys(): [ PROP_1 PROP_10 PROP_2 PROP_3 PROP_4 PROP_5 PROP_6 PROP_7 PROP_8 PROP_9 ] +set.size(): 2 +set.num_extend_elem_props(): 7 +set.prop(PROP_1): 1.101 +set.size(): 2 +set.bsize(): 48 +set.elem_prop_keys(): [] + + +------------------------------------- + 110 MODFICATIONS +------------------------------------- + +PROP_1: 1.101 +PROP_10: 182 +PROP_2: 2.201 +PROP_3: 22 +PROP_4: 779 +PROP_5: 902 +PROP_6: 984 +PROP_7: 434 +PROP_8: 140 +PROP_9: 419 + +-------------------- + 0 +-------------------- +{EXT_ELEM_PROP_10: 11.031, EXT_ELEM_PROP_2: 2.231, EXT_ELEM_PROP_3: 3.331, EXT_ELEM_PROP_4: 4.431, EXT_ELEM_PROP_6: 6.631, EXT_ELEM_PROP_7: 7.731, EXT_ELEM_PROP_8: 308} + +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 179, 179, 179 ] + + +-------------------- + 1 +-------------------- +{EXT_ELEM_PROP_10: 11.051, EXT_ELEM_PROP_2: 2.251, EXT_ELEM_PROP_3: 3.351, EXT_ELEM_PROP_4: 4.451, EXT_ELEM_PROP_6: 6.651, EXT_ELEM_PROP_7: 7.751, EXT_ELEM_PROP_8: 8.851} + +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] +[ 179, 179, 179 ] + + + +set.get_extend_elem_prop(EXT_ELEM_PROP_10,1): 11.051 +set.bsize(): 54 +set.prop(PROP_3): 22 +set.num_extend_elem_props(): 7 +set.num_extend_elem_props(): 7 +set.num_props(): 10 + + +------------------------------------- + 115 MODFICATIONS +------------------------------------- + +PROP_1: 1.101 +PROP_10: 182 +PROP_3: 22 +PROP_4: 779 +PROP_5: 902 +PROP_6: 984 +PROP_7: 434 +PROP_8: 140 +PROP_9: 419 + +-------------------- + 0 +-------------------- +{EXT_ELEM_PROP_10: 11.051, EXT_ELEM_PROP_2: 2.251, EXT_ELEM_PROP_3: 3.351, EXT_ELEM_PROP_4: 4.451, EXT_ELEM_PROP_6: 6.651, EXT_ELEM_PROP_7: 7.751, EXT_ELEM_PROP_8: 8.851} + +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] +[ 1006, 1006, 1006 ] +[ 179, 179, 179 ] + + +-------------------- + 1 +-------------------- +{EXT_ELEM_PROP_10: 11.041, EXT_ELEM_PROP_2: 2.241, EXT_ELEM_PROP_3: 3.341, EXT_ELEM_PROP_4: 4.441, EXT_ELEM_PROP_6: 6.641, EXT_ELEM_PROP_7: 7.741, EXT_ELEM_PROP_8: 8.841} + +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] + + +-------------------- + 2 +-------------------- +{EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_2: -99, EXT_ELEM_PROP_3: NaN, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_6: -99, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: -99} + +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] + + + +set.elem_prop_keys(): [] + + +------------------------------------- + 120 MODFICATIONS +------------------------------------- + +PROP_1: 1.101 +PROP_10: 182 +PROP_3: 22 +PROP_4: 779 +PROP_5: 902 +PROP_6: 984 +PROP_7: 434 +PROP_8: 140 +PROP_9: 419 + +-------------------- + 0 +-------------------- +{EXT_ELEM_PROP_10: 11.041, EXT_ELEM_PROP_2: 2.241, EXT_ELEM_PROP_3: 3.341, EXT_ELEM_PROP_4: 4.441, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: 6.641, EXT_ELEM_PROP_7: 7.741, EXT_ELEM_PROP_8: 8.841} + +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] + + +-------------------- + 1 +-------------------- +{EXT_ELEM_PROP_10: Boogle 10-4, EXT_ELEM_PROP_2: -99, EXT_ELEM_PROP_3: NaN, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: Boogle 6-4, EXT_ELEM_PROP_7: Boogle 7-4, EXT_ELEM_PROP_8: Boogle 8-4} + +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] + + + +set.num_elem_props(): 0 +set.prop_index(PROP_10): 1 +set.size(): 2 + + +------------------------------------- + 125 MODFICATIONS +------------------------------------- + +PROP_1: 1.101 +PROP_10: 182 +PROP_3: 22 +PROP_4: 779 +PROP_5: 902 +PROP_6: 984 +PROP_7: 434 +PROP_9: 419 + +-------------------- + 0 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: 11.041, EXT_ELEM_PROP_2: 2.241, EXT_ELEM_PROP_3: 3.341, EXT_ELEM_PROP_4: 4.441, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: 6.641, EXT_ELEM_PROP_8: 8.841} + +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] + + +-------------------- + 1 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: Boogle 10-4, EXT_ELEM_PROP_2: -99, EXT_ELEM_PROP_3: NaN, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: Boogle 6-4, EXT_ELEM_PROP_8: Boogle 8-4} + +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] + + + +set.size(): 2 +set.get_extend_elem_prop(EXT_ELEM_PROP_2,0): 2.241 + + +------------------------------------- + 130 MODFICATIONS +------------------------------------- + +PROP_1: 1.101 +PROP_10: 182 +PROP_3: 22 +PROP_4: 779 +PROP_5: 902 +PROP_6: 984 +PROP_7: 434 +PROP_9: 419 + +-------------------- + 0 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: 11.041, EXT_ELEM_PROP_2: 2.241, EXT_ELEM_PROP_4: 4.441, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: 6.641, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: 8.841, EXT_ELEM_PROP_9: NaN} + +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] + + +-------------------- + 1 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_2: -99, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 1004, 1004, 1004 ] +[ 1004, 1004, 1004 ] +[ 1004, 1004, 1004 ] +[ 1004, 1004, 1004 ] +[ 1004, 1004, 1004 ] + + +-------------------- + 2 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: Boogle 10-4, EXT_ELEM_PROP_2: -99, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: Boogle 6-4, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: Boogle 8-4, EXT_ELEM_PROP_9: NaN} + +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] + + + +set.num_elem_props(): 0 +set.size(): 3 +set.num_elem_props(): 0 +set.elem_prop_keys(): [] + + +------------------------------------- + 135 MODFICATIONS +------------------------------------- + +PROP_1: 1.101 +PROP_10: 182 +PROP_3: 22 +PROP_4: 779 +PROP_5: 902 +PROP_6: 984 +PROP_7: 434 +PROP_9: 419 + +-------------------- + 0 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: 11.041, EXT_ELEM_PROP_2: 2.241, EXT_ELEM_PROP_4: 4.441, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: 6.641, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: 8.841, EXT_ELEM_PROP_9: NaN} + +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 192, 192, 192 ] +[ 192, 192, 192 ] +[ 192, 192, 192 ] + + +-------------------- + 1 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_2: -99, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 1010, 1010, 1010 ] +[ 1010, 1010, 1010 ] +[ 1010, 1010, 1010 ] +[ 1010, 1010, 1010 ] +[ 1010, 1010, 1010 ] +[ 1010, 1010, 1010 ] +[ 1010, 1010, 1010 ] + + +-------------------- + 2 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_2: -99, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 1004, 1004, 1004 ] +[ 1004, 1004, 1004 ] +[ 1004, 1004, 1004 ] +[ 1004, 1004, 1004 ] +[ 1004, 1004, 1004 ] +[ 192, 192, 192 ] +[ 192, 192, 192 ] + + +-------------------- + 3 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: Boogle 10-4, EXT_ELEM_PROP_2: -99, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: Boogle 6-4, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: Boogle 8-4, EXT_ELEM_PROP_9: NaN} + +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 192, 192, 192 ] +[ 192, 192, 192 ] +[ 192, 192, 192 ] + + +-------------------- + 4 +-------------------- +{EXT_ELEM_PROP_1: 1.141, EXT_ELEM_PROP_10: 11.041, EXT_ELEM_PROP_2: 2.241, EXT_ELEM_PROP_4: 4.441, EXT_ELEM_PROP_5: 5.541, EXT_ELEM_PROP_6: 6.641, EXT_ELEM_PROP_7: 7.741, EXT_ELEM_PROP_8: 8.841, EXT_ELEM_PROP_9: 9.941} + +[ 1008, 1008, 1008 ] +[ 1008, 1008, 1008 ] +[ 1008, 1008, 1008 ] +[ 1008, 1008, 1008 ] +[ 192, 192, 192 ] +[ 192, 192, 192 ] +[ 192, 192, 192 ] + + +-------------------- + 5 +-------------------- +{EXT_ELEM_PROP_1: 1.181, EXT_ELEM_PROP_10: 11.081, EXT_ELEM_PROP_2: 2.281, EXT_ELEM_PROP_4: 4.481, EXT_ELEM_PROP_5: 5.581, EXT_ELEM_PROP_6: 6.681, EXT_ELEM_PROP_7: 7.781, EXT_ELEM_PROP_8: 8.881, EXT_ELEM_PROP_9: 9.981} + +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 192, 192, 192 ] +[ 192, 192, 192 ] +[ 192, 192, 192 ] + + +-------------------- + 6 +-------------------- +{EXT_ELEM_PROP_1: 1.131, EXT_ELEM_PROP_10: 11.031, EXT_ELEM_PROP_2: 2.231, EXT_ELEM_PROP_4: 4.431, EXT_ELEM_PROP_5: 5.531, EXT_ELEM_PROP_6: 6.631, EXT_ELEM_PROP_7: 7.731, EXT_ELEM_PROP_8: 8.831, EXT_ELEM_PROP_9: 9.931} + +[ 1007, 1007, 1007 ] +[ 1007, 1007, 1007 ] +[ 1007, 1007, 1007 ] +[ 1007, 1007, 1007 ] +[ 1007, 1007, 1007 ] +[ 1007, 1007, 1007 ] +[ 192, 192, 192 ] + + + +set.prop(PROP_3): 22 +set.get_extend_elem_prop_header(): [ EXT_ELEM_PROP_1 EXT_ELEM_PROP_10 EXT_ELEM_PROP_2 EXT_ELEM_PROP_4 EXT_ELEM_PROP_5 EXT_ELEM_PROP_6 EXT_ELEM_PROP_7 EXT_ELEM_PROP_8 EXT_ELEM_PROP_9 ] +set.size(): 7 +set.has_elem_prop(ELEM_PROP_3): 0 +set.vsize(): 176 +set.bsize(): 168 +set.prop(PROP_5): 902 +set.has_extend_elem_prop(EXT_ELEM_PROP_4): 1 +set.bsize(): 168 + + +------------------------------------- + 140 MODFICATIONS +------------------------------------- + +PROP_1: 1.101 +PROP_10: 182 +PROP_3: 22 +PROP_4: 779 +PROP_5: 902 +PROP_6: 984 +PROP_7: 434 +PROP_9: 419 + +-------------------- + 0 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_2: -99, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] + + +-------------------- + 1 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: 11.041, EXT_ELEM_PROP_2: 2.241, EXT_ELEM_PROP_4: 4.441, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: 6.641, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: 8.841, EXT_ELEM_PROP_9: NaN} + +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 192, 192, 192 ] +[ 192, 192, 192 ] + + +-------------------- + 2 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_2: -99, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 1010, 1010, 1010 ] +[ 1010, 1010, 1010 ] +[ 1010, 1010, 1010 ] +[ 1010, 1010, 1010 ] +[ 1010, 1010, 1010 ] +[ 1010, 1010, 1010 ] + + +-------------------- + 3 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_2: -99, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 1004, 1004, 1004 ] +[ 1004, 1004, 1004 ] +[ 1004, 1004, 1004 ] +[ 1004, 1004, 1004 ] +[ 1004, 1004, 1004 ] +[ 192, 192, 192 ] + + +-------------------- + 4 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: Boogle 10-4, EXT_ELEM_PROP_2: -99, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: Boogle 6-4, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: Boogle 8-4, EXT_ELEM_PROP_9: NaN} + +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 192, 192, 192 ] +[ 192, 192, 192 ] + + +-------------------- + 5 +-------------------- +{EXT_ELEM_PROP_1: 1.141, EXT_ELEM_PROP_10: 11.041, EXT_ELEM_PROP_2: 2.241, EXT_ELEM_PROP_4: 4.441, EXT_ELEM_PROP_5: 5.541, EXT_ELEM_PROP_6: 6.641, EXT_ELEM_PROP_7: 7.741, EXT_ELEM_PROP_8: 8.841, EXT_ELEM_PROP_9: 9.941} + +[ 1008, 1008, 1008 ] +[ 1008, 1008, 1008 ] +[ 1008, 1008, 1008 ] +[ 1008, 1008, 1008 ] +[ 192, 192, 192 ] +[ 192, 192, 192 ] + + +-------------------- + 6 +-------------------- +{EXT_ELEM_PROP_1: 1.181, EXT_ELEM_PROP_10: 11.081, EXT_ELEM_PROP_2: 2.281, EXT_ELEM_PROP_4: 4.481, EXT_ELEM_PROP_5: 5.581, EXT_ELEM_PROP_6: 6.681, EXT_ELEM_PROP_7: 7.781, EXT_ELEM_PROP_8: 8.881, EXT_ELEM_PROP_9: 9.981} + +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 192, 192, 192 ] +[ 192, 192, 192 ] + + +-------------------- + 7 +-------------------- +{EXT_ELEM_PROP_1: 1.131, EXT_ELEM_PROP_10: 11.031, EXT_ELEM_PROP_2: 2.231, EXT_ELEM_PROP_4: 4.431, EXT_ELEM_PROP_5: 5.531, EXT_ELEM_PROP_6: 6.631, EXT_ELEM_PROP_7: 7.731, EXT_ELEM_PROP_8: 8.831, EXT_ELEM_PROP_9: 9.931} + +[ 1007, 1007, 1007 ] +[ 1007, 1007, 1007 ] +[ 1007, 1007, 1007 ] +[ 1007, 1007, 1007 ] +[ 1007, 1007, 1007 ] +[ 1007, 1007, 1007 ] + + + +set.get_extend_elem_prop_header(): [ EXT_ELEM_PROP_1 EXT_ELEM_PROP_10 EXT_ELEM_PROP_2 EXT_ELEM_PROP_4 EXT_ELEM_PROP_5 EXT_ELEM_PROP_6 EXT_ELEM_PROP_7 EXT_ELEM_PROP_8 EXT_ELEM_PROP_9 ] +set.num_extend_elem_props(): 9 +set.elem_prop_keys(): [] +set.prop_index(PROP_3): 2 + + +------------------------------------- + 145 MODFICATIONS +------------------------------------- + +PROP_1: 1.101 +PROP_10: 182 +PROP_3: 22 +PROP_4: 779 +PROP_5: 902 +PROP_6: 984 +PROP_7: 434 +PROP_9: 419 + +-------------------- + 0 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_2: -99, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] + + +-------------------- + 1 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: 11.041, EXT_ELEM_PROP_2: 2.241, EXT_ELEM_PROP_4: 4.441, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: 6.641, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: 8.841, EXT_ELEM_PROP_9: NaN} + +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 192, 192, 192 ] +[ 192, 192, 192 ] + + +-------------------- + 2 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_2: -99, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 1010, 1010, 1010 ] +[ 1010, 1010, 1010 ] +[ 1010, 1010, 1010 ] +[ 1010, 1010, 1010 ] +[ 1010, 1010, 1010 ] +[ 1010, 1010, 1010 ] + + +-------------------- + 3 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_2: -99, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 1004, 1004, 1004 ] +[ 1004, 1004, 1004 ] +[ 1004, 1004, 1004 ] +[ 1004, 1004, 1004 ] +[ 1004, 1004, 1004 ] +[ 192, 192, 192 ] + + +-------------------- + 4 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: Boogle 10-4, EXT_ELEM_PROP_2: -99, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: Boogle 6-4, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: Boogle 8-4, EXT_ELEM_PROP_9: NaN} + +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 192, 192, 192 ] +[ 192, 192, 192 ] + + +-------------------- + 5 +-------------------- +{EXT_ELEM_PROP_1: 1.141, EXT_ELEM_PROP_10: 11.041, EXT_ELEM_PROP_2: 2.241, EXT_ELEM_PROP_4: 4.441, EXT_ELEM_PROP_5: 5.541, EXT_ELEM_PROP_6: 6.641, EXT_ELEM_PROP_7: 7.741, EXT_ELEM_PROP_8: 8.841, EXT_ELEM_PROP_9: 9.941} + +[ 1008, 1008, 1008 ] +[ 1008, 1008, 1008 ] +[ 1008, 1008, 1008 ] +[ 1008, 1008, 1008 ] +[ 192, 192, 192 ] +[ 192, 192, 192 ] + + +-------------------- + 6 +-------------------- +{EXT_ELEM_PROP_1: 1.111, EXT_ELEM_PROP_10: 11.011, EXT_ELEM_PROP_2: 2.211, EXT_ELEM_PROP_4: 4.411, EXT_ELEM_PROP_5: 5.511, EXT_ELEM_PROP_6: 6.611, EXT_ELEM_PROP_7: 7.711, EXT_ELEM_PROP_8: 8.811, EXT_ELEM_PROP_9: 9.911} + +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 192, 192, 192 ] +[ 192, 192, 192 ] + + +-------------------- + 7 +-------------------- +{EXT_ELEM_PROP_1: 1.131, EXT_ELEM_PROP_10: 11.031, EXT_ELEM_PROP_2: 2.231, EXT_ELEM_PROP_4: 4.431, EXT_ELEM_PROP_5: 5.531, EXT_ELEM_PROP_6: 6.631, EXT_ELEM_PROP_7: 7.731, EXT_ELEM_PROP_8: 8.831, EXT_ELEM_PROP_9: 9.931} + +[ 1007, 1007, 1007 ] +[ 1007, 1007, 1007 ] +[ 1007, 1007, 1007 ] +[ 1007, 1007, 1007 ] +[ 1007, 1007, 1007 ] +[ 1007, 1007, 1007 ] + + +-------------------- + 8 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_2: -99, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 561, 561, 561 ] +[ 561, 561, 561 ] +[ 561, 561, 561 ] +[ 561, 561, 561 ] +[ 561, 561, 561 ] +[ 561, 561, 561 ] + + +-------------------- + 9 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_2: -99, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] + + + +set.num_props(): 8 + + +------------------------------------- + 150 MODFICATIONS +------------------------------------- + +PROP_1: 1.101 +PROP_10: 182 +PROP_3: 22 +PROP_4: 779 +PROP_5: 902 +PROP_6: 984 +PROP_7: 434 +PROP_9: 419 + +-------------------- + 0 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_2: -99, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] + + +-------------------- + 1 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: 11.041, EXT_ELEM_PROP_2: 2.241, EXT_ELEM_PROP_4: 4.441, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: 6.641, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: 8.841, EXT_ELEM_PROP_9: NaN} + +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 192, 192, 192 ] +[ 192, 192, 192 ] + + +-------------------- + 2 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_2: -99, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 1010, 1010, 1010 ] +[ 1010, 1010, 1010 ] +[ 1010, 1010, 1010 ] +[ 1010, 1010, 1010 ] +[ 1010, 1010, 1010 ] +[ 1010, 1010, 1010 ] + + +-------------------- + 3 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_2: -99, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 1004, 1004, 1004 ] +[ 1004, 1004, 1004 ] +[ 1004, 1004, 1004 ] +[ 1004, 1004, 1004 ] +[ 1004, 1004, 1004 ] +[ 192, 192, 192 ] + + +-------------------- + 4 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: Boogle 10-4, EXT_ELEM_PROP_2: -99, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: Boogle 6-4, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: Boogle 8-4, EXT_ELEM_PROP_9: NaN} + +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 192, 192, 192 ] +[ 192, 192, 192 ] + + +-------------------- + 5 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_2: -99, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] + + +-------------------- + 6 +-------------------- +{EXT_ELEM_PROP_1: 1.141, EXT_ELEM_PROP_10: 11.041, EXT_ELEM_PROP_2: 2.241, EXT_ELEM_PROP_4: 4.441, EXT_ELEM_PROP_5: 5.541, EXT_ELEM_PROP_6: 6.641, EXT_ELEM_PROP_7: 7.741, EXT_ELEM_PROP_8: 8.841, EXT_ELEM_PROP_9: 9.941} + +[ 1008, 1008, 1008 ] +[ 1008, 1008, 1008 ] +[ 1008, 1008, 1008 ] +[ 1008, 1008, 1008 ] +[ 192, 192, 192 ] +[ 192, 192, 192 ] + + +-------------------- + 7 +-------------------- +{EXT_ELEM_PROP_1: 1.111, EXT_ELEM_PROP_10: 11.011, EXT_ELEM_PROP_2: 2.211, EXT_ELEM_PROP_4: 4.411, EXT_ELEM_PROP_5: 5.511, EXT_ELEM_PROP_6: 6.611, EXT_ELEM_PROP_7: 7.711, EXT_ELEM_PROP_8: 8.811, EXT_ELEM_PROP_9: 9.911} + +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 1001, 1001, 1001 ] +[ 192, 192, 192 ] +[ 192, 192, 192 ] + + +-------------------- + 8 +-------------------- +{EXT_ELEM_PROP_1: 1.131, EXT_ELEM_PROP_10: 11.031, EXT_ELEM_PROP_2: 2.231, EXT_ELEM_PROP_4: 4.431, EXT_ELEM_PROP_5: 5.531, EXT_ELEM_PROP_6: 6.631, EXT_ELEM_PROP_7: 7.731, EXT_ELEM_PROP_8: 8.831, EXT_ELEM_PROP_9: 9.931} + +[ 1007, 1007, 1007 ] +[ 1007, 1007, 1007 ] +[ 1007, 1007, 1007 ] +[ 1007, 1007, 1007 ] +[ 1007, 1007, 1007 ] +[ 1007, 1007, 1007 ] + + +-------------------- + 9 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_2: -99, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 561, 561, 561 ] +[ 561, 561, 561 ] +[ 561, 561, 561 ] +[ 561, 561, 561 ] +[ 561, 561, 561 ] +[ 561, 561, 561 ] + + +-------------------- + 10 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_2: -99, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] + + +-------------------- + 11 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_2: -99, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 1008, 1008, 1008 ] +[ 1008, 1008, 1008 ] +[ 1008, 1008, 1008 ] +[ 1008, 1008, 1008 ] +[ 1008, 1008, 1008 ] +[ 1008, 1008, 1008 ] + + +-------------------- + 12 +-------------------- +{EXT_ELEM_PROP_1: 1.151, EXT_ELEM_PROP_10: 11.051, EXT_ELEM_PROP_2: 2.251, EXT_ELEM_PROP_4: 4.451, EXT_ELEM_PROP_5: 5.551, EXT_ELEM_PROP_6: 6.651, EXT_ELEM_PROP_7: 7.751, EXT_ELEM_PROP_8: 8.851, EXT_ELEM_PROP_9: 9.951} + +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] + + + +set.elem_prop_keys(): [] +set.has_elem_prop(ELEM_PROP_10): 0 +set.vsize(): 242 +set.has_prop(PROP_8): 0 + + +------------------------------------- + 155 MODFICATIONS +------------------------------------- + +PROP_1: 1.101 +PROP_10: 182 +PROP_2: 692 +PROP_3: 22 +PROP_4: 779 +PROP_5: 902 +PROP_6: 984 +PROP_7: 434 +PROP_8: 147 +PROP_9: 419 + +-------------------- + 0 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_2: -99, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] + + +-------------------- + 1 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: 11.041, EXT_ELEM_PROP_2: 2.241, EXT_ELEM_PROP_4: 4.441, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: 6.641, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: 8.841, EXT_ELEM_PROP_9: NaN} + +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] + + +-------------------- + 2 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_2: -99, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 1010, 1010, 1010 ] +[ 1010, 1010, 1010 ] + + +-------------------- + 3 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_2: -99, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 1004, 1004, 1004 ] +[ 1004, 1004, 1004 ] + + +-------------------- + 4 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: Boogle 10-4, EXT_ELEM_PROP_2: -99, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: Boogle 6-4, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: Boogle 8-4, EXT_ELEM_PROP_9: NaN} + +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] + + +-------------------- + 5 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_2: -99, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 245, 245, 245 ] +[ 245, 245, 245 ] + + +-------------------- + 6 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_2: -99, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 245, 245, 245 ] +[ 245, 245, 245 ] + + +-------------------- + 7 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_2: -99, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 245, 245, 245 ] +[ 245, 245, 245 ] + + + +set.get_extend_elem_prop(EXT_ELEM_PROP_5,3): -99 + + +------------------------------------- + 160 MODFICATIONS +------------------------------------- + +PROP_1: 1.101 +PROP_10: 182 +PROP_2: 692 +PROP_3: 22 +PROP_4: 779 +PROP_5: 902 +PROP_6: 984 +PROP_7: 434 +PROP_8: 147 +PROP_9: 419 + +-------------------- + 0 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_2: 640, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] + + +-------------------- + 1 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: 11.041, EXT_ELEM_PROP_2: 2.241, EXT_ELEM_PROP_4: 4.441, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: 6.641, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] + + +-------------------- + 2 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_2: -99, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 1010, 1010, 1010 ] +[ 1010, 1010, 1010 ] + + +-------------------- + 3 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_2: -99, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 1004, 1004, 1004 ] +[ 1004, 1004, 1004 ] + + +-------------------- + 4 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: Boogle 10-4, EXT_ELEM_PROP_2: -99, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: Boogle 6-4, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] + + +-------------------- + 5 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_2: -99, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 245, 245, 245 ] +[ 245, 245, 245 ] + + +-------------------- + 6 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_2: -99, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 245, 245, 245 ] +[ 245, 245, 245 ] + + +-------------------- + 7 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_2: -99, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 245, 245, 245 ] +[ 245, 245, 245 ] + + + +set.num_props(): 10 +set.has_extend_elem_prop(EXT_ELEM_PROP_9): 1 +set.elem_prop_keys(): [] +set.prop_keys(): [ PROP_1 PROP_10 PROP_2 PROP_3 PROP_4 PROP_5 PROP_6 PROP_7 PROP_8 PROP_9 ] +set.prop(PROP_9): 419 +set.size(): 8 + + +------------------------------------- + 165 MODFICATIONS +------------------------------------- + +PROP_1: 1.101 +PROP_10: 182 +PROP_2: 692 +PROP_3: 22 +PROP_4: 779 +PROP_5: 902 +PROP_6: 984 +PROP_7: 434 +PROP_8: 147 +PROP_9: 419 + +-------------------- + 0 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] + + +-------------------- + 1 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: 11.041, EXT_ELEM_PROP_4: 4.441, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: 6.641, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] + + +-------------------- + 2 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 1010, 1010, 1010 ] +[ 1010, 1010, 1010 ] + + +-------------------- + 3 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 1004, 1004, 1004 ] +[ 1004, 1004, 1004 ] + + +-------------------- + 4 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: Boogle 10-4, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: Boogle 6-4, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] + + +-------------------- + 5 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 245, 245, 245 ] +[ 245, 245, 245 ] + + +-------------------- + 6 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 245, 245, 245 ] +[ 245, 245, 245 ] + + +-------------------- + 7 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 245, 245, 245 ] +[ 245, 245, 245 ] + + + + + +------------------------------------- + 170 MODFICATIONS +------------------------------------- + +PROP_1: 1.101 +PROP_10: 182 +PROP_2: 692 +PROP_3: 22 +PROP_4: 779 +PROP_5: 902 +PROP_6: 984 +PROP_7: 434 + +-------------------- + 0 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] + + +-------------------- + 1 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: 11.041, EXT_ELEM_PROP_4: 4.441, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 1002, 1002, 1002 ] +[ 1002, 1002, 1002 ] + + +-------------------- + 2 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 1010, 1010, 1010 ] +[ 1010, 1010, 1010 ] + + +-------------------- + 3 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 1004, 1004, 1004 ] +[ 1004, 1004, 1004 ] + + +-------------------- + 4 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: Boogle 10-4, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 1009, 1009, 1009 ] +[ 1009, 1009, 1009 ] + + +-------------------- + 5 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 245, 245, 245 ] +[ 245, 245, 245 ] + + +-------------------- + 6 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 245, 245, 245 ] +[ 245, 245, 245 ] + + +-------------------- + 7 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 245, 245, 245 ] +[ 245, 245, 245 ] + + +-------------------- + 8 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_4: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 1007, 1007, 1007 ] +[ 1007, 1007, 1007 ] + + + +set.num_props(): 8 +set.size(): 1 +set.prop_index(PROP_3): 3 +set.get_extend_elem_prop_header(): [ EXT_ELEM_PROP_1 EXT_ELEM_PROP_10 EXT_ELEM_PROP_4 EXT_ELEM_PROP_5 EXT_ELEM_PROP_7 EXT_ELEM_PROP_8 EXT_ELEM_PROP_9 ] + + +------------------------------------- + 175 MODFICATIONS +------------------------------------- + +PROP_1: 1.101 +PROP_10: 182 +PROP_2: 692 +PROP_3: 22 +PROP_4: 779 +PROP_5: 902 +PROP_6: 984 +PROP_7: 434 + + +set.num_extend_elem_props(): 6 + + +------------------------------------- + 180 MODFICATIONS +------------------------------------- + +PROP_1: 1.101 +PROP_10: 182 +PROP_2: 692 +PROP_3: 22 +PROP_4: 779 +PROP_5: 902 +PROP_6: 984 +PROP_7: 434 + + +set.bsize(): 0 +set.elem_prop_keys(): [] +set.bsize(): 0 +set.size(): 0 +set.prop_keys(): [ PROP_1 PROP_10 PROP_2 PROP_3 PROP_4 PROP_5 PROP_6 PROP_7 ] +set.elem_prop_keys(): [] +set.prop_keys(): [ PROP_1 PROP_10 PROP_2 PROP_3 PROP_4 PROP_5 PROP_6 PROP_7 PROP_8 PROP_9 ] + + +------------------------------------- + 185 MODFICATIONS +------------------------------------- + +PROP_1: 1.101 +PROP_10: 182 +PROP_2: 692 +PROP_3: 22 +PROP_4: 779 +PROP_5: 902 +PROP_6: 984 +PROP_7: 434 +PROP_8: 859 +PROP_9: 835 + + +set.has_prop(PROP_9): 1 +set.get_extend_elem_prop_header(): [ EXT_ELEM_PROP_1 EXT_ELEM_PROP_10 EXT_ELEM_PROP_5 EXT_ELEM_PROP_8 EXT_ELEM_PROP_9 ] +set.has_prop(PROP_2): 1 +set.has_extend_elem_prop(EXT_ELEM_PROP_8): 1 +set.has_extend_elem_prop(EXT_ELEM_PROP_3): 0 +set.num_extend_elem_props(): 5 +set.bsize(): 0 +set.get_extend_elem_prop(EXT_ELEM_PROP_9,6): NaN + + +------------------------------------- + 190 MODFICATIONS +------------------------------------- + +PROP_1: 1.101 +PROP_10: 182 +PROP_2: 692 +PROP_3: 22 +PROP_4: 779 +PROP_5: 902 +PROP_6: 984 +PROP_7: 434 +PROP_8: 859 +PROP_9: 835 + +-------------------- + 0 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_7: -99, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] + + +-------------------- + 1 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_7: -99, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 1005, 1005, 1005 ] +[ 1005, 1005, 1005 ] +[ 1005, 1005, 1005 ] +[ 1005, 1005, 1005 ] + + +-------------------- + 2 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_7: -99, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] + + +-------------------- + 3 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_7: -99, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] + + +-------------------- + 4 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_7: -99, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] + + +-------------------- + 5 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_7: -99, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] + + +-------------------- + 6 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_7: -99, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] + + +-------------------- + 7 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_7: -99, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] + + +-------------------- + 8 +-------------------- +{EXT_ELEM_PROP_1: 1.171, EXT_ELEM_PROP_10: 11.071, EXT_ELEM_PROP_5: 5.571, EXT_ELEM_PROP_7: 7.771, EXT_ELEM_PROP_8: 8.871, EXT_ELEM_PROP_9: 9.971} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] + + +-------------------- + 9 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_7: -99, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] + + + +set.bsize(): 270 +set.prop_keys(): [ PROP_1 PROP_10 PROP_2 PROP_3 PROP_4 PROP_5 PROP_6 PROP_7 PROP_8 PROP_9 ] + + +------------------------------------- + 195 MODFICATIONS +------------------------------------- + +PROP_1: 1.101 +PROP_10: 182 +PROP_2: 692 +PROP_3: 22 +PROP_4: 779 +PROP_5: 902 +PROP_6: 153 +PROP_7: 434 +PROP_8: 859 +PROP_9: 835 + +-------------------- + 0 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_7: -99, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] + + +-------------------- + 1 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_7: -99, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 1005, 1005, 1005 ] +[ 1005, 1005, 1005 ] +[ 1005, 1005, 1005 ] +[ 1005, 1005, 1005 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] + + +-------------------- + 2 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_7: 493, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] + + +-------------------- + 3 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_7: -99, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] + + +-------------------- + 4 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_7: -99, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] + + +-------------------- + 5 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_7: -99, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] + + +-------------------- + 6 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_7: -99, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] + + +-------------------- + 7 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_7: -99, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] + + +-------------------- + 8 +-------------------- +{EXT_ELEM_PROP_1: 1.171, EXT_ELEM_PROP_10: 11.071, EXT_ELEM_PROP_5: 5.571, EXT_ELEM_PROP_7: 7.771, EXT_ELEM_PROP_8: 8.871, EXT_ELEM_PROP_9: 9.971} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] + + +-------------------- + 9 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_7: -99, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] + + + +set.num_extend_elem_props(): 6 +set.prop_index(PROP_3): 3 +set.get_extend_elem_prop(EXT_ELEM_PROP_5,4): -99 +set.prop_index(PROP_10): 1 + + +------------------------------------- + 200 MODFICATIONS +------------------------------------- + +PROP_1: 1.101 +PROP_10: 182 +PROP_2: 692 +PROP_3: 22 +PROP_4: 779 +PROP_5: 902 +PROP_6: 153 +PROP_7: 434 +PROP_8: 859 +PROP_9: 835 + +-------------------- + 0 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: -99, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] + + +-------------------- + 1 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: -99, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 1005, 1005, 1005 ] +[ 1005, 1005, 1005 ] +[ 1005, 1005, 1005 ] +[ 1005, 1005, 1005 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] + + +-------------------- + 2 +-------------------- +{EXT_ELEM_PROP_1: 1.111, EXT_ELEM_PROP_10: 11.011, EXT_ELEM_PROP_5: 5.511, EXT_ELEM_PROP_6: 6.611, EXT_ELEM_PROP_7: 7.711, EXT_ELEM_PROP_8: 8.811, EXT_ELEM_PROP_9: 9.911} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] + + +-------------------- + 3 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: -99, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] + + +-------------------- + 4 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: -99, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] + + +-------------------- + 5 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: -99, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] + + +-------------------- + 6 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: -99, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] + + +-------------------- + 7 +-------------------- +{EXT_ELEM_PROP_1: 1.171, EXT_ELEM_PROP_10: 11.071, EXT_ELEM_PROP_5: 5.571, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: 7.771, EXT_ELEM_PROP_8: 8.871, EXT_ELEM_PROP_9: 9.971} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] + + + +set.num_props(): 10 +set.size(): 8 +set.has_extend_elem_prop(EXT_ELEM_PROP_2): 0 +set.has_extend_elem_prop(EXT_ELEM_PROP_1): 1 +set.get_extend_elem_prop(EXT_ELEM_PROP_9,3): NaN +set.get_extend_elem_prop_header(): [ EXT_ELEM_PROP_1 EXT_ELEM_PROP_10 EXT_ELEM_PROP_5 EXT_ELEM_PROP_6 EXT_ELEM_PROP_7 EXT_ELEM_PROP_8 EXT_ELEM_PROP_9 ] +set.has_prop(PROP_2): 1 +set.num_elem_props(): 0 +set.has_prop(PROP_1): 1 +set.num_extend_elem_props(): 7 +set.get_extend_elem_prop_header(): [ EXT_ELEM_PROP_1 EXT_ELEM_PROP_10 EXT_ELEM_PROP_5 EXT_ELEM_PROP_6 EXT_ELEM_PROP_7 EXT_ELEM_PROP_8 EXT_ELEM_PROP_9 ] +set.num_props(): 10 +set.elem_prop_keys(): [] +set.num_elem_props(): 0 + + +------------------------------------- + 205 MODFICATIONS +------------------------------------- + +PROP_1: 1.101 +PROP_10: 182 +PROP_2: 692 +PROP_3: 22 +PROP_4: 779 +PROP_5: 902 +PROP_6: 153 +PROP_7: 434 +PROP_8: 859 +PROP_9: 835 + +-------------------- + 0 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: -99, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] + + +-------------------- + 1 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: Boogle 10-0, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: Boogle 6-0, EXT_ELEM_PROP_7: Boogle 7-0, EXT_ELEM_PROP_8: Boogle 8-0, EXT_ELEM_PROP_9: Boogle 9-0} + +[ 1005, 1005, 1005 ] +[ 1005, 1005, 1005 ] +[ 1005, 1005, 1005 ] +[ 1005, 1005, 1005 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] + + +-------------------- + 2 +-------------------- +{EXT_ELEM_PROP_1: 1.111, EXT_ELEM_PROP_10: 11.011, EXT_ELEM_PROP_5: 5.511, EXT_ELEM_PROP_6: 6.611, EXT_ELEM_PROP_7: 7.711, EXT_ELEM_PROP_8: 8.811, EXT_ELEM_PROP_9: 9.911} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] + + +-------------------- + 3 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: -99, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] + + +-------------------- + 4 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: -99, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] + + +-------------------- + 5 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: -99, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] + + +-------------------- + 6 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: -99, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] + + +-------------------- + 7 +-------------------- +{EXT_ELEM_PROP_1: 1.171, EXT_ELEM_PROP_10: 11.071, EXT_ELEM_PROP_5: 5.571, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: 7.771, EXT_ELEM_PROP_8: 8.871, EXT_ELEM_PROP_9: 9.971} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] +[ 337, 337, 337 ] + + + +set.num_elem_props(): 0 + + +------------------------------------- + 210 MODFICATIONS +------------------------------------- + +PROP_1: 1.101 +PROP_10: 182 +PROP_2: 692 +PROP_3: 22 +PROP_4: 779 +PROP_5: 902 +PROP_6: 153 +PROP_7: 434 +PROP_8: 859 +PROP_9: 835 + +-------------------- + 0 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: -99, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] + + +-------------------- + 1 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: Boogle 6-0, EXT_ELEM_PROP_7: Boogle 7-0, EXT_ELEM_PROP_8: Boogle 8-0, EXT_ELEM_PROP_9: Boogle 9-0} + +[ 1005, 1005, 1005 ] +[ 1005, 1005, 1005 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] + + +-------------------- + 2 +-------------------- +{EXT_ELEM_PROP_1: 1.111, EXT_ELEM_PROP_5: 5.511, EXT_ELEM_PROP_6: 6.611, EXT_ELEM_PROP_7: 7.711, EXT_ELEM_PROP_8: 8.811, EXT_ELEM_PROP_9: 9.911} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] + + +-------------------- + 3 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: -99, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] + + +-------------------- + 4 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: -99, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] + + +-------------------- + 5 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: -99, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] + + +-------------------- + 6 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: -99, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] + + +-------------------- + 7 +-------------------- +{EXT_ELEM_PROP_1: 1.171, EXT_ELEM_PROP_5: 5.571, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: 7.771, EXT_ELEM_PROP_8: 8.871, EXT_ELEM_PROP_9: 9.971} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] + + +-------------------- + 8 +-------------------- +{EXT_ELEM_PROP_1: 1.141, EXT_ELEM_PROP_5: 5.541, EXT_ELEM_PROP_6: 6.641, EXT_ELEM_PROP_7: 7.741, EXT_ELEM_PROP_8: 8.841, EXT_ELEM_PROP_9: 9.941} + +[ 1007, 1007, 1007 ] +[ 1007, 1007, 1007 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] + + + +set.bsize(): 135 +set.vsize(): 145 +set.has_extend_elem_prop(EXT_ELEM_PROP_1): 1 +set.num_extend_elem_props(): 6 +set.prop_index(PROP_7): 7 +set.num_extend_elem_props(): 6 +set.num_elem_props(): 0 +set.num_extend_elem_props(): 6 + + +------------------------------------- + 215 MODFICATIONS +------------------------------------- + +PROP_1: 1.101 +PROP_10: 182 +PROP_2: 692 +PROP_3: 22 +PROP_5: 902 +PROP_6: 153 +PROP_7: 434 +PROP_8: 859 +PROP_9: 835 + +-------------------- + 0 +-------------------- +{EXT_ELEM_PROP_1: 1.141, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_5: 5.541, EXT_ELEM_PROP_6: 6.641, EXT_ELEM_PROP_7: 7.741, EXT_ELEM_PROP_8: 8.841, EXT_ELEM_PROP_9: 9.941} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] + + +-------------------- + 1 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: Boogle 6-0, EXT_ELEM_PROP_7: Boogle 7-0, EXT_ELEM_PROP_8: Boogle 8-0, EXT_ELEM_PROP_9: Boogle 9-0} + +[ 1005, 1005, 1005 ] +[ 1005, 1005, 1005 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] + + +-------------------- + 2 +-------------------- +{EXT_ELEM_PROP_1: 1.111, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_5: 5.511, EXT_ELEM_PROP_6: 6.611, EXT_ELEM_PROP_7: 7.711, EXT_ELEM_PROP_8: 8.811, EXT_ELEM_PROP_9: 9.911} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] + + +-------------------- + 3 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: -99, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] + + +-------------------- + 4 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: -99, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] + + +-------------------- + 5 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 1008, 1008, 1008 ] +[ 1008, 1008, 1008 ] +[ 1008, 1008, 1008 ] +[ 1008, 1008, 1008 ] +[ 1008, 1008, 1008 ] +[ 1008, 1008, 1008 ] + + +-------------------- + 6 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: -99, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] + + +-------------------- + 7 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: -99, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] + + +-------------------- + 8 +-------------------- +{EXT_ELEM_PROP_1: 1.171, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_5: 5.571, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: 7.771, EXT_ELEM_PROP_8: 8.871, EXT_ELEM_PROP_9: 9.971} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] + + +-------------------- + 9 +-------------------- +{EXT_ELEM_PROP_1: 1.141, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_5: 5.541, EXT_ELEM_PROP_6: 6.641, EXT_ELEM_PROP_7: 7.741, EXT_ELEM_PROP_8: 8.841, EXT_ELEM_PROP_9: 9.941} + +[ 1007, 1007, 1007 ] +[ 1007, 1007, 1007 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] + + + +set.num_elem_props(): 0 + + +------------------------------------- + 220 MODFICATIONS +------------------------------------- + +PROP_1: 1.101 +PROP_10: 182 +PROP_2: 692 +PROP_3: 22 +PROP_5: 902 +PROP_6: 153 +PROP_8: 859 +PROP_9: 835 + +-------------------- + 0 +-------------------- +{EXT_ELEM_PROP_1: 1.141, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_5: 5.541, EXT_ELEM_PROP_6: 6.641, EXT_ELEM_PROP_7: 7.741, EXT_ELEM_PROP_8: 8.841, EXT_ELEM_PROP_9: 9.941} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] + + +-------------------- + 1 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: Boogle 6-0, EXT_ELEM_PROP_7: Boogle 7-0, EXT_ELEM_PROP_8: Boogle 8-0, EXT_ELEM_PROP_9: Boogle 9-0} + +[ 1005, 1005, 1005 ] +[ 1005, 1005, 1005 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] + + +-------------------- + 2 +-------------------- +{EXT_ELEM_PROP_1: 1.111, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_5: 5.511, EXT_ELEM_PROP_6: 6.611, EXT_ELEM_PROP_7: 7.711, EXT_ELEM_PROP_8: 8.811, EXT_ELEM_PROP_9: 9.911} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] + + +-------------------- + 3 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: -99, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] + + + +set.size(): 4 + + +------------------------------------- + 225 MODFICATIONS +------------------------------------- + +PROP_1: 1.101 +PROP_10: 182 +PROP_2: 692 +PROP_3: 22 +PROP_4: 364 +PROP_5: 902 +PROP_6: 153 +PROP_7: 495 +PROP_8: 859 +PROP_9: 835 + +-------------------- + 0 +-------------------- +{EXT_ELEM_PROP_1: 1.141, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_5: 5.541, EXT_ELEM_PROP_6: 6.641, EXT_ELEM_PROP_7: 7.741, EXT_ELEM_PROP_8: 8.841, EXT_ELEM_PROP_9: 9.941} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] + + +-------------------- + 1 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: Boogle 6-0, EXT_ELEM_PROP_7: Boogle 7-0, EXT_ELEM_PROP_8: Boogle 8-0, EXT_ELEM_PROP_9: Boogle 9-0} + +[ 1005, 1005, 1005 ] +[ 1005, 1005, 1005 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] + + +-------------------- + 2 +-------------------- +{EXT_ELEM_PROP_1: 1.111, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_5: 5.511, EXT_ELEM_PROP_6: 6.611, EXT_ELEM_PROP_7: 7.711, EXT_ELEM_PROP_8: 8.811, EXT_ELEM_PROP_9: 9.911} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] + + +-------------------- + 3 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: -99, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] + + +-------------------- + 4 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + +[ 1007, 1007, 1007 ] +[ 1007, 1007, 1007 ] +[ 1007, 1007, 1007 ] +[ 1007, 1007, 1007 ] +[ 1007, 1007, 1007 ] +[ 1007, 1007, 1007 ] + + + +set.size(): 5 +set.vsize(): 88 +set.get_extend_elem_prop(EXT_ELEM_PROP_5,3): -99 +set.prop_keys(): [ PROP_1 PROP_10 PROP_2 PROP_3 PROP_4 PROP_5 PROP_6 PROP_7 PROP_8 PROP_9 ] +set.bsize(): 78 +set.get_extend_elem_prop_header(): [ EXT_ELEM_PROP_1 EXT_ELEM_PROP_10 EXT_ELEM_PROP_5 EXT_ELEM_PROP_6 EXT_ELEM_PROP_7 EXT_ELEM_PROP_8 EXT_ELEM_PROP_9 ] +set.prop(PROP_10): 182 + + +------------------------------------- + 230 MODFICATIONS +------------------------------------- + +PROP_1: 1.101 +PROP_10: 182 +PROP_2: 692 +PROP_3: 22 +PROP_4: 364 +PROP_5: 902 +PROP_6: 153 +PROP_7: 495 +PROP_8: 859 +PROP_9: 835 + +-------------------- + 0 +-------------------- +{EXT_ELEM_PROP_1: 1.141, EXT_ELEM_PROP_10: Boogle 10-0, EXT_ELEM_PROP_5: 5.541, EXT_ELEM_PROP_6: Boogle 6-0, EXT_ELEM_PROP_7: Boogle 7-0, EXT_ELEM_PROP_8: Boogle 8-0, EXT_ELEM_PROP_9: Boogle 9-0} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] + + +-------------------- + 1 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: Boogle 10-1, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: Boogle 6-1, EXT_ELEM_PROP_7: Boogle 7-1, EXT_ELEM_PROP_8: Boogle 8-1, EXT_ELEM_PROP_9: Boogle 9-1} + +[ 1005, 1005, 1005 ] +[ 1005, 1005, 1005 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] + + +-------------------- + 2 +-------------------- +{EXT_ELEM_PROP_1: 1.111, EXT_ELEM_PROP_10: Boogle 10-2, EXT_ELEM_PROP_5: 5.511, EXT_ELEM_PROP_6: Boogle 6-2, EXT_ELEM_PROP_7: Boogle 7-2, EXT_ELEM_PROP_8: Boogle 8-2, EXT_ELEM_PROP_9: Boogle 9-2} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] + + +-------------------- + 3 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: Boogle 10-3, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: Boogle 6-3, EXT_ELEM_PROP_7: Boogle 7-3, EXT_ELEM_PROP_8: Boogle 8-3, EXT_ELEM_PROP_9: Boogle 9-3} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] + + +-------------------- + 4 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: Boogle 10-3, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: Boogle 6-3, EXT_ELEM_PROP_7: Boogle 7-3, EXT_ELEM_PROP_8: Boogle 8-3, EXT_ELEM_PROP_9: Boogle 9-3} + +[ 1007, 1007, 1007 ] +[ 1007, 1007, 1007 ] +[ 1007, 1007, 1007 ] +[ 1007, 1007, 1007 ] +[ 1007, 1007, 1007 ] +[ 1007, 1007, 1007 ] + + +-------------------- + 5 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + + + + +set.prop_index(PROP_10): 1 +set.has_elem_prop(ELEM_PROP_8): 0 +set.bsize(): 78 +set.bsize(): 78 + + +------------------------------------- + FINAL PRINT +------------------------------------- + +PROP_1: 1.101 +PROP_10: 182 +PROP_2: 692 +PROP_3: 22 +PROP_4: 364 +PROP_5: 902 +PROP_6: 153 +PROP_7: 495 +PROP_8: 859 +PROP_9: 835 + +-------------------- + 0 +-------------------- +{EXT_ELEM_PROP_1: 1.141, EXT_ELEM_PROP_10: Boogle 10-0, EXT_ELEM_PROP_5: 5.541, EXT_ELEM_PROP_6: Boogle 6-0, EXT_ELEM_PROP_7: Boogle 7-0, EXT_ELEM_PROP_8: Boogle 8-0, EXT_ELEM_PROP_9: Boogle 9-0} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] + + +-------------------- + 1 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: 898, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: Boogle 6-1, EXT_ELEM_PROP_7: Boogle 7-1, EXT_ELEM_PROP_8: Boogle 8-1, EXT_ELEM_PROP_9: Boogle 9-1} + +[ 1005, 1005, 1005 ] +[ 1005, 1005, 1005 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] + + +-------------------- + 2 +-------------------- +{EXT_ELEM_PROP_1: 1.111, EXT_ELEM_PROP_10: Boogle 10-2, EXT_ELEM_PROP_5: 5.511, EXT_ELEM_PROP_6: Boogle 6-2, EXT_ELEM_PROP_7: Boogle 7-2, EXT_ELEM_PROP_8: Boogle 8-2, EXT_ELEM_PROP_9: Boogle 9-2} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] + + +-------------------- + 3 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: Boogle 10-3, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: Boogle 6-3, EXT_ELEM_PROP_7: Boogle 7-3, EXT_ELEM_PROP_8: Boogle 8-3, EXT_ELEM_PROP_9: Boogle 9-3} + +[ 576, 576, 576 ] +[ 576, 576, 576 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] +[ 359, 359, 359 ] + + +-------------------- + 4 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: Boogle 10-3, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: Boogle 6-3, EXT_ELEM_PROP_7: Boogle 7-3, EXT_ELEM_PROP_8: Boogle 8-3, EXT_ELEM_PROP_9: Boogle 9-3} + +[ 1007, 1007, 1007 ] +[ 1007, 1007, 1007 ] +[ 1007, 1007, 1007 ] +[ 1007, 1007, 1007 ] +[ 1007, 1007, 1007 ] +[ 1007, 1007, 1007 ] + + +-------------------- + 5 +-------------------- +{EXT_ELEM_PROP_1: -99, EXT_ELEM_PROP_10: NaN, EXT_ELEM_PROP_5: -99, EXT_ELEM_PROP_6: NaN, EXT_ELEM_PROP_7: NaN, EXT_ELEM_PROP_8: NaN, EXT_ELEM_PROP_9: NaN} + + + diff --git a/python/fibre/base/test/stress_test_generator.py b/python/fibre/base/test/stress_test_generator.py new file mode 100644 index 0000000..c7a4946 --- /dev/null +++ b/python/fibre/base/test/stress_test_generator.py @@ -0,0 +1,1191 @@ + + +#===================================================================================================================== +# Test functions +#===================================================================================================================== + +from fibre.base.object import Object +from fibre.base.set import Set, CantBeFrozenException, ElemSizeException, UnmatchedPropertiesException + +import os.path +import random +import time + +PROP_1 = "PROP_1" +PROP_2 = "PROP_2" +PROP_3 = "PROP_3" +PROP_4 = "PROP_4" +PROP_5 = "PROP_5" +PROP_6 = "PROP_6" +PROP_7 = "PROP_7" +PROP_8 = "PROP_8" +PROP_9 = "PROP_9" +PROP_10 = "PROP_10" + +ELEM_PROP_1 = "ELEM_PROP_1" +ELEM_PROP_2 = "ELEM_PROP_2" +ELEM_PROP_3 = "ELEM_PROP_3" +ELEM_PROP_4 = "ELEM_PROP_4" +ELEM_PROP_5 = "ELEM_PROP_5" +ELEM_PROP_6 = "ELEM_PROP_6" +ELEM_PROP_7 = "ELEM_PROP_7" +ELEM_PROP_8 = "ELEM_PROP_8" +ELEM_PROP_9 = "ELEM_PROP_9" +ELEM_PROP_10 = "ELEM_PROP_10" + +EXT_ELEM_PROP_1 = "EXT_ELEM_PROP_1" +EXT_ELEM_PROP_2 = "EXT_ELEM_PROP_2" +EXT_ELEM_PROP_3 = "EXT_ELEM_PROP_3" +EXT_ELEM_PROP_4 = "EXT_ELEM_PROP_4" +EXT_ELEM_PROP_5 = "EXT_ELEM_PROP_5" +EXT_ELEM_PROP_6 = "EXT_ELEM_PROP_6" +EXT_ELEM_PROP_7 = "EXT_ELEM_PROP_7" +EXT_ELEM_PROP_8 = "EXT_ELEM_PROP_8" +EXT_ELEM_PROP_9 = "EXT_ELEM_PROP_9" +EXT_ELEM_PROP_10 = "EXT_ELEM_PROP_10" + + +class EmptyListException(Exception): + + def __init__(self, value): + self.value = value + + def __str__(self): + return repr(self.value) + + + + +def random_size(): + + return random.choice(range(10)) + +def random_value(): + + return random.choice(range(1000)) + + + +class StressTestGenerator: + + SET_SIZE = 5 + OBJECT_SIZE = 5 + NUM_TESTS = 500 + + def __init__(self, num_elems, elem_degree): + + self.set = Set() + self.set.first_set(num_elems, elem_degree) + self.orig_size = num_elems + + + def get_valid_elem_degree(self): + + if self.only_valid and self.set.elem_degree: + elem_degree = self.set.elem_degree + else: + elem_degree = random_size() + + return elem_degree + + + def get_valid_elem_index(self): + + if self.only_valid: + if not self.set.size(): + raise EmptyListException('') + elem_index = random.choice(xrange(self.set.size())) + else: + elem_index = random_size() + + return elem_index + + + def get_valid_extend_elem_key(self): + + if self.only_valid: + if not self.set.elem_extend_prps.keys(): + raise EmptyListException('') + ext_elem_key = random.choice(self.set.elem_extend_prps.keys()) + else: + ext_elem_key = 'EXT_ELEM_PROP_%d' % random.choice(xrange(10)+1) + + return ext_elem_key + + + def get_valid_elem_key(self): + + if self.only_valid: + if not self.set.elem_prp_keys: + raise EmptyListException('') + elem_key = random.choice(self.set.elem_prp_keys) + else: + elem_key = 'ELEM_PROP_%d' % random.choice(xrange(10)+1) + + return elem_key + + + def get_valid_elem_key_index(self): + + if self.only_valid: + if not self.set.elem_prp_keys: + raise EmptyListException('') + elem_key_index = random.choice(xrange(len(self.set.elem_prp_keys))) + else: + elem_key_index = random.choice(xrange(10)) + + return elem_key_index + + + def get_valid_key(self): + + if self.only_valid: + if not self.set.prps.keys(): + raise EmptyListException('') + key = random.choice(self.set.prps.keys()) + else: + key = 'PROP_%d' % random.choice(xrange(10)+1) + + return key + + + def get_invalid_key(self): + + if self.only_valid: + invalid_keys = list() + for i in range(1,11): + key = 'PROP_%d' % i + if key not in self.set.prps.keys(): + invalid_keys.append(key) + + if not invalid_keys: + raise EmptyListException('') + key = random.choice(invalid_keys) + else: + key = 'PROP_%d' % random.choice(xrange(10)+1) + + return key + + def get_valid_key_index(self): + + if self.only_valid: + if not self.set.prps: + raise EmptyListException('') + key_index = random.choice(xrange(len(self.set.prps))) + else: + key_index = random.choice(xrange(10)) + + return key_index + + + def clear(self): + self.size = 0 + + + def elem_resize_test(self): + + format_str = 'set.elem_resize(%d,%d)' + + self.elem_degree = random.choice(range(1,10)) + + function_str = format_str % (self.elem_degree, random_value()) + + if self.only_valid: + eval('self.' + function_str) + + return (function_str,False,False) + + + def push_back_test(self): + + format_str = 'set.push_back(objects[%d][%d])' + + function_str = format_str % (self.get_valid_elem_degree(), random_size()) + + if self.only_valid: + eval('self.' + function_str) + + return (function_str,False,False) + + + def push_back_w_row_test(self): + + format_str = 'set.push_back(objects[%d][%d], ext_prop_row_maps[%d])' + + function_str = format_str % (self.get_valid_elem_degree(), random_size(), random_size()) + + if self.only_valid: + eval('self.' + function_str) + + return (function_str,False,False) + + + def append_test(self): + + function_str = 'set.append(set2)' + + if self.only_valid: + eval('self.' + function_str) + + return (function_str,False,False) + + + def erase_test(self): + + format_str = 'set.erase(%d)' + + function_str = format_str % self.get_valid_elem_index() + + if self.only_valid: + eval('self.' + function_str) + + return (function_str,False,False) + + + def insert_test(self): + + format_str = 'set.insert(objects[%d][%d],%d)' + + function_str = format_str % (self.get_valid_elem_degree(),random_size(),self.get_valid_elem_index()) + + if self.only_valid: + eval('self.' + function_str) + + return (function_str,False,False) + + + def clear_test(self): + + format_str = 'set.clear()' + + function_str = format_str + + self.size = 0 + + if self.only_valid: + eval('self.' + function_str) + + return (function_str,False,False) + + + def num_extend_elem_props_test(self): + + format_str = 'set.num_extend_elem_props()' + + function_str = format_str + + return (function_str,True,False) + + + def get_extend_elem_prop_header_test(self): + + format_str = 'set.get_extend_elem_prop_header()' + + function_str = format_str + + return (function_str,True,False) + + + def add_extend_elem_prop_test(self): + + format_str = 'set.add_extend_elem_prop(EXT_ELEM_PROP_%d,"-99")' + + function_str = format_str % (random_size()+1) + + if self.only_valid: + eval('self.' + function_str) + + return (function_str,False,False) + + + def add_extend_elem_props_test(self): + + format_str = 'set.add_extend_elem_props(set2)' + + function_str = format_str + + if self.only_valid: + eval('self.' + function_str) + + return (function_str,False,False) + + + def clear_extend_elem_props_test(self): + + format_str = 'set.clear_extend_elem_props()' + + function_str = format_str + + if self.only_valid: + eval('self.' + function_str) + + return (function_str,False,False) + + + def remove_extend_elem_prop_test(self): + + format_str = 'set.remove_extend_elem_prop(%s)' + + function_str = format_str % self.get_valid_extend_elem_key() + + if self.only_valid: + eval('self.' + function_str) + + return (function_str,False,False) + + + def set_extend_elem_prop_test(self): + + format_str = 'set.set_extend_elem_prop(%s,"%d",%d)' + + function_str = format_str % (self.get_valid_extend_elem_key(),random_value(),self.get_valid_elem_index()) + + if self.only_valid: + eval('self.' + function_str) + + return (function_str,False,False) + + + def get_extend_elem_prop_test(self): + + format_str = 'set.get_extend_elem_prop(%s,%d)' + + function_str = format_str % (self.get_valid_extend_elem_key(),self.get_valid_elem_index()) + + return (function_str,True,False) + + + def has_extend_elem_prop_test(self): + + format_str = 'set.has_extend_elem_prop(EXT_ELEM_PROP_%d)' + + function_str = format_str % (random_size()+1) + + return (function_str,True,False) + + + def get_extend_elem_prop_row_test(self): + + format_str = 'set.get_extend_elem_prop_row(%d)' + + function_str = format_str % self.get_valid_elem_index() + + if self.only_valid: + eval('self.' + function_str) + + return (function_str,False,False) + + + def set_extend_elem_prop_row_test(self): + + format_str = 'set.set_extend_elem_prop_row(ext_prop_row_maps[%d],%d)' + + function_str = format_str % (random_size(),self.get_valid_elem_index()) + + if self.only_valid: + eval('self.' + function_str) + + return (function_str,False,False) + + + def copy_extend_elem_prop_row_test(self): + + format_str = 'set.copy_extend_elem_prop_row(set2,%d,%d)' + + function_str = format_str % (random.choice(range(self.orig_size)),self.get_valid_elem_index()) + + if self.only_valid: + eval('self.' + function_str) + + return (function_str,False,False) + + + def copy_extend_elem_props_test(self): + + if self.set.size() != set2.size(): + raise ElemSizeException("'copy_extend_elem_props_test' could not be tested because set size has changed") + + format_str = 'set.copy_extend_elem_props(set2)' + + function_str = format_str + + if self.only_valid: + eval('self.' + function_str) + + + return (function_str,False,False) + + + def append_extend_elem_props_test(self): + + if self.set.size() != set2.size(): + raise ElemSizeException("'append_extend_elem_props_test' could not be tested because set size has changed") + + format_str = 'set.append_extend_elem_props(set2)' + + function_str = format_str + + if self.only_valid: + eval('self.' + function_str) + + return (function_str,False,False) + + + def num_elem_props_test(self): + + format_str = 'set.num_elem_props()' + + function_str = format_str + + return (function_str,True,False) + + + def add_elem_prop_test(self): + + format_str = 'set.add_elem_prop(%s,%d)' + + function_str = format_str % (self.get_valid_elem_key(),random_value()) + + return (function_str,False,True) + + + def has_elem_prop_test(self): + + format_str = 'set.has_elem_prop(ELEM_PROP_%d)' + + function_str = format_str % (random_size()+1) + + return (function_str,True,False) + + + def remove_elem_prop_test(self): + + format_str = 'set.remove_elem_prop(%s)' + + function_str = format_str % self.get_valid_elem_key() + + if self.only_valid: + eval('self.' + function_str) + + return (function_str,False,True) + + + def clear_elem_props_test(self): + + format_str = 'set.clear_elem_props()' + + function_str = format_str + + if self.only_valid: + eval('self.' + function_str) + + return (function_str,False,True) + + + def elem_prop_index_test(self): + + format_str = 'set.elem_prop_index(%s)' + + function_str = format_str % self.get_valid_elem_key() + + return (function_str,True,False) + + + def elem_prop_name_test(self): + + format_str = 'set.elem_prop_name(%d)' + + function_str = format_str % self.get_valid_elem_key_index() + + return (function_str,True,False) + + + def elem_prop_keys_test(self): + + format_str = 'set.elem_prop_keys()' + + function_str = format_str + + return (function_str,True,False) + + + def freeze_elem_degree_test(self): + + format_str = 'set.freeze_elem_degree()' + + function_str = format_str + + if self.only_valid: + eval('self.' + function_str) + + return (function_str,False,True) + + + def free_elem_degree_test(self): + + format_str = 'set.free_elem_degree()' + + function_str = format_str + + if self.only_valid: + eval('self.' + function_str) + + return (function_str,False,False) + + + def resize_test(self): + + format_str = 'set.resize(%d,%d,%d)' + + self.size = random_size() + + if self.set.elem_degree: + elem_degree = 0 + else: + elem_degree = self.get_valid_elem_degree() + + function_str = format_str % (random_size(),random_value(),elem_degree) + + if self.only_valid: + eval('self.' + function_str) + + return (function_str,False,False) + + + def size_test(self): + + format_str = 'set.size()' + + function_str = format_str + + return (function_str,True,False) + + + def vsize_test(self): + + format_str = 'set.vsize()' + + function_str = format_str + + return (function_str,True,False) + + + def bsize_test(self): + + format_str = 'set.bsize()' + + function_str = format_str + + return (function_str,True,False) + + + def num_props_test(self): + + format_str = 'set.num_props()' + + function_str = format_str + + return (function_str,True,False) + + + def add_prop_test(self): + + format_str = 'set.add_prop(%s,%d)' + + function_str = format_str % (self.get_invalid_key(),random_value()) + + if self.only_valid: + eval('self.' + function_str) + + return (function_str,False,False) + + + def has_prop_test(self): + + format_str = 'set.has_prop(PROP_%d)' + + function_str = format_str % (random_size()+1) + + return (function_str,True,False) + + + def remove_prop_test(self): + + format_str = 'set.remove_prop(%s)' + + function_str = format_str % self.get_valid_key() + + if self.only_valid: + eval('self.' + function_str) + + return (function_str,False,False) + + + def clear_props_test(self): + + format_str = 'set.clear_props()' + + function_str = format_str + + if self.only_valid: + eval('self.' + function_str) + + return (function_str,False,False) + + + def prop_index_test(self): + + format_str = 'set.prop_index(%s)' + + function_str = format_str % self.get_valid_key() + + return (function_str,True,False) + + + def prop_test(self): + + format_str = 'set.prop(%s)' + + function_str = format_str % self.get_valid_key() + + return (function_str,True,False) + + + def prop_name_test(self): + + format_str = 'set.prop_name(%d)' + + function_str = format_str % self.get_valid_key_index() + + if self.only_valid: + eval('self.' + function_str) + + return (function_str,False,False) + + + def prop_keys_test(self): + + format_str = 'set.prop_keys()' + + function_str = format_str + + return (function_str,True,False) + + + def generate_stress_test(self,num_iterations, only_valid=True, include_clear=True, resize_on_freeze=True, print_every=10): + + #Store only valid in object so it can be accessed by '*_test()' functions + self.only_valid = only_valid + + # Set up function list + function_list = list() + function_list.append('self.elem_resize_test()') + function_list.append('self.push_back_test()') + function_list.append('self.push_back_w_row_test()') + function_list.append('self.append_test()') + function_list.append('self.erase_test()') + function_list.append('self.insert_test()') + function_list.append('self.num_extend_elem_props_test()') + function_list.append('self.get_extend_elem_prop_header_test()') + function_list.append('self.add_extend_elem_prop_test()') + function_list.append('self.add_extend_elem_props_test()') + function_list.append('self.remove_extend_elem_prop_test()') + function_list.append('self.set_extend_elem_prop_test()') + function_list.append('self.get_extend_elem_prop_test()') + function_list.append('self.has_extend_elem_prop_test()') + function_list.append('self.get_extend_elem_prop_row_test()') + function_list.append('self.set_extend_elem_prop_row_test()') + function_list.append('self.copy_extend_elem_prop_row_test()') + function_list.append('self.copy_extend_elem_props_test()') + function_list.append('self.append_extend_elem_props_test()') + function_list.append('self.num_elem_props_test()') + function_list.append('self.add_elem_prop_test()') + function_list.append('self.has_elem_prop_test()') + function_list.append('self.remove_elem_prop_test()') + function_list.append('self.elem_prop_index_test()') + function_list.append('self.elem_prop_name_test()') + function_list.append('self.elem_prop_keys_test()') + function_list.append('self.freeze_elem_degree_test()') + function_list.append('self.free_elem_degree_test()') + function_list.append('self.resize_test()') + function_list.append('self.size_test()') + function_list.append('self.vsize_test()') + function_list.append('self.bsize_test()') + function_list.append('self.num_props_test()') + function_list.append('self.add_prop_test()') + function_list.append('self.has_prop_test()') + function_list.append('self.remove_prop_test()') + function_list.append('self.prop_index_test()') + function_list.append('self.prop_test()') + function_list.append('self.prop_name_test()') + function_list.append('self.prop_keys_test()') + + if include_clear: + function_list.append('self.clear_test()') + function_list.append('self.clear_extend_elem_props_test()') + function_list.append('self.clear_elem_props_test()') + function_list.append('self.clear_props_test()') + + + cpp_code = open('/home/tclose/Code/Tractography/cmd/stress_tester.cpp', 'w') + py_code = open('/home/tclose/Code/Tractography/python/fibre/base/test/stress_tester.py','w') + + cpp_code.write(cpp_header) + py_code.write(py_header) + + cpp_code.write(' out << "\\n\\n-------------------------------------\\n INITIAL SET \\n-------------------------------------\\n\\n" << set << "\\n\\n";\n') # Write print statement in C++ + py_code.write ('f.write("\\n\\n-------------------------------------\\n INITIAL SET \\n-------------------------------------\\n" + str(set) + "\\n\\n")\n') + cpp_code.write(' out << "\\n\\n-------------------------------------\\n SECOND SET \\n-------------------------------------\\n\\n" << set2 << "\\n\\n";\n') # Write print statement in C++ + py_code.write ('f.write("\\n\\n-------------------------------------\\n SECOND SET \\n-------------------------------------\\n" + str(set2) + "\\n\\n")\n') + + + seed = time.time() + + seed = 1323911724.74 + random.seed(seed) + + print "random seed: " + str(seed) + + modify_count = 0 + for iter in range(num_iterations): + test_function = random.choice(function_list) + print test_function + try: + (function_str, printable, elem_props_changed)= eval(test_function) + + if printable: + cpp_code.write(' out << "' + function_str + ': " << ' + function_str + ' << std::endl;\n') # Write the function to be evaluated in C++ + py_code.write("f.write('" + function_str + ": ' + str(" + function_str + ").replace(\"', '\",\" \").replace(\"['\",\"[ \").replace(\"']\",\" ]\") + '\\n')\n") # Write the function to be evaluated in Python + else: + modify_count = modify_count + 1 + cpp_code.write(' ' + function_str + ';\n') # Write the function to be evaluated in C++ + py_code.write(function_str + '\n') # Write the function to be evaluated in Python + + if not (modify_count % print_every): + cpp_code.write(' out << "\\n\\n-------------------------------------\\n %d MODFICATIONS \\n-------------------------------------\\n\\n" << set << "\\n\\n";\n' % modify_count) # Write print statement in C++ + py_code.write ('f.write("\\n\\n-------------------------------------\\n %d MODFICATIONS \\n-------------------------------------\\n" + str(set) + "\\n\\n")\n' % modify_count) + + + + if elem_props_changed: + cpp_code.write(' elem_props = set.get_elem_prop_header(); recreate_elem_prop_objects(elem_props,objects,prop_row_maps,prop_rows);\n') + py_code.write('elem_props = set.get_elem_prop_header(); (objects,prop_row_maps,prop_rows) = recreate_elem_prop_objects(elem_props)\n') + + except EmptyListException: + print 'Could not produce valid index as list was empty' + + except CantBeFrozenException: + if resize_on_freeze: + self.elem_resize_test() + self.freeze_elem_degree_test() + else: + print 'Couldn''t freeze because rows were of different sizes' + + except ElemSizeException: + print 'Couldn''t append set because element sizes had already changed' + + except UnmatchedPropertiesException: + print 'Couldn''t append set because properties had already changed' + + + cpp_code.write(cpp_footer) + py_code.write(py_footer) + + cpp_code.close() + py_code.close() + + + +#===================================================================================================================== +# Stress test functions +#===================================================================================================================== + + +def recreate_objects(elem_keys): + + object_list = list() + + for size_i in range(10): + objects = list() + + for val_i in range(10): + + object = Object(size_i, val_i + 1001) + + for key in elem_keys: + object.prps[key] = val_i + 1001 + + objects.append(object) + + object_list.append(objects) + + return object_list + + +def recreate_prop_row_maps(elem_keys): + + row_maps = list() + + key_i = 0 + for i in range(10): + value_i = 0 + row_map = dict() + for key in elem_keys: + row_map[key] = value_i * 0.01 + key_i * 0.1 + 0.001 + value_i = value_i + 1 + row_maps.append(row_map) + key_i = key_i + 1 + + return row_maps + + +def recreate_prop_rows(prop_keys): + + prop_rows = list() + + key_i = 0 + for i in range(10): + value_i = 0 + prop_row = list() + for key in prop_keys: + prop_row.append(value_i * 0.01 + key_i * 0.1 + 0.001) + value_i = value_i + 1 + prop_rows.append(prop_row) + + key_i = key_i + 1 + + return prop_rows + + +def recreate_elem_prop_objects(prop_keys): + + return (recreate_objects(prop_keys),recreate_prop_row_maps(prop_keys),recreate_prop_rows(prop_keys)) + + +def create_ext_prop_row_maps(): + + row_maps = list() + + for value_i in range(1,11): + row_map = dict() + for key_i in range(1,11): + row_map["EXT_ELEM_PROP_" + str(key_i)] = value_i * 0.01 + key_i * 1.1 + 0.001 + row_maps.append(row_map) + + return row_maps; + + +props = list() + +props.append(PROP_1) +props.append(PROP_2) +props.append(PROP_3) +props.append(PROP_4) +props.append(PROP_5) + +elem_props = list() + +elem_props.append(ELEM_PROP_1) +elem_props.append(ELEM_PROP_2) +elem_props.append(ELEM_PROP_3) +elem_props.append(ELEM_PROP_4) +elem_props.append(ELEM_PROP_5) + +objects = recreate_objects(elem_props) +prop_rows = recreate_prop_rows(elem_props) +prop_row_maps = recreate_prop_row_maps(elem_props) +ext_prop_row_maps = create_ext_prop_row_maps() + +set2 = Set() +set2.second_set(StressTestGenerator.SET_SIZE,StressTestGenerator.OBJECT_SIZE) + + + +cpp_header = '\n\ +\n\ +extern "C" {\n\ +#include \n\ +#include \n\ +}\n\ +\n\ +#include "math/matrix.h"\n\ +#include "exception.h"\n\ +\n\ +#include "bts/cmd.h"\n\ +#include "bts/common.h"\n\ +#include "bts/file.h"\n\ +\n\ +#include "bts/fibre/base/set.h"\n\ +\n\ +\n\ +using namespace BTS;\n\ +\n\ +\n\ +std::vector< std::vector > recreate_objects(const std::vector& elem_props) {\n\ +\n\ + std::vector< std::vector > objects(10);\n\ +\n\ + for (size_t size_i = 0; size_i < 10; ++size_i) {\n\ + objects[size_i];\n\ + for (size_t value_i = 0; value_i < 10; ++value_i) {\n\ + objects[size_i].push_back(Fibre::Base::Object(size_i, 3, elem_props));\n\ + objects[size_i][value_i].set(value_i+1001);\n\ + }\n\ + }\n\ +\n\ + return objects;\n\ +\n\ +}\n\ +\n\ +std::vector< std::map > recreate_prop_row_maps(const std::vector& elem_props) {\n\ +\n\ + std::vector< std::map > prop_row_maps(10);\n\ +\n\ + for (size_t value_i = 0; value_i < 10; ++value_i) {\n\ + for (size_t key_i = 0; key_i < elem_props.size(); ++key_i)\n\ + prop_row_maps[value_i][elem_props[key_i]] = (double)(value_i+1) * 0.01 + (double)(key_i+1) * 0.1 + 0.001;\n\ + }\n\ +\n\ + return prop_row_maps;\n\ +\n\ +}\n\ +\n\ +std::vector< std::vector > recreate_prop_rows(const std::vector& elem_props) {\n\ +\n\ + std::vector< std::vector > prop_rows(10);\n\ +\n\ + for (size_t value_i = 0; value_i < 10; ++value_i) {\n\ + for (size_t key_i = 0; key_i < elem_props.size(); ++key_i)\n\ + prop_rows[value_i].push_back((double)(value_i+1) * 0.01 + (double)(key_i+1) * 0.1 + 0.001);\n\ + }\n\ +\n\ + return prop_rows;\n\ +\n\ +}\n\ +\n\ +\n\ +std::vector< std::map > create_ext_prop_row_maps() {\n\ +\n\ + std::vector< std::map > prop_rows(10);\n\ +\n\ + for (size_t value_i = 0; value_i < 10; ++value_i) {\n\ + for (size_t key_i = 1; key_i < 11; ++key_i)\n\ + prop_rows[value_i]["EXT_ELEM_PROP_" +str(key_i)] = str((double)(value_i+1) * 0.01 + (double)key_i * 1.1 + 0.001);\n\ + }\n\ +\n\ + return prop_rows;\n\ +\n\ +}\n\ +\n\ +void recreate_elem_prop_objects(const std::vector& elem_props, std::vector >& objects, std::vector< std::map >& prop_row_maps, std::vector< std::vector >& prop_rows) {\n\ +\n\ + objects = recreate_objects(elem_props);\n\ + prop_row_maps = recreate_prop_row_maps(elem_props);\n\ + prop_rows = recreate_prop_rows(elem_props);\n\ +\n\ +}\n\ +\n\ +SET_VERSION_DEFAULT;\n\ +SET_AUTHOR ("Thomas G. Close");\n\ +SET_COPYRIGHT (NULL);\n\ +\n\ +DESCRIPTION = {\n\ + "Tests a random sequence of Fibre::Base::Set operations against those performed on a Python version.",\n\ + "",\n\ + NULL\n\ +};\n\ +\n\ +ARGUMENTS = {\n\ +\n\ +\n\ + Argument()\n\ +};\n\ +\n\ +\n\ +OPTIONS = {\n\ +\n\ +Option() };\n\ +\n\ +\n\ +EXECUTE {\n\ +\n\ + size_t SET_SIZE = 5;\n\ + size_t OBJECT_SIZE = 5;\n\ +\n\ + const char* PROP_1 = "PROP_1";\n\ + const char* PROP_2 = "PROP_2";\n\ + const char* PROP_3 = "PROP_3";\n\ + const char* PROP_4 = "PROP_4";\n\ + const char* PROP_5 = "PROP_5";\n\ + const char* PROP_6 = "PROP_6";\n\ + const char* PROP_7 = "PROP_7";\n\ + const char* PROP_8 = "PROP_8";\n\ + const char* PROP_9 = "PROP_9";\n\ + const char* PROP_10 = "PROP_10";\n\ +\n\ + const char* ELEM_PROP_1 = "ELEM_PROP_1";\n\ + const char* ELEM_PROP_2 = "ELEM_PROP_2";\n\ + const char* ELEM_PROP_3 = "ELEM_PROP_3";\n\ + const char* ELEM_PROP_4 = "ELEM_PROP_4";\n\ + const char* ELEM_PROP_5 = "ELEM_PROP_5";\n\ + const char* ELEM_PROP_6 = "ELEM_PROP_6";\n\ + const char* ELEM_PROP_7 = "ELEM_PROP_7";\n\ + const char* ELEM_PROP_8 = "ELEM_PROP_8";\n\ + const char* ELEM_PROP_9 = "ELEM_PROP_9";\n\ + const char* ELEM_PROP_10 = "ELEM_PROP_10";\n\ +\n\ + std::string EXT_ELEM_PROP_1 = "EXT_ELEM_PROP_1";\n\ + std::string EXT_ELEM_PROP_2 = "EXT_ELEM_PROP_2";\n\ + std::string EXT_ELEM_PROP_3 = "EXT_ELEM_PROP_3";\n\ + std::string EXT_ELEM_PROP_4 = "EXT_ELEM_PROP_4";\n\ + std::string EXT_ELEM_PROP_5 = "EXT_ELEM_PROP_5";\n\ + std::string EXT_ELEM_PROP_6 = "EXT_ELEM_PROP_6";\n\ + std::string EXT_ELEM_PROP_7 = "EXT_ELEM_PROP_7";\n\ + std::string EXT_ELEM_PROP_8 = "EXT_ELEM_PROP_8";\n\ + std::string EXT_ELEM_PROP_9 = "EXT_ELEM_PROP_9";\n\ + std::string EXT_ELEM_PROP_10 = "EXT_ELEM_PROP_10";\n\ +\n\ + std::vector props;\n\ +\n\ + props.push_back(PROP_1);\n\ + props.push_back(PROP_2);\n\ + props.push_back(PROP_3);\n\ + props.push_back(PROP_4);\n\ + props.push_back(PROP_5);\n\ +\n\ + std::vector elem_props;\n\ +\n\ + elem_props.push_back(ELEM_PROP_1);\n\ + elem_props.push_back(ELEM_PROP_2);\n\ + elem_props.push_back(ELEM_PROP_3);\n\ + elem_props.push_back(ELEM_PROP_4);\n\ + elem_props.push_back(ELEM_PROP_5);\n\ +\n\ +\n\ + std::vector< std::vector > objects = recreate_objects(elem_props);\n\ + std::vector > prop_rows = recreate_prop_rows(elem_props);\n\ + std::vector< std::map > prop_row_maps = recreate_prop_row_maps(elem_props);\n\ +\n\ + std::vector< std::map > ext_prop_row_maps = create_ext_prop_row_maps();\n\ +\n\ +\n\ + //Iniate set\n\ + Fibre::Base::Set set(SET_SIZE, OBJECT_SIZE, 3, props, elem_props);\n\ +\n\ + for (size_t elem_i = 0; elem_i < SET_SIZE; ++elem_i) {\n\ + Fibre::Base::Object ob = set[elem_i];\n\ + for (size_t elem_elem_i = 0; elem_elem_i < OBJECT_SIZE; ++elem_elem_i) {\n\ + Triple& t = ob[elem_elem_i];\n\ + for (size_t elem_elem_elem_i = 0; elem_elem_elem_i < 3; ++elem_elem_elem_i)\n\ + t[elem_elem_elem_i] = elem_i * 100 + elem_elem_i * 10 + elem_elem_elem_i +1;\n\ + }\n\ +\n\ + for (size_t prop_i = 0; prop_i < 5; ++prop_i)\n\ + ob.prop(prop_i) = (double)elem_i * 100.0 + (double)(prop_i+1) * .1 + 0.001;\n\ + }\n\ +\n\ + for (size_t prop_i = 0; prop_i < 5; ++prop_i)\n\ + set.prop(prop_i) = (double)(prop_i+1) * 1.1 + 0.001;\n\ +\n\ + for (size_t eprop_i = 1; eprop_i < 6; ++eprop_i) {\n\ + set.add_extend_elem_prop("EXT_ELEM_PROP_" + str(eprop_i),"NaN");\n\ + for (size_t row_i = 0; row_i < set.size(); ++row_i)\n\ + set.set_extend_elem_prop("EXT_ELEM_PROP_" + str(eprop_i), "Ooogle " + str(eprop_i) + "-" + str(row_i), row_i);\n\ + }\n\ +\n\ +\n\ + //Iniate set\n\ + Fibre::Base::Set set2(SET_SIZE, OBJECT_SIZE, 3, props, elem_props);\n\ +\n\ + for (size_t elem_i = 0; elem_i < SET_SIZE; ++elem_i) {\n\ + Fibre::Base::Object ob = set2[elem_i];\n\ + for (size_t elem_elem_i = 0; elem_elem_i < OBJECT_SIZE; ++elem_elem_i) {\n\ + Triple& t = ob[elem_elem_i];\n\ + for (size_t elem_elem_elem_i = 0; elem_elem_elem_i < 3; ++elem_elem_elem_i)\n\ + t[elem_elem_elem_i] = -(double)(elem_i * 100 + elem_elem_i * 10 + elem_elem_elem_i + 1);\n\ + }\n\ +\n\ + for (size_t prop_i = 0; prop_i < 5; ++prop_i)\n\ + ob.prop(prop_i) = -(double)elem_i * 100.0 - (double)(prop_i+1) * .1 - 0.001;\n\ + }\n\ +\n\ + for (size_t prop_i = 0; prop_i < 5; ++prop_i)\n\ + set2.prop(prop_i) = -(double)(prop_i+1) * 1.1 - 0.001;\n\ +\n\ + for (size_t eprop_i = 6; eprop_i < 11; ++eprop_i) {\n\ + set2.add_extend_elem_prop("EXT_ELEM_PROP_" + str(eprop_i),"NaN");\n\ + for (size_t row_i = 0; row_i < set2.size(); ++row_i)\n\ + set2.set_extend_elem_prop("EXT_ELEM_PROP_" + str(eprop_i), "Boogle " + str(eprop_i) + "-" + str(row_i), row_i);\n\ + }\n\ +\n\ + std::ofstream out;\n\ +\n\ + out.open("/home/tclose/Code/Tractography/python/fibre/base/test/output/cpp_output.txt");\n\ +\n\ +\n\ +\n\ + //====================================================================================================================\n\ + // Test functions start here\n\ + //====================================================================================================================\n\ +\n' + + +cpp_footer='\ +\n\ +\n\ + out << std::endl << std::endl << "-------------------------------------" << std::endl;\n\ + out << " FINAL PRINT " << std::endl;\n\ + out << "-------------------------------------\\n" << std::endl;\n\ +\n\ + out << set << std::endl;\n\ +\n\ + std::cout << "Ran cpp test successfully" << std::endl;\n\ +\n\ +\n\ +}\n' + + + +py_header="\ +from stress_test_generator import *\n\ +\n\ +set = Set()\n\ +set.first_set(StressTestGenerator.SET_SIZE,StressTestGenerator.OBJECT_SIZE)\n\ +global objects\n\ +global prop_rows\n\ +global prop_row_maps\n\ +\n\ +f = open('/home/tclose/Code/Tractography/python/fibre/base/test/output/python_output.txt','w')\n" + + + +#===================================================================================================================== +# Generated functions start here +#===================================================================================================================== + + +py_footer="\ +\n\ +\n\ +#=====================================================================================================================\n\ +# Generated functions end here\n\ +#=====================================================================================================================\n\ +\n\ +f.write('\\n\\n-------------------------------------\\n FINAL PRINT \\n-------------------------------------\\n')\n\ +\n\ +f.write(str(set))\n\ +\n\ +print 'Ran python test successfully!'\n\ +\n\ +f.write('\\n')\n\ +\n\ +f.close()\n" + + +if __name__ == '__main__': + + test_generator = StressTestGenerator(StressTestGenerator.SET_SIZE, StressTestGenerator.OBJECT_SIZE) + test_generator.generate_stress_test(StressTestGenerator.NUM_TESTS, include_clear=False, print_every=5) + + + \ No newline at end of file diff --git a/python/fibre/base/test/stress_tester.py b/python/fibre/base/test/stress_tester.py new file mode 100644 index 0000000..7be4771 --- /dev/null +++ b/python/fibre/base/test/stress_tester.py @@ -0,0 +1,501 @@ +from stress_test_generator import * + +set = Set() +set.first_set(StressTestGenerator.SET_SIZE,StressTestGenerator.OBJECT_SIZE) +global objects +global prop_rows +global prop_row_maps + +f = open('/home/tclose/Code/Tractography/python/fibre/base/test/output/python_output.txt','w') +f.write("\n\n-------------------------------------\n INITIAL SET \n-------------------------------------\n" + str(set) + "\n\n") +f.write("\n\n-------------------------------------\n SECOND SET \n-------------------------------------\n" + str(set2) + "\n\n") +set.insert(objects[5][8],1) +f.write('set.num_elem_props(): ' + str(set.num_elem_props()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +f.write('set.elem_prop_index(ELEM_PROP_4): ' + str(set.elem_prop_index(ELEM_PROP_4)).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +set.add_elem_prop(ELEM_PROP_2,669) +elem_props = set.get_elem_prop_header(); (objects,prop_row_maps,prop_rows) = recreate_elem_prop_objects(elem_props) +f.write('set.has_extend_elem_prop(EXT_ELEM_PROP_7): ' + str(set.has_extend_elem_prop(EXT_ELEM_PROP_7)).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +set.add_prop(PROP_6,984) +f.write('set.num_props(): ' + str(set.num_props()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +set.free_elem_degree() +set.remove_prop(PROP_3) +f.write("\n\n-------------------------------------\n 5 MODFICATIONS \n-------------------------------------\n" + str(set) + "\n\n") +set.add_elem_prop(ELEM_PROP_4,463) +elem_props = set.get_elem_prop_header(); (objects,prop_row_maps,prop_rows) = recreate_elem_prop_objects(elem_props) +f.write('set.bsize(): ' + str(set.bsize()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +set.copy_extend_elem_prop_row(set2,3,2) +set.copy_extend_elem_prop_row(set2,1,1) +f.write('set.size(): ' + str(set.size()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +set.add_prop(PROP_9,419) +f.write('set.num_extend_elem_props(): ' + str(set.num_extend_elem_props()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +f.write('set.prop(PROP_9): ' + str(set.prop(PROP_9)).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +f.write('set.elem_prop_keys(): ' + str(set.elem_prop_keys()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +set.add_elem_prop(ELEM_PROP_5,661) +f.write("\n\n-------------------------------------\n 10 MODFICATIONS \n-------------------------------------\n" + str(set) + "\n\n") +elem_props = set.get_elem_prop_header(); (objects,prop_row_maps,prop_rows) = recreate_elem_prop_objects(elem_props) +set.push_back(objects[9][0], ext_prop_row_maps[3]) +f.write('set.prop_index(PROP_2): ' + str(set.prop_index(PROP_2)).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +f.write('set.vsize(): ' + str(set.vsize()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +f.write('set.num_props(): ' + str(set.num_props()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +set.erase(1) +set.add_elem_prop(ELEM_PROP_4,815) +elem_props = set.get_elem_prop_header(); (objects,prop_row_maps,prop_rows) = recreate_elem_prop_objects(elem_props) +f.write('set.num_extend_elem_props(): ' + str(set.num_extend_elem_props()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +f.write('set.prop_index(PROP_2): ' + str(set.prop_index(PROP_2)).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +set.add_prop(PROP_7,434) +set.insert(objects[5][8],1) +f.write("\n\n-------------------------------------\n 15 MODFICATIONS \n-------------------------------------\n" + str(set) + "\n\n") +f.write('set.get_extend_elem_prop_header(): ' + str(set.get_extend_elem_prop_header()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +f.write('set.prop_keys(): ' + str(set.prop_keys()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +set.free_elem_degree() +set.set_extend_elem_prop_row(ext_prop_row_maps[1],4) +f.write('set.prop_keys(): ' + str(set.prop_keys()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +f.write('set.elem_prop_keys(): ' + str(set.elem_prop_keys()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +set.set_extend_elem_prop_row(ext_prop_row_maps[3],4) +set.push_back(objects[5][6], ext_prop_row_maps[7]) +set.erase(2) +f.write("\n\n-------------------------------------\n 20 MODFICATIONS \n-------------------------------------\n" + str(set) + "\n\n") +set.insert(objects[1][5],5) +set.push_back(objects[6][1]) +f.write('set.elem_prop_index(ELEM_PROP_4): ' + str(set.elem_prop_index(ELEM_PROP_4)).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +f.write('set.elem_prop_index(ELEM_PROP_4): ' + str(set.elem_prop_index(ELEM_PROP_4)).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +set.resize(1,574,0) +set.push_back(objects[0][2]) +set.elem_resize(7,511) +f.write("\n\n-------------------------------------\n 25 MODFICATIONS \n-------------------------------------\n" + str(set) + "\n\n") +set.push_back(objects[7][8]) +f.write('set.prop(PROP_4): ' + str(set.prop(PROP_4)).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +set.get_extend_elem_prop_row(1) +set.elem_resize(8,886) +set.add_extend_elem_props(set2) +set.add_elem_prop(ELEM_PROP_4,734) +f.write("\n\n-------------------------------------\n 30 MODFICATIONS \n-------------------------------------\n" + str(set) + "\n\n") +elem_props = set.get_elem_prop_header(); (objects,prop_row_maps,prop_rows) = recreate_elem_prop_objects(elem_props) +f.write('set.num_extend_elem_props(): ' + str(set.num_extend_elem_props()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +set.freeze_elem_degree() +elem_props = set.get_elem_prop_header(); (objects,prop_row_maps,prop_rows) = recreate_elem_prop_objects(elem_props) +f.write('set.num_props(): ' + str(set.num_props()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +set.insert(objects[8][4],1) +set.remove_elem_prop(ELEM_PROP_3) +elem_props = set.get_elem_prop_header(); (objects,prop_row_maps,prop_rows) = recreate_elem_prop_objects(elem_props) +set.insert(objects[8][5],1) +f.write('set.num_extend_elem_props(): ' + str(set.num_extend_elem_props()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +set.set_extend_elem_prop(EXT_ELEM_PROP_3,"733",0) +f.write("\n\n-------------------------------------\n 35 MODFICATIONS \n-------------------------------------\n" + str(set) + "\n\n") +set.erase(2) +set.erase(0) +set.erase(1) +f.write('set.prop(PROP_7): ' + str(set.prop(PROP_7)).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +set.freeze_elem_degree() +elem_props = set.get_elem_prop_header(); (objects,prop_row_maps,prop_rows) = recreate_elem_prop_objects(elem_props) +set.add_extend_elem_prop(EXT_ELEM_PROP_10,"-99") +f.write("\n\n-------------------------------------\n 40 MODFICATIONS \n-------------------------------------\n" + str(set) + "\n\n") +set.remove_extend_elem_prop(EXT_ELEM_PROP_1) +set.free_elem_degree() +f.write('set.num_props(): ' + str(set.num_props()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +f.write('set.get_extend_elem_prop(EXT_ELEM_PROP_9,0): ' + str(set.get_extend_elem_prop(EXT_ELEM_PROP_9,0)).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +f.write('set.has_elem_prop(ELEM_PROP_9): ' + str(set.has_elem_prop(ELEM_PROP_9)).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +set.elem_resize(8,975) +set.remove_elem_prop(ELEM_PROP_5) +elem_props = set.get_elem_prop_header(); (objects,prop_row_maps,prop_rows) = recreate_elem_prop_objects(elem_props) +set.remove_extend_elem_prop(EXT_ELEM_PROP_6) +f.write("\n\n-------------------------------------\n 45 MODFICATIONS \n-------------------------------------\n" + str(set) + "\n\n") +f.write('set.vsize(): ' + str(set.vsize()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +set.remove_elem_prop(ELEM_PROP_1) +elem_props = set.get_elem_prop_header(); (objects,prop_row_maps,prop_rows) = recreate_elem_prop_objects(elem_props) +f.write('set.elem_prop_index(ELEM_PROP_4): ' + str(set.elem_prop_index(ELEM_PROP_4)).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +f.write('set.vsize(): ' + str(set.vsize()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +set.prop_name(6) +set.push_back(objects[8][7]) +set.remove_extend_elem_prop(EXT_ELEM_PROP_2) +set.remove_extend_elem_prop(EXT_ELEM_PROP_8) +f.write("\n\n-------------------------------------\n 50 MODFICATIONS \n-------------------------------------\n" + str(set) + "\n\n") +set.add_elem_prop(ELEM_PROP_4,776) +elem_props = set.get_elem_prop_header(); (objects,prop_row_maps,prop_rows) = recreate_elem_prop_objects(elem_props) +set.copy_extend_elem_prop_row(set2,1,1) +set.erase(2) +set.push_back(objects[8][8], ext_prop_row_maps[2]) +set.elem_resize(2,480) +f.write("\n\n-------------------------------------\n 55 MODFICATIONS \n-------------------------------------\n" + str(set) + "\n\n") +set.add_extend_elem_prop(EXT_ELEM_PROP_8,"-99") +f.write('set.size(): ' + str(set.size()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +f.write('set.num_props(): ' + str(set.num_props()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +f.write('set.num_extend_elem_props(): ' + str(set.num_extend_elem_props()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +set.insert(objects[2][4],0) +f.write('set.has_elem_prop(ELEM_PROP_7): ' + str(set.has_elem_prop(ELEM_PROP_7)).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +set.set_extend_elem_prop_row(ext_prop_row_maps[0],0) +set.freeze_elem_degree() +elem_props = set.get_elem_prop_header(); (objects,prop_row_maps,prop_rows) = recreate_elem_prop_objects(elem_props) +set.push_back(objects[2][2]) +f.write("\n\n-------------------------------------\n 60 MODFICATIONS \n-------------------------------------\n" + str(set) + "\n\n") +set.copy_extend_elem_prop_row(set2,0,2) +f.write('set.get_extend_elem_prop(EXT_ELEM_PROP_3,3): ' + str(set.get_extend_elem_prop(EXT_ELEM_PROP_3,3)).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +f.write('set.num_elem_props(): ' + str(set.num_elem_props()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +set.add_extend_elem_prop(EXT_ELEM_PROP_4,"-99") +set.remove_elem_prop(ELEM_PROP_2) +elem_props = set.get_elem_prop_header(); (objects,prop_row_maps,prop_rows) = recreate_elem_prop_objects(elem_props) +f.write('set.vsize(): ' + str(set.vsize()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +set.prop_name(2) +set.remove_elem_prop(ELEM_PROP_4) +f.write("\n\n-------------------------------------\n 65 MODFICATIONS \n-------------------------------------\n" + str(set) + "\n\n") +elem_props = set.get_elem_prop_header(); (objects,prop_row_maps,prop_rows) = recreate_elem_prop_objects(elem_props) +f.write('set.get_extend_elem_prop_header(): ' + str(set.get_extend_elem_prop_header()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +set.set_extend_elem_prop_row(ext_prop_row_maps[0],1) +set.prop_name(2) +f.write('set.prop_index(PROP_4): ' + str(set.prop_index(PROP_4)).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +f.write('set.num_elem_props(): ' + str(set.num_elem_props()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +f.write('set.bsize(): ' + str(set.bsize()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +f.write('set.has_extend_elem_prop(EXT_ELEM_PROP_3): ' + str(set.has_extend_elem_prop(EXT_ELEM_PROP_3)).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +set.free_elem_degree() +set.remove_extend_elem_prop(EXT_ELEM_PROP_7) +f.write('set.num_extend_elem_props(): ' + str(set.num_extend_elem_props()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +f.write('set.num_props(): ' + str(set.num_props()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +set.free_elem_degree() +f.write("\n\n-------------------------------------\n 70 MODFICATIONS \n-------------------------------------\n" + str(set) + "\n\n") +f.write('set.has_extend_elem_prop(EXT_ELEM_PROP_8): ' + str(set.has_extend_elem_prop(EXT_ELEM_PROP_8)).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +set.add_extend_elem_props(set2) +set.insert(objects[6][7],2) +f.write('set.vsize(): ' + str(set.vsize()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +set.copy_extend_elem_prop_row(set2,3,5) +set.copy_extend_elem_prop_row(set2,4,2) +set.get_extend_elem_prop_row(4) +f.write("\n\n-------------------------------------\n 75 MODFICATIONS \n-------------------------------------\n" + str(set) + "\n\n") +f.write('set.num_props(): ' + str(set.num_props()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +set.add_prop(PROP_8,140) +set.set_extend_elem_prop(EXT_ELEM_PROP_4,"138",2) +set.get_extend_elem_prop_row(3) +set.get_extend_elem_prop_row(2) +set.set_extend_elem_prop_row(ext_prop_row_maps[5],5) +f.write("\n\n-------------------------------------\n 80 MODFICATIONS \n-------------------------------------\n" + str(set) + "\n\n") +f.write('set.get_extend_elem_prop_header(): ' + str(set.get_extend_elem_prop_header()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +set.set_extend_elem_prop(EXT_ELEM_PROP_5,"667",2) +set.add_extend_elem_prop(EXT_ELEM_PROP_2,"-99") +set.insert(objects[1][2],2) +set.add_extend_elem_prop(EXT_ELEM_PROP_8,"-99") +set.remove_prop(PROP_5) +f.write("\n\n-------------------------------------\n 85 MODFICATIONS \n-------------------------------------\n" + str(set) + "\n\n") +set.remove_extend_elem_prop(EXT_ELEM_PROP_6) +set.insert(objects[8][9],3) +set.resize(1,277,5) +f.write('set.num_extend_elem_props(): ' + str(set.num_extend_elem_props()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +set.add_extend_elem_prop(EXT_ELEM_PROP_6,"-99") +set.prop_name(0) +f.write("\n\n-------------------------------------\n 90 MODFICATIONS \n-------------------------------------\n" + str(set) + "\n\n") +set.erase(0) +set.prop_name(3) +f.write('set.elem_prop_keys(): ' + str(set.elem_prop_keys()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +set.elem_resize(8,926) +f.write('set.get_extend_elem_prop_header(): ' + str(set.get_extend_elem_prop_header()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +set.remove_extend_elem_prop(EXT_ELEM_PROP_9) +set.remove_prop(PROP_4) +f.write("\n\n-------------------------------------\n 95 MODFICATIONS \n-------------------------------------\n" + str(set) + "\n\n") +set.remove_extend_elem_prop(EXT_ELEM_PROP_5) +set.add_prop(PROP_5,902) +f.write('set.num_extend_elem_props(): ' + str(set.num_extend_elem_props()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +set.add_prop(PROP_10,182) +set.push_back(objects[8][0], ext_prop_row_maps[2]) +f.write('set.vsize(): ' + str(set.vsize()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +f.write('set.prop_index(PROP_9): ' + str(set.prop_index(PROP_9)).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +f.write('set.num_extend_elem_props(): ' + str(set.num_extend_elem_props()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +set.add_prop(PROP_4,779) +f.write("\n\n-------------------------------------\n 100 MODFICATIONS \n-------------------------------------\n" + str(set) + "\n\n") +f.write('set.prop_keys(): ' + str(set.prop_keys()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +f.write('set.has_extend_elem_prop(EXT_ELEM_PROP_2): ' + str(set.has_extend_elem_prop(EXT_ELEM_PROP_2)).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +set.add_prop(PROP_3,22) +set.resize(3,137,0) +f.write('set.num_elem_props(): ' + str(set.num_elem_props()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +f.write('set.has_extend_elem_prop(EXT_ELEM_PROP_10): ' + str(set.has_extend_elem_prop(EXT_ELEM_PROP_10)).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +set.set_extend_elem_prop(EXT_ELEM_PROP_8,"308",0) +f.write('set.num_props(): ' + str(set.num_props()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +f.write('set.get_extend_elem_prop(EXT_ELEM_PROP_10,2): ' + str(set.get_extend_elem_prop(EXT_ELEM_PROP_10,2)).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +set.erase(1) +set.erase(1) +f.write("\n\n-------------------------------------\n 105 MODFICATIONS \n-------------------------------------\n" + str(set) + "\n\n") +f.write('set.get_extend_elem_prop(EXT_ELEM_PROP_3,0): ' + str(set.get_extend_elem_prop(EXT_ELEM_PROP_3,0)).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +set.push_back(objects[8][5], ext_prop_row_maps[4]) +set.freeze_elem_degree() +elem_props = set.get_elem_prop_header(); (objects,prop_row_maps,prop_rows) = recreate_elem_prop_objects(elem_props) +f.write('set.prop_keys(): ' + str(set.prop_keys()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +f.write('set.size(): ' + str(set.size()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +f.write('set.num_extend_elem_props(): ' + str(set.num_extend_elem_props()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +f.write('set.prop(PROP_1): ' + str(set.prop(PROP_1)).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +f.write('set.size(): ' + str(set.size()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +set.freeze_elem_degree() +elem_props = set.get_elem_prop_header(); (objects,prop_row_maps,prop_rows) = recreate_elem_prop_objects(elem_props) +set.get_extend_elem_prop_row(0) +f.write('set.bsize(): ' + str(set.bsize()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +f.write('set.elem_prop_keys(): ' + str(set.elem_prop_keys()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +set.elem_resize(9,179) +f.write("\n\n-------------------------------------\n 110 MODFICATIONS \n-------------------------------------\n" + str(set) + "\n\n") +f.write('set.get_extend_elem_prop(EXT_ELEM_PROP_10,1): ' + str(set.get_extend_elem_prop(EXT_ELEM_PROP_10,1)).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +set.push_back(objects[9][1], ext_prop_row_maps[3]) +set.erase(0) +f.write('set.bsize(): ' + str(set.bsize()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +f.write('set.prop(PROP_3): ' + str(set.prop(PROP_3)).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +f.write('set.num_extend_elem_props(): ' + str(set.num_extend_elem_props()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +set.push_back(objects[9][8]) +f.write('set.num_extend_elem_props(): ' + str(set.num_extend_elem_props()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +f.write('set.num_props(): ' + str(set.num_props()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +set.remove_prop(PROP_2) +set.get_extend_elem_prop_row(0) +f.write("\n\n-------------------------------------\n 115 MODFICATIONS \n-------------------------------------\n" + str(set) + "\n\n") +set.add_extend_elem_prop(EXT_ELEM_PROP_5,"-99") +f.write('set.elem_prop_keys(): ' + str(set.elem_prop_keys()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +set.prop_name(2) +set.prop_name(0) +set.erase(0) +set.copy_extend_elem_prop_row(set2,4,1) +f.write("\n\n-------------------------------------\n 120 MODFICATIONS \n-------------------------------------\n" + str(set) + "\n\n") +set.free_elem_degree() +f.write('set.num_elem_props(): ' + str(set.num_elem_props()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +set.remove_prop(PROP_8) +f.write('set.prop_index(PROP_10): ' + str(set.prop_index(PROP_10)).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +set.free_elem_degree() +f.write('set.size(): ' + str(set.size()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +set.remove_extend_elem_prop(EXT_ELEM_PROP_7) +set.add_extend_elem_prop(EXT_ELEM_PROP_1,"-99") +f.write("\n\n-------------------------------------\n 125 MODFICATIONS \n-------------------------------------\n" + str(set) + "\n\n") +set.elem_resize(4,873) +set.remove_extend_elem_prop(EXT_ELEM_PROP_3) +f.write('set.size(): ' + str(set.size()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +set.add_extend_elem_props(set2) +set.free_elem_degree() +f.write('set.get_extend_elem_prop(EXT_ELEM_PROP_2,0): ' + str(set.get_extend_elem_prop(EXT_ELEM_PROP_2,0)).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +set.insert(objects[5][3],1) +f.write("\n\n-------------------------------------\n 130 MODFICATIONS \n-------------------------------------\n" + str(set) + "\n\n") +f.write('set.num_elem_props(): ' + str(set.num_elem_props()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +f.write('set.size(): ' + str(set.size()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +f.write('set.num_elem_props(): ' + str(set.num_elem_props()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +set.push_back(objects[4][7], ext_prop_row_maps[3]) +f.write('set.elem_prop_keys(): ' + str(set.elem_prop_keys()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +set.push_back(objects[4][0], ext_prop_row_maps[7]) +set.push_back(objects[6][6], ext_prop_row_maps[2]) +set.elem_resize(7,192) +set.insert(objects[7][9],1) +f.write("\n\n-------------------------------------\n 135 MODFICATIONS \n-------------------------------------\n" + str(set) + "\n\n") +f.write('set.prop(PROP_3): ' + str(set.prop(PROP_3)).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +f.write('set.get_extend_elem_prop_header(): ' + str(set.get_extend_elem_prop_header()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +f.write('set.size(): ' + str(set.size()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +set.insert(objects[7][1],0) +set.add_extend_elem_prop(EXT_ELEM_PROP_6,"-99") +f.write('set.has_elem_prop(ELEM_PROP_3): ' + str(set.has_elem_prop(ELEM_PROP_3)).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +f.write('set.vsize(): ' + str(set.vsize()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +f.write('set.bsize(): ' + str(set.bsize()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +set.free_elem_degree() +set.freeze_elem_degree() +elem_props = set.get_elem_prop_header(); (objects,prop_row_maps,prop_rows) = recreate_elem_prop_objects(elem_props) +f.write('set.prop(PROP_5): ' + str(set.prop(PROP_5)).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +f.write('set.has_extend_elem_prop(EXT_ELEM_PROP_4): ' + str(set.has_extend_elem_prop(EXT_ELEM_PROP_4)).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +f.write('set.bsize(): ' + str(set.bsize()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +set.elem_resize(6,44) +f.write("\n\n-------------------------------------\n 140 MODFICATIONS \n-------------------------------------\n" + str(set) + "\n\n") +f.write('set.get_extend_elem_prop_header(): ' + str(set.get_extend_elem_prop_header()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +f.write('set.num_extend_elem_props(): ' + str(set.num_extend_elem_props()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +set.get_extend_elem_prop_row(2) +f.write('set.elem_prop_keys(): ' + str(set.elem_prop_keys()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +set.set_extend_elem_prop_row(ext_prop_row_maps[0],6) +set.add_extend_elem_props(set2) +set.resize(9,561,0) +f.write('set.prop_index(PROP_3): ' + str(set.prop_index(PROP_3)).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +set.push_back(objects[6][8]) +f.write("\n\n-------------------------------------\n 145 MODFICATIONS \n-------------------------------------\n" + str(set) + "\n\n") +set.insert(objects[6][0],5) +set.add_extend_elem_props(set2) +set.push_back(objects[6][7]) +f.write('set.num_props(): ' + str(set.num_props()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +set.prop_name(7) +set.push_back(objects[6][1], ext_prop_row_maps[4]) +f.write("\n\n-------------------------------------\n 150 MODFICATIONS \n-------------------------------------\n" + str(set) + "\n\n") +f.write('set.elem_prop_keys(): ' + str(set.elem_prop_keys()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +f.write('set.has_elem_prop(ELEM_PROP_10): ' + str(set.has_elem_prop(ELEM_PROP_10)).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +f.write('set.vsize(): ' + str(set.vsize()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +set.resize(5,969,0) +f.write('set.has_prop(PROP_8): ' + str(set.has_prop(PROP_8)).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +set.elem_resize(2,367) +set.add_prop(PROP_2,692) +set.add_prop(PROP_8,147) +set.resize(8,245,0) +f.write("\n\n-------------------------------------\n 155 MODFICATIONS \n-------------------------------------\n" + str(set) + "\n\n") +f.write('set.get_extend_elem_prop(EXT_ELEM_PROP_5,3): ' + str(set.get_extend_elem_prop(EXT_ELEM_PROP_5,3)).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +set.prop_name(6) +set.remove_extend_elem_prop(EXT_ELEM_PROP_8) +set.add_extend_elem_props(set2) +set.get_extend_elem_prop_row(5) +set.set_extend_elem_prop(EXT_ELEM_PROP_2,"640",0) +f.write("\n\n-------------------------------------\n 160 MODFICATIONS \n-------------------------------------\n" + str(set) + "\n\n") +f.write('set.num_props(): ' + str(set.num_props()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +set.free_elem_degree() +set.get_extend_elem_prop_row(0) +f.write('set.has_extend_elem_prop(EXT_ELEM_PROP_9): ' + str(set.has_extend_elem_prop(EXT_ELEM_PROP_9)).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +f.write('set.elem_prop_keys(): ' + str(set.elem_prop_keys()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +f.write('set.prop_keys(): ' + str(set.prop_keys()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +set.remove_extend_elem_prop(EXT_ELEM_PROP_2) +f.write('set.prop(PROP_9): ' + str(set.prop(PROP_9)).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +f.write('set.size(): ' + str(set.size()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +set.free_elem_degree() +set.freeze_elem_degree() +f.write("\n\n-------------------------------------\n 165 MODFICATIONS \n-------------------------------------\n" + str(set) + "\n\n") +elem_props = set.get_elem_prop_header(); (objects,prop_row_maps,prop_rows) = recreate_elem_prop_objects(elem_props) +set.freeze_elem_degree() +elem_props = set.get_elem_prop_header(); (objects,prop_row_maps,prop_rows) = recreate_elem_prop_objects(elem_props) +set.remove_extend_elem_prop(EXT_ELEM_PROP_6) +set.remove_prop(PROP_9) +set.push_back(objects[2][6]) +set.remove_prop(PROP_8) +f.write("\n\n-------------------------------------\n 170 MODFICATIONS \n-------------------------------------\n" + str(set) + "\n\n") +set.resize(1,823,0) +f.write('set.num_props(): ' + str(set.num_props()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +set.elem_resize(1,218) +set.prop_name(4) +f.write('set.size(): ' + str(set.size()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +set.copy_extend_elem_prop_row(set2,4,0) +f.write('set.prop_index(PROP_3): ' + str(set.prop_index(PROP_3)).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +f.write('set.get_extend_elem_prop_header(): ' + str(set.get_extend_elem_prop_header()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +set.erase(0) +f.write("\n\n-------------------------------------\n 175 MODFICATIONS \n-------------------------------------\n" + str(set) + "\n\n") +set.remove_extend_elem_prop(EXT_ELEM_PROP_7) +f.write('set.num_extend_elem_props(): ' + str(set.num_extend_elem_props()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +set.elem_resize(2,672) +set.prop_name(0) +set.prop_name(2) +set.elem_resize(4,946) +f.write("\n\n-------------------------------------\n 180 MODFICATIONS \n-------------------------------------\n" + str(set) + "\n\n") +f.write('set.bsize(): ' + str(set.bsize()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +set.prop_name(7) +f.write('set.elem_prop_keys(): ' + str(set.elem_prop_keys()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +f.write('set.bsize(): ' + str(set.bsize()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +set.remove_extend_elem_prop(EXT_ELEM_PROP_4) +f.write('set.size(): ' + str(set.size()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +f.write('set.prop_keys(): ' + str(set.prop_keys()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +f.write('set.elem_prop_keys(): ' + str(set.elem_prop_keys()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +set.add_prop(PROP_8,859) +set.add_prop(PROP_9,835) +f.write('set.prop_keys(): ' + str(set.prop_keys()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +set.add_extend_elem_prop(EXT_ELEM_PROP_10,"-99") +f.write("\n\n-------------------------------------\n 185 MODFICATIONS \n-------------------------------------\n" + str(set) + "\n\n") +f.write('set.has_prop(PROP_9): ' + str(set.has_prop(PROP_9)).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +f.write('set.get_extend_elem_prop_header(): ' + str(set.get_extend_elem_prop_header()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +f.write('set.has_prop(PROP_2): ' + str(set.has_prop(PROP_2)).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +f.write('set.has_extend_elem_prop(EXT_ELEM_PROP_8): ' + str(set.has_extend_elem_prop(EXT_ELEM_PROP_8)).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +f.write('set.has_extend_elem_prop(EXT_ELEM_PROP_3): ' + str(set.has_extend_elem_prop(EXT_ELEM_PROP_3)).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +f.write('set.num_extend_elem_props(): ' + str(set.num_extend_elem_props()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +f.write('set.bsize(): ' + str(set.bsize()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +set.freeze_elem_degree() +elem_props = set.get_elem_prop_header(); (objects,prop_row_maps,prop_rows) = recreate_elem_prop_objects(elem_props) +set.resize(9,576,0) +set.insert(objects[4][4],1) +set.add_extend_elem_prop(EXT_ELEM_PROP_7,"-99") +f.write('set.get_extend_elem_prop(EXT_ELEM_PROP_9,6): ' + str(set.get_extend_elem_prop(EXT_ELEM_PROP_9,6)).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +set.set_extend_elem_prop_row(ext_prop_row_maps[6],8) +f.write("\n\n-------------------------------------\n 190 MODFICATIONS \n-------------------------------------\n" + str(set) + "\n\n") +set.remove_prop(PROP_6) +set.set_extend_elem_prop(EXT_ELEM_PROP_7,"493",2) +set.elem_resize(9,337) +set.add_prop(PROP_6,153) +f.write('set.bsize(): ' + str(set.bsize()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +f.write('set.prop_keys(): ' + str(set.prop_keys()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +set.free_elem_degree() +f.write("\n\n-------------------------------------\n 195 MODFICATIONS \n-------------------------------------\n" + str(set) + "\n\n") +f.write('set.num_extend_elem_props(): ' + str(set.num_extend_elem_props()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +f.write('set.prop_index(PROP_3): ' + str(set.prop_index(PROP_3)).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +set.add_extend_elem_props(set2) +set.erase(4) +set.add_extend_elem_prop(EXT_ELEM_PROP_1,"-99") +f.write('set.get_extend_elem_prop(EXT_ELEM_PROP_5,4): ' + str(set.get_extend_elem_prop(EXT_ELEM_PROP_5,4)).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +f.write('set.prop_index(PROP_10): ' + str(set.prop_index(PROP_10)).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +set.erase(8) +set.set_extend_elem_prop_row(ext_prop_row_maps[0],2) +f.write("\n\n-------------------------------------\n 200 MODFICATIONS \n-------------------------------------\n" + str(set) + "\n\n") +f.write('set.num_props(): ' + str(set.num_props()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +f.write('set.size(): ' + str(set.size()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +f.write('set.has_extend_elem_prop(EXT_ELEM_PROP_2): ' + str(set.has_extend_elem_prop(EXT_ELEM_PROP_2)).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +f.write('set.has_extend_elem_prop(EXT_ELEM_PROP_1): ' + str(set.has_extend_elem_prop(EXT_ELEM_PROP_1)).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +f.write('set.get_extend_elem_prop(EXT_ELEM_PROP_9,3): ' + str(set.get_extend_elem_prop(EXT_ELEM_PROP_9,3)).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +set.freeze_elem_degree() +elem_props = set.get_elem_prop_header(); (objects,prop_row_maps,prop_rows) = recreate_elem_prop_objects(elem_props) +f.write('set.get_extend_elem_prop_header(): ' + str(set.get_extend_elem_prop_header()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +set.freeze_elem_degree() +elem_props = set.get_elem_prop_header(); (objects,prop_row_maps,prop_rows) = recreate_elem_prop_objects(elem_props) +f.write('set.has_prop(PROP_2): ' + str(set.has_prop(PROP_2)).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +f.write('set.num_elem_props(): ' + str(set.num_elem_props()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +f.write('set.has_prop(PROP_1): ' + str(set.has_prop(PROP_1)).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +set.copy_extend_elem_prop_row(set2,0,1) +f.write('set.num_extend_elem_props(): ' + str(set.num_extend_elem_props()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +f.write('set.get_extend_elem_prop_header(): ' + str(set.get_extend_elem_prop_header()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +set.get_extend_elem_prop_row(6) +f.write('set.num_props(): ' + str(set.num_props()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +f.write('set.elem_prop_keys(): ' + str(set.elem_prop_keys()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +f.write('set.num_elem_props(): ' + str(set.num_elem_props()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +set.add_extend_elem_props(set2) +f.write("\n\n-------------------------------------\n 205 MODFICATIONS \n-------------------------------------\n" + str(set) + "\n\n") +set.elem_resize(2,89) +set.push_back(objects[2][6], ext_prop_row_maps[3]) +set.elem_resize(5,359) +set.free_elem_degree() +f.write('set.num_elem_props(): ' + str(set.num_elem_props()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +set.remove_extend_elem_prop(EXT_ELEM_PROP_10) +f.write("\n\n-------------------------------------\n 210 MODFICATIONS \n-------------------------------------\n" + str(set) + "\n\n") +f.write('set.bsize(): ' + str(set.bsize()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +f.write('set.vsize(): ' + str(set.vsize()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +f.write('set.has_extend_elem_prop(EXT_ELEM_PROP_1): ' + str(set.has_extend_elem_prop(EXT_ELEM_PROP_1)).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +f.write('set.num_extend_elem_props(): ' + str(set.num_extend_elem_props()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +f.write('set.prop_index(PROP_7): ' + str(set.prop_index(PROP_7)).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +f.write('set.num_extend_elem_props(): ' + str(set.num_extend_elem_props()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +set.insert(objects[6][7],5) +f.write('set.num_elem_props(): ' + str(set.num_elem_props()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +set.set_extend_elem_prop_row(ext_prop_row_maps[3],0) +set.add_extend_elem_prop(EXT_ELEM_PROP_6,"-99") +set.remove_prop(PROP_4) +f.write('set.num_extend_elem_props(): ' + str(set.num_extend_elem_props()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +set.add_extend_elem_props(set2) +f.write("\n\n-------------------------------------\n 215 MODFICATIONS \n-------------------------------------\n" + str(set) + "\n\n") +f.write('set.num_elem_props(): ' + str(set.num_elem_props()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +set.add_extend_elem_prop(EXT_ELEM_PROP_5,"-99") +set.remove_prop(PROP_7) +set.add_extend_elem_props(set2) +set.elem_resize(5,955) +set.resize(4,369,0) +f.write("\n\n-------------------------------------\n 220 MODFICATIONS \n-------------------------------------\n" + str(set) + "\n\n") +set.add_prop(PROP_4,364) +set.freeze_elem_degree() +elem_props = set.get_elem_prop_header(); (objects,prop_row_maps,prop_rows) = recreate_elem_prop_objects(elem_props) +set.add_prop(PROP_7,495) +set.free_elem_degree() +f.write('set.size(): ' + str(set.size()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +set.push_back(objects[6][6]) +f.write("\n\n-------------------------------------\n 225 MODFICATIONS \n-------------------------------------\n" + str(set) + "\n\n") +f.write('set.size(): ' + str(set.size()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +set.free_elem_degree() +f.write('set.vsize(): ' + str(set.vsize()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +f.write('set.get_extend_elem_prop(EXT_ELEM_PROP_5,3): ' + str(set.get_extend_elem_prop(EXT_ELEM_PROP_5,3)).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +set.append_extend_elem_props(set2) +f.write('set.prop_keys(): ' + str(set.prop_keys()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +set.push_back(objects[0][4]) +set.add_extend_elem_props(set2) +f.write('set.bsize(): ' + str(set.bsize()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +f.write('set.get_extend_elem_prop_header(): ' + str(set.get_extend_elem_prop_header()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +f.write('set.prop(PROP_10): ' + str(set.prop(PROP_10)).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +set.copy_extend_elem_prop_row(set2,3,4) +f.write("\n\n-------------------------------------\n 230 MODFICATIONS \n-------------------------------------\n" + str(set) + "\n\n") +set.get_extend_elem_prop_row(1) +f.write('set.prop_index(PROP_10): ' + str(set.prop_index(PROP_10)).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +f.write('set.has_elem_prop(ELEM_PROP_8): ' + str(set.has_elem_prop(ELEM_PROP_8)).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +set.set_extend_elem_prop(EXT_ELEM_PROP_10,"898",1) +f.write('set.bsize(): ' + str(set.bsize()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +f.write('set.bsize(): ' + str(set.bsize()).replace("', '"," ").replace("['","[ ").replace("']"," ]") + '\n') +set.get_extend_elem_prop_row(1) + + +#===================================================================================================================== +# Generated functions end here +#===================================================================================================================== + +f.write('\n\n-------------------------------------\n FINAL PRINT \n-------------------------------------\n') + +f.write(str(set)) + +print 'Ran python test successfully!' + +f.write('\n') + +f.close() diff --git a/python/scan.py b/python/scan.py new file mode 100644 index 0000000..b49699e --- /dev/null +++ b/python/scan.py @@ -0,0 +1,284 @@ +#!/usr/bin/env python + +import sys +import subprocess +import os.path +import getopt +import threading +import shutil + +global lock, cmds, stop + +lock = threading.Lock() +cmds = [] +stop = False + +def usage(): + print 'scan.py:\n arguments: samples_location, [other_options, echo_options, origin, axes, output]' + +def buildScanCmds(samples, other_options='', echo_options='', origin='', axes='', output_dir='', verbose=False, svd=0): + """Batch scans in multiple dimensions""" + + samples_ext = samples.split('.')[-1] + + if samples_ext == 'sst': + + state_ext = 'str' + + elif samples_ext == 'tst': + + state_ext = 'tct' + + else: + + raise Exception("Unrecognised samples extension '%s'" % samples_ext) + + + path = samples.split('/') + + if path.count('mcmc'): + + ind = path.index('mcmc') + + sub_path = '/'.join(path[ind+2:]) + sub_path = '.'.join(sub_path.split('.')[0:-1]) + + else: + sub_path = raw_input("Sub-path name: ") + + + + if not output_dir: + output_dir = '/home/tclose/Data/Tractography/analysis/scan/%s' % sub_path + + + + + if svd: + + #Round the value of svd up to the nearest multiple of 2. + if svd % 2: + svd += 1 + + axes = '/home/tclose/Data/Tractography/analysis/svd/%s' % sub_path + + if os.path.isdir(axes): + try: + subprocess.call('svn delete --force %s' % axes) + except OSError: + shutil.rmtree(axes) + + os.makedirs(axes) + + svd_file = axes + '.' + samples_ext + + svd_cmd = '/home/tclose/Code/Tractography/bin/svd_fibres %s %s -max %d' % (samples, svd_file, svd) + + if verbose: + print 'SVD Command: ' + print '\n\n%s\n' % svd_cmd + + subprocess.call(svd_cmd, shell=True) + + comp_i = 0 + + for dir_i in range(0,svd,2): + + subdir = 'principle-comp_%d-%d' % (dir_i, dir_i+1) + + os.mkdir(os.path.join(axes,subdir)) + + + for comp_i in range(0,svd): + + #Round the value of svd down to the nearest multiple of 2. + if comp_i % 2: + dir_i = comp_i - 1 + else: + dir_i = comp_i + + subdir = 'principle-comp_%d-%d' % (dir_i, dir_i+1) + + select_cmd = '/home/tclose/Code/Tractography/bin/select_fibres %s %s/%s/%d.%s -inc %d' % (svd_file, axes, subdir, comp_i, state_ext, comp_i) + + if verbose: + print 'Select Command: ' + print '\n\n%s\n' % select_cmd + + subprocess.call(select_cmd, shell=True) + + + os.remove(svd_file) + try: + os.remove(svd_file + 'x') + os.remove(svd_file + 'xx') + except OSError: + None + + elif not axes: + + if state_ext == 'str': + + axes = '/home/tclose/Data/Tractography/analysis/scan/templates/strand/no_intens' + + elif state_ext == 'tct': + + axes = '/home/tclose/Data/Tractography/analysis/scan/templates/tract/no_intens' + + else: + + raise Exception("Unrecognised state extension '%s'" % state_ext) + + + # If directory exists, clean all files within it first. + if os.path.isdir(output_dir): + try: + subprocess.call('svn delete --force %s' % output_dir) + except OSError: + shutil.rmtree(output_dir) + + os.makedirs(output_dir) + + axes_subdir = os.listdir(axes) + + if '.svn' in axes_subdir: + axes_subdir.remove('.svn') + + global cmds + + cmds = [] + + for dir in axes_subdir: + + masks = os.listdir(os.path.join(axes,dir)) + + if '.svn' in masks: + masks.remove('.svn') + + for mask in masks[:]: + if mask.split('.')[-1] <> state_ext: + masks.remove(mask) + + mask1 = os.path.join(axes,dir,masks[0]) + mask2 = os.path.join(axes,dir,masks[1]) + + if svd: + strip_mask1 = 'comp_%s' % masks[0] + strip_mask2 = 'comp_%s' % masks[1] + else: + strip_mask1 = '.'.join(masks[0].split('.')[0:-1]) + strip_mask2 = '.'.join(masks[1].split('.')[0:-1]) + + echo_cmd = '/home/tclose/code/bin/echo_parameters %s -method scan -output %s/%s_%s.mif -axis1 %s -axis2 %s %s' % (samples, output_dir, strip_mask1, strip_mask2, mask1, mask2, ' '.join(echo_options)) + + if verbose: + print 'Echo Command: ' + print echo_cmd + + echo = subprocess.Popen(echo_cmd, stdout=subprocess.PIPE, shell=True).communicate()[0] + + if not echo: + raise Exception ('Echo command failed: (%s)' % echo_cmd) + + cmd = '/home/tclose/code/bin/' + echo.strip() + ' ' + other_options + + cmds.append(cmd) + + if verbose: + print 'Scan Command (echo): ' + print '\n%s\n\n' % cmd + + + + + print "MATLAB plot command:\n\nplot_scan %s -state %s.iter.%s \n\n" % (output_dir, '.'.join(samples.split('.')[0:-1]), samples.split('.')[-1]) + + +def runScanCmds(): + + global cmds + + while True: + lock.acquire() + if not len(cmds): + lock.release() + return None + cmd = cmds.pop() + lock.release() + + subprocess.call(cmd, shell=True) + + +if __name__ == '__main__': + + try: + opts, args = getopt.getopt(sys.argv[1:], "ho:a:p:e:vs:", ["help", "origin", "axes", "output", "echo_options", "verbose", "svd"]) + except getopt.GetoptError: + usage() + sys.exit(2) + + origin = '' + axes = '' + output_dir = '' + echo_options = '' + verbose = False + stop = False + svd = 0 + + for opt, arg in opts: + if opt in ("-h", "--help"): + usage() + sys.exit() + elif opt in ("-o", "--origin"): + origin = arg + elif opt == ('-a', "--axes"): + axes = arg + elif opt in ("-p", "--output"): + output_dir = arg + elif opt in ("-e", "--echo_options"): + output_dir = arg + elif opt in ("-v", "--verbose"): + verbose = True + elif opt in ("-s", "--svd"): + svd = int(arg) + + if len(args) == 0: + usage() + sys.exit(2) + + samples = args[0] + + if len(args) > 1: + other_options = ' '.join(args[1:]) + else: + other_options = '' + + global cmds + + buildScanCmds(samples, other_options, echo_options, origin, axes, output_dir, verbose, svd) + + + print 'Running %d scans...\n\n' % len(cmds) + + try: num_processors = os.sysconf('SC_NPROCESSORS_ONLN') + except: + try: num_processors = int(os.environ['NUMBER_OF_PROCESSORS']) + except: num_processors = 1 + + if verbose: + print '' + print 'launching ' + str(num_processors) + ' threads' + print '' + + threads = [] + for i in range (1, num_processors): + t = threading.Thread (target=runScanCmds); + t.start() + threads.append (t) + + exit_value = runScanCmds() + + for t in threads: t.join() + + exit (stop > 1) + \ No newline at end of file diff --git a/src/NFG_links b/src/NFG_links new file mode 100755 index 0000000..14b0608 --- /dev/null +++ b/src/NFG_links @@ -0,0 +1,21 @@ +#!/bin/bash + +for dir in `ls $1`; do + + rm phantom/$dir/* + + for filename in `ls $1/$dir`; do + + ext_pos=$(( ${#filename}-1 )) + ext=${filename:$ext_pos} + + if [ $ext = 'c' ]; then + ln -s $1/$dir/$filename phantom/$dir/${filename}pp + + elif [ $ext = 'h' ]; then + ln -s $1/$dir/$filename phantom/$dir/$filename + + fi + + done +done diff --git a/src/blossom5/CHANGES.TXT b/src/blossom5/CHANGES.TXT new file mode 100644 index 0000000..17e1e77 --- /dev/null +++ b/src/blossom5/CHANGES.TXT @@ -0,0 +1,32 @@ +Changes from version 1.0 to 2.0: + +- Replaced Fibonacci heaps with pairing heaps + (M. Fredman, R. Sedgewick, D. Sleator, R. Tarjan, Algorithmica 1(1):111-129, 1986). + Pairing heaps take less memory (namely, 2 pointers per edge less) compared to Fibonacci heaps, + and seem to be marginally faster. + + Finonacci heaps are still available - replace PQ.h with PQ-Fibonacci.h . + +- Changed data structures so that the time in SHRINK operations + is O(m log n) per augmentation (I believe). This was not the case + in version 1.0 (see footnote 5 in the MPC paper). + +I re-ran experiments corresponding to tables 1,3,4,5,9 in the paper. +The new version was marginally faster (e.g. up to 10% faster) on all examples +except for lrb744710, where it was about 3 times faster. + +Changes from version 2.0 to 2.01 (thanks to Nic Schraudolph and Dmitry Kamenetsky for useful suggestions): + +- Fixed bug in block.h (replaced "new char[] ... delete ..." with "new char[] ... delete[] ..."; +in the first case the behavious is not specified, though most compilers would compile it correctly.) + +- Removed PQ-Fibonacci.h + +- Added disclaimer about using floating point numbers + +Changes from version 2.01 to 2.02 + +- Tweaks to stop compiler warnings, + changed "delete rev_mapping" to "delete [] rev_mapping" in misc.cpp (thanks to Nic Schraudolph for suggestions) + +- Added a statement to license conditions diff --git a/src/blossom5/CheckPerfectMatching.cpp b/src/blossom5/CheckPerfectMatching.cpp new file mode 100644 index 0000000..0099f2f --- /dev/null +++ b/src/blossom5/CheckPerfectMatching.cpp @@ -0,0 +1,172 @@ +#include +#include "blossom5/PerfectMatching.h" +#include "blossom5/LCA.h" + +struct Node +{ + PerfectMatching::REAL sum; // = twice_y[i] + twice_y[i->parent] + twice_y[i->parent->parent] + ... + Node* match; + Node* parent; + Node* child; + Node* sibling; + int lca_preorder; +}; + + +int CheckPerfectMatchingOptimality(int node_num, int edge_num, int* edges, int* weights, PerfectMatching* pm, PerfectMatching::REAL threshold) +{ + int _i, _j, _e; + Node* i; + Node* j; + int blossom_num = pm->GetBlossomNum(); + int* blossom_parents = new int[node_num+blossom_num]; + PerfectMatching::REAL* twice_y = new PerfectMatching::REAL[node_num+blossom_num]; + + PerfectMatching::REAL y_blossom_min = 0; + PerfectMatching::REAL slack_min = 0; + PerfectMatching::REAL active_slack_max = 0; + + // step 1 - read dual solution and construct tree + pm->GetDualSolution(blossom_parents, twice_y); + Node* nodes = new Node[node_num+blossom_num+1]; + memset(nodes, 0, (node_num+blossom_num+1)*sizeof(Node)); + Node* ROOT = nodes+node_num+blossom_num; + for (_i=0, i=nodes; _isum = twice_y[_i]; + if (_i >= node_num && y_blossom_min > i->sum) y_blossom_min = i->sum; + if (blossom_parents[_i] >= 0) + { + if (blossom_parents[_i]=node_num+blossom_num) + { + delete [] nodes; + delete [] blossom_parents; + delete [] twice_y; + return 2; + } + i->parent = nodes + blossom_parents[_i]; + i->sibling = i->parent->child; + i->parent->child = i; + } + } + delete [] blossom_parents; + delete [] twice_y; + + for (i=nodes; iparent) + { + i->parent = ROOT; + i->sibling = ROOT->child; + ROOT->child = i; + } + } + + LCATree* lca_tree = new LCATree(node_num+blossom_num+1); + Node** rev_mapping = new Node*[node_num+blossom_num]; + + i = ROOT; + while ( 1 ) + { + if (i->child) + { + if (i < nodes+node_num) { delete [] nodes; delete lca_tree; delete [] rev_mapping; return 2; } + i->child->sum += i->sum; + i = i->child; + } + else + { + if (i >= nodes+node_num) { delete [] nodes; delete lca_tree; delete [] rev_mapping; return 2; } + while ( 1 ) + { + i->lca_preorder = lca_tree->Add(i, i->parent); + rev_mapping[i->lca_preorder] = i; + if (i->sibling) break; + i = i->parent; + if (i == ROOT) + { + i->lca_preorder = lca_tree->AddRoot(i); + break; + } + } + if (i == ROOT) break; + i = i->sibling; + i->sum += i->parent->sum; + } + } + + int matched_num = 0; + for (_e=0; _e=node_num || _j>=node_num || _i==_j) { delete [] nodes; delete lca_tree; delete [] rev_mapping; return 2; } + + int lca_i = nodes[_i].lca_preorder; + int lca_j = nodes[_j].lca_preorder; + lca_tree->GetPenultimateNodes(lca_i, lca_j); + i = rev_mapping[lca_i]; + j = rev_mapping[lca_j]; + PerfectMatching::REAL twice_slack = 2*weights[_e] - (nodes[_i].sum - i->parent->sum) - (nodes[_j].sum - j->parent->sum); + if (slack_min > twice_slack) slack_min = twice_slack; + if (pm->GetSolution(_e)) + { + if (pm->GetMatch(_i)!=_j || pm->GetMatch(_j)!=_i || i->match || j->match) { delete [] nodes; delete lca_tree; delete [] rev_mapping; return 2; } + i->match = j; + j->match = i; + if (active_slack_max < twice_slack) active_slack_max = twice_slack; + matched_num += 2; + } + } + + delete [] nodes; + delete lca_tree; + delete [] rev_mapping; + + if (matched_num != node_num) return 2; + + if (y_blossom_min < -threshold || slack_min < -threshold || active_slack_max > threshold) + { + printf("ERROR in CheckPerfectMatchingOptimality():\n"); + if ( ((PerfectMatching::REAL)1 / 2) == 0 ) + printf("\ty_blossom_min=%d\n\tslack_min=%d\n\tactive_slack_max=%d\n", (int)y_blossom_min, (int)slack_min, (int)active_slack_max); + else + printf("\ty_blossom_min=%.15f\n\tslack_min=%.15f\n\tactive_slack_max=%.15f\n", (double)y_blossom_min, (double)slack_min, (double)active_slack_max); + return 1; + } + + return 0; +} + +double ComputePerfectMatchingCost(int node_num, int edge_num, int* edges, int* weights, PerfectMatching* pm) +{ + int i; + int j; + int e; + double cost = 0; + + int* nodes = new int[node_num]; + memset(nodes, 0, node_num*sizeof(int)); + for (e=0; eGetSolution(e)) + { + i = edges[2*e]; + j = edges[2*e+1]; + nodes[i] ++; + nodes[j] ++; + cost += weights[e]; + } + } + for (i=0; i +#include +#include +#include "blossom5/GEOMGeomPerfectMatching.h" +#include "blossom5/GEOMGPMkdtree.h" + + + + +// greedy procedure to make sure that a perfect matching exists: +// 1. construct a matching among existing edges +// (greedy procedure: pick a node, check whether there are edges leading +// to unmatched nodes, if there are pick the edge with the smallest length). +// 2. take remaining unmatched nodes, construct kd-tree for them, +// assign an ordering to nodes (last visited time during left-most depth-first search), +// add edges between consecutive nodes (2*i,2*i+1) +void GeomPerfectMatching::CompleteInitialMatching() +{ + if (options.verbose) printf("adding edges to make sure that a perfect matching exists..."); + PointId p, q; + Edge* e; + double len, len_min; + int unmatched_num = 0, edge_num0 = edge_num; + + // construct greedy matching + for (p=0; pnext[0]) + { + if (nodes[e->head[0]].is_marked) continue; + len = Dist2(p, e->head[0]); + if (q < 0 || len_min > len) + { + q = e->head[0]; + len_min = len; + } + } + if (q >= 0) + { + nodes[p].is_marked = nodes[q].is_marked = 1; + } + else unmatched_num ++; + } + + if (unmatched_num == 0) + { + for (p=0; pAddPerfectMatching(rev_mapping); + + delete kd_tree; + delete [] unmatched_coords; + delete [] rev_mapping; + + if (options.verbose) printf("done (%d edges)\n", edge_num-edge_num0); +} + +void GeomPerfectMatching::InitKNN(int K) +{ + if (node_num != node_num_max) { printf("InitKNN() cannot be called before all points have been added!\n"); exit(1); } + if (options.verbose) printf("adding K nearest neighbors (K=%d)\n", K); + + int dir, k; + PointId p; + Edge* e; + + if (K > node_num - 1) K = node_num - 1; + + GPMKDTree* kd_tree = new GPMKDTree(DIM, node_num, coords, this); + PointId* neighbors = new PointId[K]; + + for (p=0; pnext[dir]) + { + nodes[e->head[dir]].is_marked = 1; + } + + kd_tree->ComputeKNN(p, K, neighbors); + for (k=0; knext[dir]) + { + nodes[e->head[dir]].is_marked = 0; + } + } + + delete kd_tree; + delete [] neighbors; +} + +#ifdef DELAUNAY_TRIANGLE + +#ifdef _MSC_VER +#pragma warning(disable: 4311) +#pragma warning(disable: 4312) +#endif + +extern "C" { +#define ANSI_DECLARATORS +#define TRILIBRARY +#define NO_TIMER +#define main NO_MAIN_FUNCTION +#include "blossom5/triangle/triangle.c" +} + +void GeomPerfectMatching::InitDelaunay() +{ + if (node_num < 16) return; + if (options.verbose) printf("adding edges in Delaunay triangulation\n"); + + int k; + + struct triangulateio in, out, vorout; + in.numberofpoints = node_num; + in.numberofpointattributes = 0; + in.pointlist = (REAL *) malloc(in.numberofpoints * 2 * sizeof(REAL)); + for (k=0; k<2*node_num; k++) in.pointlist[k] = coords[k]; + in.pointattributelist = NULL; + in.pointmarkerlist = NULL; + in.numberofsegments = 0; + in.numberofholes = 0; + in.numberofregions = 0; + in.regionlist = 0; + + out.pointlist = (REAL *) NULL; + out.pointattributelist = (REAL *) NULL; + out.pointmarkerlist = (int *) NULL; + out.trianglelist = (int *) NULL; + out.triangleattributelist = (REAL *) NULL; + out.neighborlist = (int *) NULL; + out.segmentlist = (int *) NULL; + out.segmentmarkerlist = (int *) NULL; + out.edgelist = (int *) NULL; + out.edgemarkerlist = (int *) NULL; + + vorout.pointlist = (REAL *) NULL; + vorout.pointattributelist = (REAL *) NULL; + vorout.edgelist = (int *) NULL; + vorout.normlist = (REAL *) NULL; + + triangulate("pczAevn", &in, &out, &vorout); + + free(in.pointlist); + free(out.pointlist); + free(out.pointmarkerlist); + free(out.trianglelist); + free(out.neighborlist); + free(out.segmentlist); + free(out.segmentmarkerlist); + free(out.edgemarkerlist); + free(vorout.pointlist); + free(vorout.pointattributelist); + free(vorout.edgelist); + free(vorout.normlist); + + for (k=0; k +#include +#include +#include "blossom5/GEOMGeomPerfectMatching.h" +#include "blossom5/GEOMGPMkdtree.h" + + +GeomPerfectMatching::GeomPerfectMatching(int nodeNum, int _DIM) + : DIM(_DIM), + node_num(0), + node_num_max(nodeNum), + edge_num(0) +{ + if (node_num_max < 1) { printf("too few nodes\n"); exit(1); } + if (node_num_max & 1) { printf("# of points is odd: perfect matching cannot exist\n"); exit(1); } + nodes = (Node*) malloc(node_num_max*sizeof(Node)); + memset(nodes, 0, node_num_max*sizeof(Node)); + edges = new Block(512); + coords = (REAL*) malloc((DIM+1)*node_num_max*sizeof(REAL)); + sums = coords + DIM*node_num_max; + matching = (int*) malloc(node_num_max*sizeof(int)); + int i; + for (i=0; i= node_num_max) + { + printf("Error: you are trying to add too many points!\n"); + exit(1); + } + memcpy(coords+DIM*node_num, coord, DIM*sizeof(REAL)); + return node_num ++; +} + +void GeomPerfectMatching::AddInitialEdge(PointId _i, PointId _j) +{ + assert(_i>=0 && _i=0 && _jNew(); + edge_num ++; + + e->head[1] = _i; + e->head[0] = _j; + e->next[0] = i->first[0]; + e->next[1] = j->first[1]; + i->first[0] = e; + j->first[1] = e; +} + + +GeomPerfectMatching::REAL GeomPerfectMatching::ComputeCost(PointId* matching) +{ + if (node_num != node_num_max) { printf("ComputeCost() cannot be called before all points have been added!\n"); exit(1); } + + REAL cost = 0; + int i; + for (i=0; i=node_num || matching[matching[i]]!=i) + { + printf("ComputeCost(): not a valid matching!\n"); + exit(1); + } + if (matching[i] > i) + { + cost += Dist(i, matching[i]); + } + } + return cost; +} + + diff --git a/src/blossom5/GEOM/GPMkdtree.cpp b/src/blossom5/GEOM/GPMkdtree.cpp new file mode 100644 index 0000000..0d9211a --- /dev/null +++ b/src/blossom5/GEOM/GPMkdtree.cpp @@ -0,0 +1,688 @@ +#include +#include +#include +#include "blossom5/GEOMGPMkdtree.h" +#include "blossom5/timer.h" + + +// 'mapping' must be of size 2*N. (array[N], ... array[2*N-1] is used as a temporary buffer). +// After the call array[mapping[0]] <= array[mapping[1]] <= ... <= array[mapping[N-1]]. +// array is not modified. +template inline void sort(Type* array, int array_skip, int* mapping, int N) +{ + // mergesort + int i; + int* mappingSrc = mapping; + int* mappingDst = mapping + N; + int* pSrc1; + int* pSrc2; + int* pSrc1End; + int* pSrc2End; + int* pDst; + + for (i=0; i<(N&(~1)); i+=2) + { + if (array[array_skip*i] < array[array_skip*(i+1)]) + { + mappingSrc[i] = i; + mappingSrc[i+1] = i+1; + } + else + { + mappingSrc[i] = i+1; + mappingSrc[i+1] = i; + } + } + if (i != N) mappingSrc[i] = i; + + int step; + for (step=2; step= mappingSrc + N) + { + memcpy(pDst, pSrc1, (int)((char*)(mappingSrc + N) - (char*)pSrc1)); + break; + } + pSrc2 = pSrc1End; + pSrc2End = pSrc2 + step; + if (pSrc2End > mappingSrc + N) pSrc2End = mappingSrc + N; + while ( 1 ) + { + if (array[(array_skip)*(*pSrc1)] < array[array_skip*(*pSrc2)]) + { + *pDst ++ = *pSrc1 ++; + if (pSrc1 == pSrc1End) + { + memcpy(pDst, pSrc2, (int)((char*)pSrc2End - (char*)pSrc2)); + pDst = (int*) ((char*)pDst + (int)((char*)pSrc2End - (char*)pSrc2)); + break; + } + } + else + { + *pDst ++ = *pSrc2 ++; + if (pSrc2 == pSrc2End) + { + memcpy(pDst, pSrc1, (int)((char*)pSrc1End - (char*)pSrc1)); + pDst = (int*) ((char*)pDst + (int)((char*)pSrc1End - (char*)pSrc1)); + break; + } + } + } + } + pDst = mappingDst; + mappingDst = mappingSrc; + mappingSrc = pDst; + } + if (mappingSrc != mapping) memcpy(mapping, mappingSrc, N*sizeof(int)); +} + +////////////////////////////////////////////////////////////////////////////////////////// + +#define NEIGHBOR_PARENT(k) (((k)-1)>>1) +#define NEIGHBOR_FIRST_CHILD(k) (((k)<<1)+1) + +Neighbors::Neighbors() +{ + K_max = 0; + dist_array = NULL; +} + +Neighbors::~Neighbors() +{ + if (dist_array) delete [] dist_array; +} + +void Neighbors::Init(int _K, PointId* _array) +{ + K = _K; + array = _array; + num = 0; + if (K > K_max) + { + if (dist_array) delete [] dist_array; + K_max = K; + dist_array = new double[K_max]; + } +} + +inline void Neighbors::Swap(int k1, int k2) +{ + PointId p = array[k1]; array[k1] = array[k2]; array[k2] = p; + double d = dist_array[k1]; dist_array[k1] = dist_array[k2]; dist_array[k2] = d; +} + +inline void Neighbors::Add(PointId p, double dist) +{ + int k; + if (num < K) + { + k = num ++; + array[k] = p; + dist_array[k] = dist; + while ( k > 0 ) + { + int k_parent = NEIGHBOR_PARENT(k); + if (dist_array[k] <= dist_array[k_parent]) break; + Swap(k, k_parent); + k = k_parent; + } + } + else + { + if (dist_array[0] <= dist) return; + array[0] = p; + dist_array[0] = dist; + k = 0; + while ( 1 ) + { + int k_child = NEIGHBOR_FIRST_CHILD(k); + if (k_child >= K) break; + if (k_child+1 < K && dist_array[k_child+1] > dist_array[k_child]) k_child ++; + if (dist_array[k] >= dist_array[k_child]) break; + Swap(k, k_child); + k = k_child; + } + } + //for (k=1; k 0); + return dist_array[0]; +} + +////////////////////////////////////////////////////////////////////////////////////////// + +GPMKDTree::GPMKDTree(int _D, int _point_num, REAL* coords, GeomPerfectMatching* _GPM) + : D(_D), DIM(_GPM->DIM), point_num(_point_num), GPM(_GPM) +{ + Node* i; + Node* j; + int d, d0, k; + int* mapping = new int[(D+2)*point_num]; + int* buf = mapping + D*point_num; + int* marking = buf + point_num; + memset(marking, 0, point_num*sizeof(int)); + int* ptr = mapping; + + int node_num_max = 4*point_num/3+2; + nodes = (Node*)malloc(node_num_max*sizeof(Node)); + rev_mapping = (Node**)malloc(point_num*sizeof(Node*)); + memset(rev_mapping, 0, point_num*sizeof(Node*)); + + REAL** coords_array = new REAL*[D]; + int* skip_array = new int[D]; + for (d=0; dsums; skip_array[d] = 1; } + + for (d=0; d(coords_array[d], skip_array[d], ptr, point_num); + if (d == DIM) sum_max = GPM->sums[ptr[point_num-1]]; + ptr += point_num; + } + + nodes[0].parent = NULL; + nodes[0].order = 0; + nodes[0].d = point_num; + nodes[0].first_child = NULL; + node_num = 1; + Node* first_unprocessed = &nodes[0]; + while ( (i=first_unprocessed) ) + { + first_unprocessed = i->first_child; + + int start = i->order; + int num0 = i->d, num; + if ((DIM==D && num0<=2) || (DIMd = -num0; + for (k=0; kpoints[k] = mapping[start+k]; + rev_mapping[mapping[start+k]] = i; + } + continue; + } + + // not a leaf. + if (node_num + 2 > node_num_max) + { + node_num_max = 3*node_num_max/2 + 16; + Node* nodes_old = nodes; + nodes = (Node*)realloc(nodes, node_num_max*sizeof(Node)); +#define UPDATE_NODE_PTR(ptr) ptr = (Node*)((char*)ptr + ((char*)nodes-(char*)nodes_old)) + UPDATE_NODE_PTR(i); + if (first_unprocessed) UPDATE_NODE_PTR(first_unprocessed); + for (k=0; k=0 && nodes[k].first_child) UPDATE_NODE_PTR(nodes[k].first_child); + } + for (k=0; kparent) ? ((i->parent->d + 1) % D) : 0; + //num = num0/2; + + const int FRACTION = 20; + int num_min = 1; if (num_min < num0/FRACTION) num_min = num0/FRACTION; + int num_max = num0-1; if (num_max > (FRACTION-1)*num0/FRACTION) num_max = (FRACTION-1)*num0/FRACTION; + int num_max_DIM = num0-1; + + if (D>DIM && (!i->parent || !i->parent->parent || !i->parent->parent->parent)) d0 = D-1; + else + { + d0 = -1; + REAL diff_max = 0; + for (d=0; d split) break; + } + + //////////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////////// + + ptr = mapping + d0*point_num; + for (k=start; kd = d0; + PointId p = ptr[start + num - ((num >= num0-num) ? 1 : 0)]; + i->coord = coords_array[d0][p*skip_array[d0]]; + i->first_child = j = &nodes[node_num]; + node_num += 2; + j->parent = (j+1)->parent = i; + j->order = start; + j->d = num; + (j+1)->order = start+num; + (j+1)->d = num0-num; + (j+1)->first_child = first_unprocessed; + j->first_child = j+1; + first_unprocessed = j; + } + + delete [] coords_array; + delete [] skip_array; + delete [] mapping; + + //////////////////////////////////////////////////////////////////////////////////// + // set ordering and depth_max + int depth = 0, depth_max = 0; + + // set ordering + i = &nodes[0]; + k = 0; + if (D > DIM) + { + // ordering for AddNegativeEdges() - tree preorder + while ( 1 ) + { + if (!IS_LEAF(i)) + { + i = i->first_child; + depth ++; + if (depth_max < depth) depth_max = depth; + } + else + { + while ( 1 ) + { + i->order = k ++; + + if (!i->parent) break; + if (i->parent->first_child == i) { i ++; break; } + i = i->parent; + depth --; + } + if (!i->parent) break; + } + } + } + else + { + // compute tree inorder - useful for nearest neighbor search so that that branches close to the input node are explored first + while ( 1 ) + { + if (!IS_LEAF(i)) + { + i = i->first_child; + depth ++; + if (depth_max < depth) depth_max = depth; + } + else + { + i->order = k ++; + while ( 1 ) + { + if (!i->parent) break; + if (i->parent->first_child == i) { i->parent->order = k ++; i ++; break; } + i = i->parent; + depth --; + } + if (!i->parent) break; + } + } + } + + traversing_buf = (REAL*) malloc((D + depth_max + 2)*sizeof(REAL)); +} + +GPMKDTree::~GPMKDTree() +{ + free(nodes); + free(rev_mapping); + free(traversing_buf); +} + +void GPMKDTree::AddPerfectMatching(PointId* rev_mapping) +{ + Node* i; + int k; + PointId p, q = -1; + i = &nodes[0]; + do + { + if (IS_LEAF(i)) + { + for (k=0; k<-i->d; k++) + { + p = i->points[k]; + if (q < 0) q = p; + else { GPM->AddInitialEdge(rev_mapping[p], rev_mapping[q]); q = -1; } + } + } + else + { + i = i->first_child; + continue; + } + + while ( i->parent ) + { + if (i->parent->first_child == i) { i ++; break; } + i = i->parent; + } + } while (i->parent); +} + +////////////////////////////////////////////////////////////////////////////////////////// + +#define MOVE_DOWN_LEFT(i)\ + {\ + *stack ++ = current_diff[i->d];\ + if (current_diff[i->d] <= 0 && (diff = i->coord - coord0[i->d]) < 0) current_diff[i->d] = diff;\ + i = i->first_child;\ + } + +#define MOVE_DOWN_RIGHT(i)\ + {\ + *stack ++ = current_diff[i->d];\ + if (current_diff[i->d] >= 0 && (diff = i->coord - coord0[i->d]) > 0) current_diff[i->d] = diff;\ + i = i->first_child+1;\ + } + +#define MOVE_LEFT(i)\ + {\ + int d_prev = i->parent->d;\ + current_diff[d_prev] = stack[-1];\ + if (current_diff[d_prev] <= 0 && (diff = i->parent->coord - coord0[d_prev]) < 0) current_diff[d_prev] = diff;\ + i --;\ + } + +#define MOVE_RIGHT(i)\ + {\ + int d_prev = i->parent->d;\ + current_diff[d_prev] = stack[-1];\ + if (current_diff[d_prev] >= 0 && (diff = i->parent->coord - coord0[d_prev]) > 0) current_diff[d_prev] = diff;\ + i ++;\ + } + +#define MOVE_UP(i)\ + {\ + i = i->parent;\ + current_diff[i->d] = *(-- stack);\ + } + +////////////////////////////////////////////////////////////////////////////////////////// + +#define MOVE_DOWN_LEFT_X(i)\ + {\ + *stack ++ = current_diff[i->d];\ + if (i->d < D-1) { if (current_diff[i->d] <= 0 && (diff = i->coord - coord0[i->d]) < 0) current_diff[i->d] = diff; }\ + else current_diff[i->d] = i->coord;\ + i = i->first_child;\ + } + +#define MOVE_DOWN_RIGHT_X(i)\ + {\ + *stack ++ = current_diff[i->d];\ + if (i->d < D-1) { if (current_diff[i->d] >= 0 && (diff = i->coord - coord0[i->d]) > 0) current_diff[i->d] = diff; }\ + i = i->first_child+1;\ + } + +#define MOVE_LEFT_X(i)\ + {\ + int d_prev = i->parent->d;\ + current_diff[d_prev] = stack[-1];\ + if (d_prev < D-1) { if (current_diff[d_prev] <= 0 && (diff = i->parent->coord - coord0[d_prev]) < 0) current_diff[d_prev] = diff; }\ + else current_diff[d_prev] = i->parent->coord;\ + i --;\ + } + +#define MOVE_RIGHT_X(i)\ + {\ + int d_prev = i->parent->d;\ + current_diff[d_prev] = stack[-1];\ + if (d_prev < D-1) { if (current_diff[d_prev] >= 0 && (diff = i->parent->coord - coord0[d_prev]) > 0) current_diff[d_prev] = diff; }\ + i ++;\ + } + +#define MOVE_UP_X(i)\ + {\ + i = i->parent;\ + current_diff[i->d] = *(-- stack);\ + } + +////////////////////////////////////////////////////////////////////////////////////////// + +/* +void GPMKDTree::ComputeKNN(PointId p0, int K, PointId* neighbors_array) +{ + int p; + REAL* coord0 = GPM->coords + p0*DIM; + + neighbors.Init(K, neighbors_array); + + for (p=0; pDist(coord0, GPM->coords+p*DIM)); + } +} +*/ + +void GPMKDTree::ComputeKNN(PointId p0, int K, PointId* neighbors_array) +{ + int neighbor_num = 0; + Node* i = rev_mapping[p0]; + int k, order0 = i->order; + REAL diff; + REAL* coords = GPM->coords; + REAL* coord0 = GPM->coords + p0*DIM; + REAL* current_diff = traversing_buf; + REAL* stack = traversing_buf + D; + + neighbors.Init(K, neighbors_array); + + for (k=0; kd; k++) + { + PointId p = i->points[k]; + if (p == p0) continue; + double dist2; + REAL* coord2 = coords+p*DIM; + GPM_GET_DIST2(dist2, coord0, coord2); + neighbors.Add(p, dist2); + } + } + else + { + if (neighbors.GetNum() < K || GPM->Norm2(current_diff) < neighbors.GetMax()) + { + if (i->order > order0) + { + MOVE_DOWN_LEFT(i); + } + else + { + MOVE_DOWN_RIGHT(i); + } + continue; + } + } + + while ( i->parent ) + { + if (i->parent->order > order0) + { + if (i->parent->first_child == i) + { + MOVE_RIGHT(i); + break; + } + } + else + { + if (i->parent->first_child != i) + { + MOVE_LEFT(i); + break; + } + } + MOVE_UP(i); + } + } while ( i->parent ); +} + + +////////////////////////////////////////////////////////////////////////////////////////// + +/* +void GPMKDTree::AddNegativeEdges(PointId p, PerfectMatching* pm) +{ + PointId q; + for (q=p+1; qnodes[q].is_marked) continue; + REAL len = GPM->Dist(p, q); + if (2*len - GPM->sums[p] - GPM->sums[q] < 0) + { + if (pm->AddNewEdge(p, q, len, true)>=0) + { + GPM->AddInitialEdge(p, q); + } + } + } +} +*/ + + +void GPMKDTree::AddNegativeEdges(PointId p0, PerfectMatching* pm) +{ + Node* i = rev_mapping[p0]; + int k, order0 = i->order; + bool check; + REAL diff; + REAL* coords = GPM->coords; + REAL* coord0 = coords + p0*DIM; + REAL* sums = GPM->sums; + REAL sum0 = sums[p0]; + REAL* current_diff = traversing_buf; + REAL* stack = traversing_buf + D; + + for (k=0; i->points[k]!=p0; k++) {} + for (k++; k<-i->d; k++) + { + PointId p = i->points[k]; + + REAL len = GPM->Dist(coord0, GPM->coords+p*DIM); + if (2*len - GPM->sums[p] < GPM->sums[p0]) + { + double start_time = get_time(); + if (pm->AddNewEdge(p0, p, len, true)>=0) GPM->AddInitialEdge(p0, p); + GPM->graph_update_time += get_time() - start_time; + } + } + + for (k=0; korder > order0) + { + if (IS_LEAF(i)) + { + for (k=0; k<-i->d; k++) + { + PointId p = i->points[k]; + if (!GPM->nodes[p].is_marked) + { + //REAL* coord2 = coords+p*DIM; + //REAL threshold = sums[p0]+sums[p]; + //GPM_CHECK_DIST(check, coord0, coord2, threshold); + //if (check) + { + REAL len = GPM->Dist(coord0, GPM->coords+p*DIM); + if (2*len - GPM->sums[p] < GPM->sums[p0]) + { + double start_time = get_time(); + if (pm->AddNewEdge(p0, p, len, true)>=0) GPM->AddInitialEdge(p0, p); + GPM->graph_update_time += get_time() - start_time; + } + } + } + } + } + else + { + REAL threshold = current_diff[D-1] + sum0; + GPM_CHECK_NORM(check, current_diff, threshold); + if (check) + { + MOVE_DOWN_LEFT_X(i); + continue; + } + } + } + + while ( i->parent ) + { + if (i->parent->first_child == i) + { + MOVE_RIGHT_X(i); + break; + } + MOVE_UP_X(i); + } + } while (i->parent); +} diff --git a/src/blossom5/GEOM/GPMkdtree.h b/src/blossom5/GEOM/GPMkdtree.h new file mode 100644 index 0000000..1372cd1 --- /dev/null +++ b/src/blossom5/GEOM/GPMkdtree.h @@ -0,0 +1,105 @@ +/* + GPMkdtree.h - kd-tree data structure for pricing in complete geometric instances + + Copyright 2008 Vladimir Kolmogorov (vnk@adastral.ucl.ac.uk) + + This software can be used for research purposes only. Commercial use is prohibited. + Public redistribution of the code or its derivatives is prohibited. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#ifndef NJKASKJTASJNBAJSNRBAJS +#define NJKASKJTASJNBAJSNRBAJS + +#include "blossom5/GEOMGeomPerfectMatching.h" + +struct Neighbors +{ + typedef GeomPerfectMatching::REAL REAL; + typedef GeomPerfectMatching::PointId PointId; + + Neighbors(); + ~Neighbors(); + + int GetNum() { return num; } + + void Init(int K, PointId* array); + void Add(PointId p, double dist); + double GetMax(); + +private: + void Swap(int k1, int k2); + PointId* array; + double* dist_array; + int num, K, K_max; +}; + + + +struct GPMKDTree +{ + typedef GeomPerfectMatching::REAL REAL; + typedef GeomPerfectMatching::PointId PointId; + + GPMKDTree(int D, int point_num, REAL* coords, GeomPerfectMatching* GPM); + ~GPMKDTree(); + + // if D == DIM + void AddPerfectMatching(PointId* rev_mapping); + void ComputeKNN(PointId p, int K, PointId* neighbors); + + // if D == DIM+1 + void AddNegativeEdges(PointId p, PerfectMatching* pm); + + ////////////////////////////////////////////////////////////////////////// + +public: +#define CHILDREN_MAX 2 + struct Node + { + Node* parent; + int d; // split dimension. d<0 indicates a leaf. +#define IS_LEAF(i) ((i)->d < 0) + union + { + struct // for non-leaves + { + REAL coord; + Node* first_child; // the second child is first_child+1 + }; + struct // for leaves + { + PointId points[CHILDREN_MAX]; // the number of points is -d + }; + }; + int order; + }* nodes; + + + ////////////////////////////////////////////////////////////////////////// + Node** rev_mapping; + + int D, DIM, point_num, node_num; + REAL sum_max; + REAL* traversing_buf; + GeomPerfectMatching* GPM; + + Neighbors neighbors; +}; + + + + +#endif diff --git a/src/blossom5/GEOM/GPMmain.cpp b/src/blossom5/GEOM/GPMmain.cpp new file mode 100644 index 0000000..08db6b4 --- /dev/null +++ b/src/blossom5/GEOM/GPMmain.cpp @@ -0,0 +1,148 @@ +#include +#include +#include +#include "blossom5/GEOMGeomPerfectMatching.h" +#include "blossom5/GEOMGPMkdtree.h" +#include "blossom5/timer.h" + + + +GeomPerfectMatching::REAL GeomPerfectMatching::SolveComplete() +{ + if (node_num != node_num_max) { printf("ComputeCost() cannot be called before all points have been added!\n"); exit(1); } + + PointId p, q; + int e = 0, E = node_num*(node_num-1)/2; + PerfectMatching* pm = new PerfectMatching(node_num, E); + for (p=0; pAddEdge(p, q, Dist(p, q)); + } + } + pm->options = options; + pm->Solve(); + for (p=0; pGetSolution(e++)) + { + matching[p] = q; + matching[q] = p; + } + } + } + delete pm; + return ComputeCost(matching); +} + +GeomPerfectMatching::REAL GeomPerfectMatching::Solve() +{ + double start_time = get_time(); + double perfect_matching_time = 0; + double negative_edges_time = 0; + if (options.verbose) { printf("starting geometric matching with %d points\n", node_num); fflush(stdout); } + PointId p, q; + Edge* e; + int _e; + int iter; + bool success = false; + PerfectMatching* pm = NULL; + GPMKDTree* kd_tree; + + double init_matching_time = get_time(); + + if (gpm_options.init_Delaunay) InitDelaunay(); + if (gpm_options.init_KNN > 0) InitKNN(gpm_options.init_KNN); + if (gpm_options.init_greedy) CompleteInitialMatching(); + + init_matching_time = get_time() - init_matching_time; + + graph_update_time = 0; + + int iter_max = gpm_options.iter_max; + for (iter=0; iter_max<=0 || iterStartUpdate(); + for (p=0; pGetTwiceSum(p); + if ( ((REAL)1 / 2) == 0 && ((PerfectMatching::REAL)1 / 2) != 0 ) sums[p] = (REAL)ceil((double)s); + else sums[p] = (REAL)s; + } + if (options.verbose) { printf("building kd_tree..."); fflush(stdout); } + { + kd_tree = new GPMKDTree(DIM+1, node_num, coords, this); + } + if (options.verbose) { printf(" done. Now adding negative edges:\n "); fflush(stdout); } + + for (p=0; pnext[0]) nodes[e->head[0]].is_marked = 1; + for (e=nodes[p].first[1]; e; e=e->next[1]) nodes[e->head[1]].is_marked = 1; + kd_tree->AddNegativeEdges(p, pm); + for (e=nodes[p].first[0]; e; e=e->next[0]) nodes[e->head[0]].is_marked = 0; + for (e=nodes[p].first[1]; e; e=e->next[1]) nodes[e->head[1]].is_marked = 0; + } + delete kd_tree; + //if (edge_num - edge_num0 > node_num / 32) + if ( 0 ) // always reuse previous computation + { + delete pm; + pm = NULL; + } + else + { + pm->FinishUpdate(); + if (edge_num0 == edge_num) success = true; + } + if (options.verbose) { printf("\ndone (%d edges added)\n", edge_num-edge_num0); fflush(stdout); } + negative_edges_time += get_time() - negative_edges_start_time; + } + if (!pm) + { + int E = 5*node_num; + if (E < 5*edge_num/4) E = 5*edge_num/4; + pm = new PerfectMatching(node_num, E); + for (e=edges->ScanFirst(); e; e=edges->ScanNext()) + { + p = e->head[1]; q = e->head[0]; + pm->AddEdge(p, q, Dist(p, q)); + } + } + if (options.verbose) printf("iter %d: ", iter+1); + pm->options = options; + double perfect_matching_start = get_time(); + pm->Solve(); + perfect_matching_time += get_time() - perfect_matching_start; + if (success) break; + } + + for (_e=0, e=edges->ScanFirst(); e; _e++, e=edges->ScanNext()) + { + if (pm->GetSolution(_e)) + { + p = e->head[1]; q = e->head[0]; + matching[p] = q; + matching[q] = p; + } + } + delete pm; + REAL cost = ComputeCost(matching); + if (options.verbose) + { + printf("geometric matching finished [%.3f secs]. cost=%.1f \n", get_time()-start_time, (double)cost); + printf(" selecting initial edges: [%.3f secs], perfect matching: [%.3f secs]\n", init_matching_time, perfect_matching_time); + printf(" pricing: [%.3f secs] including graph updates: [%.3f secs]\n", negative_edges_time, graph_update_time); + fflush(stdout); + } + return cost; +} + diff --git a/src/blossom5/GEOM/GeomPerfectMatching.h b/src/blossom5/GEOM/GeomPerfectMatching.h new file mode 100644 index 0000000..d783a90 --- /dev/null +++ b/src/blossom5/GEOM/GeomPerfectMatching.h @@ -0,0 +1,177 @@ +/* + GeomPerfectMatching.h - computing min cost perfect matching in complete geometric instances (with edge weights equal to Euclidean distances) + + Copyright 2008 Vladimir Kolmogorov (vnk@adastral.ucl.ac.uk) + + This software can be used for research purposes only. Commercial use is prohibited. + Public redistribution of the code or its derivatives is prohibited. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef ASKHALKSJBRASMNABFAJSTAS +#define ASKHALKSJBRASMNABFAJSTAS + +#include +#include +#include "blossom5/PerfectMatching.h" + +//#define DELAUNAY_TRIANGLE + +struct GPMKDTree; + +class GeomPerfectMatching +{ +public: + typedef int REAL; // if you change it to double, you should also change PerfectMatching::REAL to double! + typedef int PointId; + + // pointNum must be a positive even number. + GeomPerfectMatching(int pointNum, int DIM); + ~GeomPerfectMatching(); + + // Must be called exactly point_num times (before anything else can be called). + // First call returns 0, second returns 1, and so on. + // coord must be an array of size DIM. (This array is read into internal memory.) + PointId AddPoint(REAL* coord); + + + ////////////// SOLVING ////////////// + + // solves perfect matching in the complete graph. Inefficient, just for testing. + REAL SolveComplete(); + + + // options for Solve() + struct GPMOptions + { + GPMOptions() : init_Delaunay(true), init_KNN(0), init_greedy(true), iter_max(0) {} + + // three variables below determine the initial subset of edges. + // Delaunay initialization seems to be more robust than K nearest neighbors + // (but you need to download the "Triangle" package of Shewchuk + // from http://www.cs.cmu.edu/~quake/triangle.html , extract it to the directory 'triangle' + // and define DELAUNAY_TRIANGLE above). + bool init_Delaunay; // add Delaunay triangulation edges. + int init_KNN; // use init_KNN nearest neighbors for each point. + bool init_greedy; // add edges greedily to make sure that a perfect matching exists (see comments before CompleteInitialMatching() in GPMinit.cpp for details) + + int iter_max; // If iter_max <= 0 then adds subsets of edges until an optimal solution is found. + // Otherwise runs at most iter_max iterations, so the solution may be suboptimal. + // (iter_max=1 runs perfect matching just for the initial subset). + }; + struct PerfectMatching::Options options; + struct GPMOptions gpm_options; + + REAL Solve(); + + // You can also specify the initial subset manually + void AddInitialEdge(PointId i, PointId j); + + //////////// READING RESULTS ////////// + // Can be called after Solve() or SolveComplete(). Returns pointer to an array 'matching' + // of size node_num. (matching[i] is the point corresponding to point i). + // User must not modify this array. + PointId GetMatch(PointId p) { return matching[p]; } + + + + REAL Dist(REAL* coord1, REAL* coord2); + REAL Dist(PointId p, PointId q); + + + ////////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////// +private: + +friend struct GPMKDTree; + + struct Edge + { + PointId head[2]; + Edge* next[2]; + }; + struct Node + { + Edge* first[2]; + int is_marked; + }; + + Node* nodes; + Block* edges; + REAL* coords; // array of size DIM*node_num_max + REAL* sums; // array of size node_num_max + PointId* matching; // array of size node_num_max + + int DIM; + int node_num, node_num_max; + int edge_num; + + double graph_update_time; + +// below x denotes REAL, X denotes double, c,c1,c2 are coords (REAL*) +#define GPM_ROUND(X) (REAL)( ( ((REAL)1 / 2) == 0 ) ? ((X)+0.5) : (X) ) +#define GPM_GET_NORM2(X, c) { int d; X = 0; for (d=0; d= 0 +#define GPM_CHECK_NORM(result, c, x)\ + {\ + if (threshold <= 0) result = false;\ + else\ + {\ + double X;\ + GPM_GET_NORM2(X, c);\ + result = (4*X < (double)x*threshold);\ + }\ + } +#define GPM_CHECK_DIST(result, c1, c2, x)\ + {\ + if (threshold <= 0) result = false;\ + else\ + {\ + double X;\ + GPM_GET_DIST2(X, c1, c2);\ + result = (4*X < (double)x*threshold);\ + }\ + } + + double Norm2(REAL* coord) { double norm2; GPM_GET_NORM2(norm2, coord); return norm2; } + REAL Norm(REAL* coord) { REAL norm; GPM_GET_NORM (norm, coord); return norm; } + double Dist2(REAL* coord1, REAL* coord2) { double dist2; GPM_GET_DIST2(dist2, coord1, coord2); return dist2; } + double Dist2(PointId p, PointId q) { return Dist2(coords+DIM*p, coords+DIM*q); } + + void CompleteInitialMatching(); // add edges so that a perfect matching is guaranteed to exist + void InitKNN(int K); + void InitDelaunay(); + + REAL ComputeCost(PointId* matching); +}; + +inline GeomPerfectMatching::REAL GeomPerfectMatching::Dist(REAL* coord1, REAL* coord2) +{ + REAL dist; + GPM_GET_DIST (dist, coord1, coord2); + return dist; +} + +inline GeomPerfectMatching::REAL GeomPerfectMatching::Dist(PointId p, PointId q) +{ + return Dist(coords+DIM*p, coords+DIM*q); +} + +#endif diff --git a/src/blossom5/GRAPH1.TXT b/src/blossom5/GRAPH1.TXT new file mode 100644 index 0000000..13ec532 --- /dev/null +++ b/src/blossom5/GRAPH1.TXT @@ -0,0 +1,10 @@ +6 9 +0 1 3 +0 3 10 +0 4 7 +1 2 -1 +1 4 5 +1 5 4 +2 5 -7 +3 4 0 +4 5 4 diff --git a/src/blossom5/GRAPH2.TXT b/src/blossom5/GRAPH2.TXT new file mode 100644 index 0000000..b3e487f --- /dev/null +++ b/src/blossom5/GRAPH2.TXT @@ -0,0 +1,11 @@ +c example of a graph in DIMACS format +p edge 6 9 +e 1 2 3 +e 1 4 10 +e 1 5 7 +e 2 3 -1 +e 2 5 5 +e 2 6 4 +e 3 6 -7 +e 4 5 0 +e 5 6 4 diff --git a/src/blossom5/LCA.h b/src/blossom5/LCA.h new file mode 100644 index 0000000..3426f7e --- /dev/null +++ b/src/blossom5/LCA.h @@ -0,0 +1,297 @@ +/* + +LCA.h - Imlementation of LCA data structure described in + +O. Berkman, U. Vishkin: Recursive Star-Tree Parallel Data Structure. SIAM J. Comput. 22(2): 221-242 (1993) + +It takes O(n \log n) space (and O(n \log n) time for construction). The memory requirement can be +reduced to O(n) by defining LCA_BLOCKS. The implementation then follows the approach described in + +J. Fischer, V. Heun: Theoretical and Practical Improvements on the RMQ-Problem, with Applications to LCA and LCE. + Proceedings of the 17th Annual Symposium on Combinatorial Pattern Matching + (CPM'06), Lecture Notes in Computer Science 4009, 36-48, Springer-Verlag, 2006. + +(although in-block queries are computed naively in O(K) worst-case time, where K is the size of the block, +rather than as described by Fischer and Heun). + +Written by Vladimir Kolmogorov, vnk@adastral.ucl.ac.uk. + +// example for +// 4 +// / \ +// 2 3 +// / \ +// 0 1 +// (Note: the ordering of nodes is in the tree preorder!!!) + + LCATree* lca = new LCATree(5); + char A0, A1, A2, A3, A4; + + lca->Add(&A0, &A2); + lca->Add(&A1, &A2); + lca->Add(&A2, &A4); + lca->Add(&A3, &A4); + lca->AddRoot(&A4); + + int result = lca->GetLCA(1, 3); // should be 4 + delete lca; + + +*/ + +#ifndef GNAKDLATHJSTHAJSRNAKSJDA +#define GNAKDLATHJSTHAJSRNAKSJDA + +#include +#include +#include +#include + +//#define LCA_BLOCKS + +class LCATree +{ +public: + typedef void* NodeId; // can be any type, e.g. int. (The code checks NodeId's only for equalities.) + typedef int PreorderId; + + LCATree(int node_num_max); + ~LCATree(); + + // construct tree. Nodes must be added in the tree preorder!!! + // First call returns 0, second returns 1, and so on. + PreorderId Add(NodeId i, NodeId i_parent); + PreorderId AddRoot(NodeId i); // completes tree construction + + PreorderId GetLCA(PreorderId i, PreorderId j); + // Let i0=i, j0=j be the input nodes, and let r = LCA(i0,j0). + // This function sets i and j to be the immediate children of r + // such that i is a descendant of i0 and j is a descendant of j0. + // There must hold i0!=r, j0!=r. + void GetPenultimateNodes(PreorderId& i, PreorderId& j); + + +////////////////////////////////////////////////////////////////////////// +private: + int n, n_max, K, k_max; + int** array; + + NodeId* buf0; + int* buf1; + NodeId* parent_current; + int* child_current; + + int* parents; + + int _GetLCA(int i, int j); // same as GetLCA, but assumes that i 0) { K ++; n /= 2; } + if (K < 1) K = 1; +#else + K = 1; + n = 0; +#endif + parents = new int[n_max]; + buf0 = new NodeId[n_max]; + buf1 = new int[n_max]; + parent_current = buf0; + child_current = buf1; +} + +inline LCATree::~LCATree() +{ + int k; + delete [] parents; + if (buf0) delete [] buf0; + if (buf1) delete [] buf1; + if (array) + { + for (k=1; k<=k_max; k++) delete [] array[k]; + delete [] array; + } +} + +inline LCATree::PreorderId LCATree::Add(NodeId i, NodeId i_parent) +{ + assert(n < n_max); + + if (n == 0) + { + *parent_current = i; + *(++ parent_current) = i_parent; + parents[0] = -1; + } + else + { + if (i == *parent_current) + { + int c = *child_current --; + while ( 1 ) + { + int c_next = parents[c]; + parents[c] = n; + if (c_next < 0) break; + c = c_next; + } + parent_current --; + } + if (i_parent == *parent_current) parents[n] = *child_current; + else + { + *(++ parent_current) = i_parent; + parents[n] = -1; + child_current ++; + } + } + *child_current = n; + return n ++; +} + + +inline LCATree::PreorderId LCATree::AddRoot(NodeId i) +{ + assert(n < n_max); + + if (n > 0) + { + if (i != *parent_current || parent_current != buf0+1) + { + printf("Error in LCATree construction: wrong sequence of calls!\n"); + exit(1); + } + int c = *child_current --; + while ( 1 ) + { + int c_next = parents[c]; + parents[c] = n; + if (c_next < 0) break; + c = c_next; + } + child_current ++; + } + parents[n++] = -1; + + delete [] buf0; + buf0 = NULL; + delete [] buf1; + buf1 = NULL; + + // initialize array + int b, k = 1, block_num = (n-1)/K+1; + if (block_num < 3) return n-1; + int d = (block_num-1)/4; + while (d) { k ++; d >>= 1; } + k_max = k; + + array = new int*[k_max+1]; + array[0] = parents; + for (k=1, d=2; k<=k_max; k++, d*=2) + { + array[k] = new int[block_num-d]; + if (k == 1) + { + for (b=0; b j) ? i : j; + } + } + } + + return n-1; +} + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// + +inline int LCATree::GetLCADirect(int i, int j) +{ + while (i < j) i = parents[i]; + return i; +} + + +inline int LCATree::_GetLCA(int i, int j) +{ +#ifdef LCA_BLOCKS + + int bi = i/K, bj = j/K; + if (bi == bj) return GetLCADirect(i, j); + int i_last = (bi+1)*K-1, j_first = bj*K; + i = GetLCADirect(i, i_last); + j = GetLCADirect(j_first, j); + if (i < j) i = j; + // set j = LCA(i_last, j_first) + if (j_first - i_last == 1) j = parents[i_last]; + else + { + int k = 1, d = (bj-bi)/4; + while (d) { k ++; d >>= 1; } + int diff = 1<bj-diff); + j = (array[k][bi] > array[k][bj-diff]) ? array[k][bi] : array[k][bj-diff]; + } + return (i > j) ? i : j; + +#else + + if (j == i) return i; + + int k = 0, d = (j-i)/2; + while (d) { k ++; d >>= 1; } + int diff = 1<j-diff); + return (array[k][i] > array[k][j-diff]) ? array[k][i] : array[k][j-diff]; + +#endif +} + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// + +inline LCATree::PreorderId LCATree::GetLCA(PreorderId i, PreorderId j) +{ + if (i > j) { PreorderId k = i; i = j; j = k; } + return _GetLCA(i, j); +} + +inline void LCATree::GetPenultimateNodes(PreorderId& _i, PreorderId& _j) +{ + int i, j, d, swap; + if (_i < _j) { i = _i; j = _j; swap = 0; } + else { i = _j; j = _i; swap = 1; } + int r = _GetLCA(i, j); + assert(i!=r && j!=r); + while (parents[i] != r) + { + int i0 = parents[i]; + d = (j - i0)/2; + while ( (i=_GetLCA(i0, i0+d)) == r ) d /= 2; + } + while (parents[j] != r) + { + int j0 = parents[j]; + d = (r - j0)/2; + while ( (j=_GetLCA(j0, j0+d)) == r ) d /= 2; + } + if (swap == 0) { _i = i; _j = j; } + else { _j = i; _i = j; } +} + +#endif diff --git a/src/blossom5/LICENSE.TXT b/src/blossom5/LICENSE.TXT new file mode 100644 index 0000000..0331c36 --- /dev/null +++ b/src/blossom5/LICENSE.TXT @@ -0,0 +1,22 @@ +Copyright 2008-2009 Vladimir Kolmogorov (vnk@adastral.ucl.ac.uk) + +This software can be used for research and evaluation purposes only. Commercial use is prohibited. +Public redistribution of the code or its derivatives is prohibited. +If you use this software for research purposes, you should cite the following paper in any resulting publication: + Vladimir Kolmogorov. "Blossom V: A new implementation of a minimum cost perfect matching algorithm." + In Mathematical Programming Computation (MPC), July 2009, 1(1):43-67. + +For commercial use of the software not covered by this agreement, please contact the author. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + diff --git a/src/blossom5/Makefile b/src/blossom5/Makefile new file mode 100644 index 0000000..3eb5cf1 --- /dev/null +++ b/src/blossom5/Makefile @@ -0,0 +1,21 @@ +DIRS := . MinCost GEOM + +SOURCES := $(foreach dir, $(DIRS), $(wildcard $(dir)/*.cpp)) +OBJS := $(patsubst %.cpp, %.o, $(SOURCES)) + +CFLAGS := -O5 -D_NDEBUG +CC := c++ +LIBS := -lrt +INCLUDES := +LIBDIR := + +all: blossom5 + +blossom5: ${OBJS} + ${CC} ${CFLAGS} ${LIBDIR} -o $@ ${OBJS} ${LIBS} + +.cpp.o: + $(CC) $(CFLAGS) ${INCLUDES} $< -c -o $@ + +clean: + rm -f ${OBJS} blossom5 diff --git a/src/blossom5/MinCost/MinCost.cpp b/src/blossom5/MinCost/MinCost.cpp new file mode 100644 index 0000000..4ac5434 --- /dev/null +++ b/src/blossom5/MinCost/MinCost.cpp @@ -0,0 +1,287 @@ +#include +#include +#include +#include "blossom5/MinCost/MinCost.h" + + +template + MinCost::MinCost(int _nodeNum, int _edgeNumMax, void (*err_function)(const char *)) + : nodeNum(_nodeNum), + edgeNum(0), + edgeNumMax(_edgeNumMax), + counter(0), + cost(0), + error_function(err_function) +{ + nodes = (Node*) malloc(nodeNum*sizeof(Node)); + arcs = (Arc*) malloc(2*edgeNumMax*sizeof(Arc)); + if (!nodes || !arcs) { if (error_function) (*error_function)("Not enough memory!"); exit(1); } + + memset(nodes, 0, nodeNum*sizeof(Node)); + memset(arcs, 0, 2*edgeNumMax*sizeof(Arc)); + firstActive = &nodes[nodeNum]; +#ifdef MINCOST_DEBUG + for (int i=0; i + MinCost::~MinCost() +{ + free(nodes); + free(arcs); +} + +template + void MinCost::Init() +{ + Node* i; + Arc* a; + + for (a=arcs; ar_cap > 0 && a->GetRCost() < 0) PushFlow(a, a->r_cap); + } + + Node** lastActivePtr = &firstActive; + for (i=nodes; iexcess > 0) + { + *lastActivePtr = i; + lastActivePtr = &i->next; + } + else i->next = NULL; + } + *lastActivePtr = &nodes[nodeNum]; +} + + +template + FlowType MinCost::Augment(Node* start, Node* end) +{ + FlowType delta = (start->excess < -end->excess) ? start->excess : -end->excess; + Arc* a; + + for (a=end->parent; a; a=a->sister->head->parent) + { + if (delta > a->r_cap) delta = a->r_cap; + } + assert(delta > 0); + + end->excess += delta; + for (a=end->parent; a; a=a->head->parent) + { + DecreaseRCap(a, delta); + a = a->sister; + IncreaseRCap(a, delta); + } + start->excess -= delta; + + return delta; +} + +template + void MinCost::Dijkstra(Node* start) +{ + assert(start->excess > 0); + + Node* i; + Node* j; + Arc* a; + CostType d; + Node* permanentNodes; + + int FLAG0 = ++ counter; // permanently labeled nodes + int FLAG1 = ++ counter; // temporarily labeled nodes + + start->parent = NULL; + start->flag = FLAG1; + queue.Reset(); + queue.Add(start, 0); + + permanentNodes = NULL; + + while ( (i=queue.RemoveMin(d)) ) + { + if (i->excess < 0) + { + FlowType delta = Augment(start, i); + cost += delta*(d - i->pi + start->pi); + for (i=permanentNodes; i; i=i->next_permanent) i->pi += d; + break; + } + + i->pi -= d; + i->flag = FLAG0; + i->next_permanent = permanentNodes; + permanentNodes = i; + + for (a=i->firstNonsaturated; a; a=a->next) + { + j = a->head; + if (j->flag == FLAG0) continue; + d = a->GetRCost(); + if (j->flag == FLAG1) + { + if (d >= queue.GetKey(j)) continue; + queue.DecreaseKey(j, d); + } + else + { + queue.Add(j, d); + j->flag = FLAG1; + } + j->parent = a; + } + + } +} + + +template + CostType MinCost::Solve() +{ + Node* i; + //Init(); + while ( 1 ) + { + i = firstActive; + if (i == &nodes[nodeNum]) break; + firstActive = i->next; + i->next = NULL; + if (i->excess > 0) + { + Dijkstra(i); + if (i->excess > 0 && !i->next) + { + i->next = firstActive; + firstActive = i; + } + } + } +#ifdef MINCOST_DEBUG + TestOptimality(); + TestCosts(); +#endif + + return cost; +} + + +template + void MinCost::TestOptimality() +{ + Node* i; + Arc* a; + + for (i=nodes; iexcess != 0) + { + assert(0); + } + for (a=i->firstSaturated; a; a=a->next) + { + if (a->r_cap != 0) + { + assert(0); + } + } + for (a=i->firstNonsaturated; a; a=a->next) + { + CostType c = a->GetRCost(); + if (a->r_cap <= 0 || a->GetRCost() < -1e-5) + { + assert(0); + } + } + } +} + +#ifdef MINCOST_DEBUG + +template + void MinCost::TestCosts() +{ + Arc* a; + + CostType _cost = 0; + + for (a=arcs; ar_cap + a->sister->r_cap == a->cap_orig + a->sister->cap_orig); + _cost += a->cost*(a->cap_orig - a->r_cap); + } + + CostType delta = cost - _cost; + if (delta < 0) delta = -delta; + if (delta >= 1e-5) + { + assert(0); + } +} + +#endif + + + + +/////////////////////////////////////////////////////////////////////////////////////// + +#define FLOW_INFTY ((int)0x00fffffff) + +template + DualMinCost::DualMinCost(int _nodeNum, int _edgeNumMax) + : MinCost(_nodeNum+1, _edgeNumMax+2*_nodeNum) +{ + source = _nodeNum; +} + +template + DualMinCost::~DualMinCost() +{ +} + +template + void DualMinCost::AddUnaryTerm(NodeId i, int objective_coef) +{ + MinCost::AddNodeExcess(i, objective_coef); + MinCost::AddNodeExcess(source, -objective_coef); +} + +template + void DualMinCost::SetLowerBound(NodeId i, CostType cmin) +{ + AddEdge(i, source, FLOW_INFTY, 0, -cmin); +} + +template + void DualMinCost::SetUpperBound(NodeId i, CostType cmax) +{ + AddEdge(source, i, FLOW_INFTY, 0, cmax); +} + +template + void DualMinCost::AddConstraint(NodeId i, NodeId j, CostType cmax) +{ + AddEdge(i, j, FLOW_INFTY, 0, cmax); +} + +template + void DualMinCost::Solve() +{ + MinCost::Solve(); +} + +template + CostType DualMinCost::GetSolution(NodeId i) +{ + return MinCost::nodes[source].pi - MinCost::nodes[i].pi; +} + + + +#include "blossom5/MinCost/instances.inc" + + diff --git a/src/blossom5/MinCost/MinCost.h b/src/blossom5/MinCost/MinCost.h new file mode 100644 index 0000000..fa3bc91 --- /dev/null +++ b/src/blossom5/MinCost/MinCost.h @@ -0,0 +1,504 @@ +/* + MinCost.h - successive shortest path algorithm of Ford and Fulkerson for solving a minimum cost flow problem + + Copyright 2008 Vladimir Kolmogorov (vnk@adastral.ucl.ac.uk) + + This software can be used for research purposes only. Commercial use is prohibited. + Public redistribution of the code or its derivatives is prohibited. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#ifndef __MINCOST_H__ +#define __MINCOST_H__ + +#include +#include + +// if GRAPH_ASSERT is defined then all calls to graph construction functions are assert'ed for correctness +// (e.g. that node_id's are valid id's and edge capacities are non-negative). +//#define GRAPH_ASSERT + +//#define MINCOST_DEBUG + + + +template class MinCost +{ +public: + typedef int NodeId; + typedef int EdgeId; + + MinCost(int NodeNum, int edgeNumMax, void (*err_function)(const char *) = NULL); + + // Destructor + ~MinCost(); + + void AddNodeExcess(NodeId i, FlowType excess); + + // first call returns 0, second 1, and so on. + // cap, rev_cap must be non-negative. + // cost can be negative. + EdgeId AddEdge(NodeId i, NodeId j, FlowType cap, FlowType rev_cap, CostType cost); + + CostType Solve(); + + /////////////////////////////////////////////////// + + FlowType GetRCap(EdgeId e); + void SetRCap(EdgeId e, FlowType new_rcap); + FlowType GetReverseRCap(EdgeId e); + void SetReverseRCap(EdgeId e, FlowType new_rcap); + void PushFlow(EdgeId e, FlowType delta); + void UpdateCost(EdgeId e, FlowType cap_orig, CostType delta); + + CostType GetDual(NodeId i) { return nodes[i].pi; } + +///////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// + +protected: + // internal variables and functions + + struct Node; + struct Arc; + + struct Node + { + Arc *firstNonsaturated; + Arc *firstSaturated; + + Arc *parent; + Node *next; // list of nodes with positive excesses + + FlowType excess; + CostType pi; + int flag; + union + { + int heap_ptr; + Node* next_permanent; + }; +#ifdef MINCOST_DEBUG + int id; +#endif + }; + + struct Arc + { + Node *head; + Arc *prev; + Arc *next; + Arc *sister; // reverse arc + + FlowType r_cap; // residual capacity +#ifdef MINCOST_DEBUG + FlowType cap_orig; +#endif + CostType cost; + CostType GetRCost() { return cost + head->pi - sister->head->pi; } + }; + + int nodeNum, edgeNum, edgeNumMax; + Node *nodes; + Arc *arcs; + Node* firstActive; + int counter; + CostType cost; + + + void (*error_function)(const char *); // this function is called if a error occurs, + // with a corresponding error message + // (or exit(1) is called if it's NULL) + + ///////////////////////////////////////////////////////////////////////// + + struct PriorityQueue + { + PriorityQueue(); + ~PriorityQueue(); + void Reset(); + CostType GetKey(Node* i); + void Add(Node* i, CostType key); + void DecreaseKey(Node* i, CostType key); + Node* RemoveMin(CostType& key); + + private: + struct Item + { + Node* i; + CostType key; + }* array; + int N, arraySize; + void Swap(int k1, int k2); + }; + + PriorityQueue queue; + + ///////////////////////////////////////////////////////////////////////// + + void SetRCap(Arc* a, FlowType new_rcap); + void PushFlow(Arc* a, FlowType delta); + + void Init(); + void DecreaseRCap(Arc* a, FlowType delta); + void IncreaseRCap(Arc* a, FlowType delta); + FlowType Augment(Node* start, Node* end); + void Dijkstra(Node* start); + + void TestOptimality(); +#ifdef MINCOST_DEBUG + void TestCosts(); +#endif +}; + + +template class DualMinCost : private MinCost +{ +public: + typedef int NodeId; + DualMinCost(int node_num, int constraint_num_max); + ~DualMinCost(); + + void AddUnaryTerm(NodeId i, int objective_coef); + void SetLowerBound(NodeId, CostType cmin); + void SetUpperBound(NodeId, CostType cmax); + void AddConstraint(NodeId i, NodeId j, CostType cmax); // xj - xi <= cmax + + void Solve(); + CostType GetSolution(NodeId i); + +private: + NodeId source; +}; + + + + + + + + + +/////////////////////////////////////// +// Implementation - inline functions // +/////////////////////////////////////// + + + +template + inline void MinCost::AddNodeExcess(NodeId _i, FlowType excess) +{ + assert(_i>=0 && _i 0 && !nodes[_i].next) + { + nodes[_i].next = firstActive; + firstActive = &nodes[_i]; + } +} + +template + inline typename MinCost::EdgeId MinCost::AddEdge(NodeId _i, NodeId _j, FlowType cap, FlowType rev_cap, CostType cost) +{ + assert(_i>=0 && _i=0 && _j= 0); + assert(rev_cap >= 0); + + Arc *a = &arcs[2*edgeNum]; + Arc *a_rev = a+1; + edgeNum ++; + + Node* i = nodes + _i; + Node* j = nodes + _j; + + a -> sister = a_rev; + a_rev -> sister = a; + if (cap > 0) + { + if (i->firstNonsaturated) i->firstNonsaturated->prev = a; + a -> next = i -> firstNonsaturated; + i -> firstNonsaturated = a; + } + else + { + if (i->firstSaturated) i->firstSaturated->prev = a; + a -> next = i -> firstSaturated; + i -> firstSaturated = a; + } + a->prev = NULL; + if (rev_cap > 0) + { + if (j->firstNonsaturated) j->firstNonsaturated->prev = a_rev; + a_rev -> next = j -> firstNonsaturated; + j -> firstNonsaturated = a_rev; + } + else + { + if (j->firstSaturated) j->firstSaturated->prev = a_rev; + a_rev -> next = j -> firstSaturated; + j -> firstSaturated = a_rev; + } + a_rev->prev = NULL; + + a -> head = j; + a_rev -> head = i; + a -> r_cap = cap; + a_rev -> r_cap = rev_cap; + a -> cost = cost; + a_rev -> cost = -cost; +#ifdef MINCOST_DEBUG + a->cap_orig = cap; + a_rev->cap_orig = rev_cap; +#endif + + if (a->r_cap > 0 && a->GetRCost() < 0) PushFlow(a, a->r_cap); + if (a_rev->r_cap > 0 && a_rev->GetRCost() < 0) PushFlow(a_rev, a_rev->r_cap); + + return edgeNum-1; +} + +/////////////////////////////////////// +/////////////////////////////////////// +/////////////////////////////////////// + +template + inline void MinCost::DecreaseRCap(Arc* a, FlowType delta) +{ + a->r_cap -= delta; + if (a->r_cap == 0) + { + Node* i = a->sister->head; + if (a->next) a->next->prev = a->prev; + if (a->prev) a->prev->next = a->next; + else i->firstNonsaturated = a->next; + a->next = i->firstSaturated; + if (a->next) a->next->prev = a; + a->prev = NULL; + i->firstSaturated = a; + } +} + +template + inline void MinCost::IncreaseRCap(Arc* a, FlowType delta) +{ + if (a->r_cap == 0) + { + Node* i = a->sister->head; + if (a->next) a->next->prev = a->prev; + if (a->prev) a->prev->next = a->next; + else i->firstSaturated = a->next; + a->next = i->firstNonsaturated; + if (a->next) a->next->prev = a; + a->prev = NULL; + i->firstNonsaturated = a; + } + a->r_cap += delta; +} + +template + inline FlowType MinCost::GetRCap(EdgeId e) +{ + Arc* a = &arcs[2*e]; + return a->r_cap; +} + +template + inline void MinCost::SetRCap(Arc* a, FlowType new_rcap) +{ + assert(new_rcap >= 0); +#ifdef MINCOST_DEBUG + a->cap_orig += new_rcap - a->r_cap; +#endif + if (a->r_cap == 0) + { + Node* i = a->sister->head; + if (a->next) a->next->prev = a->prev; + if (a->prev) a->prev->next = a->next; + else i->firstSaturated = a->next; + a->next = i->firstNonsaturated; + if (a->next) a->next->prev = a; + a->prev = NULL; + i->firstNonsaturated = a; + } + a->r_cap = new_rcap; + if (a->r_cap == 0) + { + Node* i = a->sister->head; + if (a->next) a->next->prev = a->prev; + if (a->prev) a->prev->next = a->next; + else i->firstNonsaturated = a->next; + a->next = i->firstSaturated; + if (a->next) a->next->prev = a; + a->prev = NULL; + i->firstSaturated = a; + } +} + +template + inline void MinCost::SetRCap(EdgeId e, FlowType new_rcap) +{ + SetRCap(&arcs[2*e], new_rcap); +} + +template + inline FlowType MinCost::GetReverseRCap(EdgeId e) +{ + Arc* a = &arcs[2*e+1]; + return a->r_cap; +} + +template + inline void MinCost::SetReverseRCap(EdgeId e, FlowType new_rcap) +{ + SetRCap(&arcs[2*e+1], new_rcap); +} + +template + inline void MinCost::PushFlow(Arc* a, FlowType delta) +{ + if (delta < 0) { a = a->sister; delta = -delta; } + DecreaseRCap(a, delta); + IncreaseRCap(a->sister, delta); + a->head->excess += delta; + a->sister->head->excess -= delta; + cost += delta*a->cost; + if (a->head->excess > 0 && !a->head->next) + { + a->head->next = firstActive; + firstActive = a->head; + } +} + +template + inline void MinCost::PushFlow(EdgeId e, FlowType delta) +{ + PushFlow(&arcs[2*e], delta); +} + +template + inline void MinCost::UpdateCost(EdgeId e, FlowType cap_orig, CostType delta) +{ + Arc* a = &arcs[2*e]; + cost += delta*(cap_orig-a->r_cap); + a->cost += delta; + a->sister->cost = -a->cost; + + if (a->GetRCost() > 0) a = a->sister; + if (a->r_cap > 0 && a->GetRCost() < 0) PushFlow(a, a->r_cap); +} + +/////////////////////////////////////// +/////////////////////////////////////// +/////////////////////////////////////// + +template + inline MinCost::PriorityQueue::PriorityQueue() +{ + N = 0; + arraySize = 16; + array = (Item*) malloc(arraySize*sizeof(Item)); +} + +template + inline MinCost::PriorityQueue::~PriorityQueue() +{ + free(array); +} + +template + inline void MinCost::PriorityQueue::Reset() +{ + N = 0; +} + +template + inline CostType MinCost::PriorityQueue::GetKey(Node* i) +{ + return array[i->heap_ptr].key; +} + +template + inline void MinCost::PriorityQueue::Swap(int k1, int k2) +{ + Item* a = array+k1; + Item* b = array+k2; + a->i->heap_ptr = k2; + b->i->heap_ptr = k1; + Node* i = a->i; a->i = b->i; b->i = i; + CostType key = a->key; a->key = b->key; b->key = key; +} + +template + inline void MinCost::PriorityQueue::Add(Node* i, CostType key) +{ + if (N == arraySize) + { + arraySize *= 2; + array = (Item*) realloc(array, arraySize*sizeof(Item)); + } + int k = i->heap_ptr = N ++; + array[k].i = i; + array[k].key = key; + while (k > 0) + { + int k2 = (k-1)/2; + if (array[k2].key <= array[k].key) break; + Swap(k, k2); + k = k2; + } +} + +template + inline void MinCost::PriorityQueue::DecreaseKey(Node* i, CostType key) +{ + int k = i->heap_ptr; + array[k].key = key; + while (k > 0) + { + int k2 = (k-1)/2; + if (array[k2].key <= array[k].key) break; + Swap(k, k2); + k = k2; + } +} + +template + inline typename MinCost::Node* MinCost::PriorityQueue::RemoveMin(CostType& key) +{ + if (N == 0) return NULL; + + Swap(0, N-1); + N --; + + int k = 0; + while ( 1 ) + { + int k1 = 2*k + 1, k2 = k1 + 1; + if (k1 >= N) break; + int k_min = (k2 >= N || array[k1].key <= array[k2].key) ? k1 : k2; + if (array[k].key <= array[k_min].key) break; + Swap(k, k_min); + k = k_min; + } + + key = array[N].key; + return array[N].i; +} + + +#endif diff --git a/src/blossom5/MinCost/instances.inc b/src/blossom5/MinCost/instances.inc new file mode 100644 index 0000000..0bebe57 --- /dev/null +++ b/src/blossom5/MinCost/instances.inc @@ -0,0 +1,12 @@ +#include "blossom5/MinCost/MinCost.h" + +#ifdef _MSC_VER +#pragma warning(disable: 4661) +#endif + + +template class MinCost; +template class MinCost; + +template class DualMinCost; +template class DualMinCost; diff --git a/src/blossom5/PMduals.cpp b/src/blossom5/PMduals.cpp new file mode 100644 index 0000000..2ee5a9f --- /dev/null +++ b/src/blossom5/PMduals.cpp @@ -0,0 +1,441 @@ +#include +#include +#include +#include "blossom5/PMimplementation.h" +#include "blossom5/MinCost/MinCost.h" + + +void PerfectMatching::ComputeEpsGlobal() +{ + Node* r; + PriorityQueue::Item* q; + Tree* t; + Tree* t2; + TreeEdge* e; + int i, j, k, N = 0, E = 0; + + for (r=nodes[node_num].tree_sibling_next; r; r=r->tree_sibling_next) + { + t = r->tree; + t->id = N; + N += 2; + for (k=0; k<2; k++) + for (e=t->first[k]; e; e=e->next[k]) E += 6; + } + DualMinCost* m = new DualMinCost(N, E); + for (r=nodes[node_num].tree_sibling_next; r; r=r->tree_sibling_next) + { + t = r->tree; + i = t->id; + m->AddUnaryTerm(i, -1); + m->SetLowerBound(i, 0); + m->AddUnaryTerm(i+1, 1); + m->SetUpperBound(i+1, 0); + + if (t->eps_delta < PM_INFTY) + { + m->SetUpperBound(i, t->eps_delta); + m->SetLowerBound(i+1, -t->eps_delta); + } + for (e=t->first[0]; e; e=e->next[0]) + { + t2 = e->head[0]; + if (t2 == NULL) continue; + j = e->head[0]->id; + if ((q=e->pq01[0].GetMin())) + { + m->AddConstraint(j, i, q->slack - t->eps + t2->eps); + m->AddConstraint(i+1, j+1, q->slack - t->eps + t2->eps); + } + if ((q=e->pq01[1].GetMin())) + { + m->AddConstraint(i, j, q->slack - t2->eps + t->eps); + m->AddConstraint(j+1, i+1, q->slack - t2->eps + t->eps); + } + if ((q=e->pq00.GetMin())) + { + m->AddConstraint(i+1, j, q->slack - t->eps - t2->eps); + m->AddConstraint(j+1, i, q->slack - t->eps - t2->eps); + } + } + } + m->Solve(); + for (r=nodes[node_num].tree_sibling_next; r; r=r->tree_sibling_next) + { + t = r->tree; + i = t->id; + t->eps_delta = (m->GetSolution(i) - m->GetSolution(i+1))/2; + } + delete m; +} + +void PerfectMatching::ComputeEpsSingle() +{ + Node* r; + PriorityQueue::Item* q; + Tree* t; + Tree* t2; + TreeEdge* e; + REAL eps = PM_INFTY; + + for (r=nodes[node_num].tree_sibling_next; r; r=r->tree_sibling_next) + { + t = r->tree; + if (eps > t->eps_delta) eps = t->eps_delta; + for (e=t->first[0]; e; e=e->next[0]) + { + t2 = e->head[0]; + if ((q=e->pq00.GetMin()) && 2*eps > q->slack-t->eps-t2->eps) + { + eps = (q->slack-t->eps-t2->eps)/2; + } + } + } + for (r=nodes[node_num].tree_sibling_next; r; r=r->tree_sibling_next) + { + r->tree->eps_delta = eps; + } +} + + +void PerfectMatching::ComputeEpsCC() +{ + Node* r; + PriorityQueue::Item* q; + Tree* t0; + Tree* t; + Tree* t2; + Tree* t_next; + TreeEdge* e; + REAL eps, eps2; + Tree* queue_last; + int dir; + Tree* FIXED_TREE = trees-1; + int component_num = 0; + TreeEdge** e_ptr; + + for (r=nodes[node_num].tree_sibling_next; r; r=r->tree_sibling_next) + { + t0 = r->tree; + t0->next = NULL; + } + for (r=nodes[node_num].tree_sibling_next; r; r=r->tree_sibling_next) + { + t0 = r->tree; + if (t0->next) continue; + eps = t0->eps_delta; + + t0->next = queue_last = t = t0; + while ( 1 ) + { + for (dir=0; dir<2; dir++) + for (e_ptr=&t->first[dir], e=*e_ptr; e; e=*e_ptr) + { + t2 = e->head[dir]; + if (t2 == NULL) { *e_ptr = e->next[dir]; tree_edges->Delete(e); continue; } + e_ptr = &e->next[dir]; + + REAL eps00 = ((q=e->pq00.GetMin())) ? (q->slack - t->eps - t2->eps) : PM_INFTY; + if (t2->next && t2->next != FIXED_TREE) + { + if (2*eps > eps00) eps = eps00/2; + continue; + } + + REAL eps01[2]; + eps01[dir] = ((q=e->pq01[dir].GetMin())) ? (q->slack - t->eps + t2->eps) : PM_INFTY; + eps01[1-dir] = ((q=e->pq01[1-dir].GetMin())) ? (q->slack - t2->eps + t->eps) : PM_INFTY; + + if (t2->next == FIXED_TREE) eps2 = t2->eps_delta; + else if (eps01[0] > 0 && eps01[1] > 0) eps2 = 0; + else + { + queue_last->next = t2; + queue_last = t2; + t2->next = t2; + if (eps > eps00) eps = eps00; + if (eps > t2->eps_delta) eps = t2->eps_delta; + continue; + } + if (eps > eps00 - eps2) eps = eps00 - eps2; + if (eps > eps2 + eps01[dir]) eps = eps2 + eps01[dir]; + } + + if (t->next == t) break; + t = t->next; + } + for (t=t0; ; t=t_next) + { + t->eps_delta = eps; + t_next = t->next; + t->next = FIXED_TREE; + if (t_next == t) break; + } + component_num ++; + } + //printf("%d CCs ", component_num); +} + + +void PerfectMatching::ComputeEpsSCC() +{ + PriorityQueue::Item* q; + Node* r; + Tree* t0; + Tree* t; + Tree* t2; + TreeEdge* e; + TreeEdge** e_ptr; + REAL eps; + int c, dir; + + for (r=nodes[node_num].tree_sibling_next; r; r=r->tree_sibling_next) + { + t0 = r->tree; + t0->dfs_parent = NULL; + + for (dir=0; dir<2; dir++) + for (e_ptr=&t0->first[dir], e=*e_ptr; e; e=*e_ptr) + { + t2 = e->head[dir]; + if (t2 == NULL) { *e_ptr = e->next[dir]; tree_edges->Delete(e); continue; } + e_ptr = &e->next[dir]; + } + } + Tree* stack = NULL; + + // first DFS + for (r=nodes[node_num].tree_sibling_next; r; r=r->tree_sibling_next) + { + t0 = r->tree; + if (t0->dfs_parent) continue; + t = t0; + e = (t->first[0]) ? t->first[0] : t->first[1]; + t->dfs_parent = (TreeEdge*)trees; + while ( 1 ) + { + if (e == NULL) + { + t->next = stack; + stack = t; + + if (t == t0) break; + + e = t->dfs_parent; + if (t == e->head[0]) { t = e->head[1]; e = (e->next[0]) ? e->next[0] : t->first[1]; } + else { t = e->head[0]; e = e->next[1]; } + continue; + } + + if (e->head[1] == t) + { + if (e->head[0]->dfs_parent || !(q=e->pq01[0].GetMin()) || q->slack - t->eps + e->head[0]->eps > 0) { e = (e->next[0]) ? e->next[0] : t->first[1]; continue; } + t = e->head[0]; + } + else + { + if (e->head[1]->dfs_parent || !(q=e->pq01[1].GetMin()) || q->slack - t->eps + e->head[1]->eps > 0) { e = e->next[1]; continue; } + t = e->head[1]; + } + t->dfs_parent = e; + e = (t->first[0]) ? t->first[0] : t->first[1]; + } + } + + for (r=nodes[node_num].tree_sibling_next; r; r=r->tree_sibling_next) r->tree->dfs_parent = NULL; + + int component_num = 0; + while (stack) + { + t0 = stack; + stack = t0->next; + if (t0->dfs_parent) continue; + t = t0; + e = (t->first[0]) ? t->first[0] : t->first[1]; + t->dfs_parent = (TreeEdge*)trees; + while ( 1 ) + { + if (e == NULL) + { + e = t->dfs_parent; + t->dfs_parent = (TreeEdge*)((char*)trees + component_num); + if (t == t0) break; + if (t == e->head[0]) { t = e->head[1]; e = (e->next[0]) ? e->next[0] : t->first[1]; } + else { t = e->head[0]; e = e->next[1]; } + continue; + } + + if (e->head[1] == t) + { + if (e->head[0]->dfs_parent || !(q=e->pq01[1].GetMin()) || q->slack - e->head[0]->eps + t->eps > 0) { e = (e->next[0]) ? e->next[0] : t->first[1]; continue; } + t = e->head[0]; + } + else + { + if (e->head[1]->dfs_parent || !(q=e->pq01[0].GetMin()) || q->slack - e->head[1]->eps + t->eps > 0) { e = e->next[1]; continue; } + t = e->head[1]; + } + t->dfs_parent = e; + e = (t->first[0]) ? t->first[0] : t->first[1]; + } + component_num ++; + } + + Tree** array = new Tree*[component_num]; + memset(array, 0, component_num*sizeof(Tree*)); + + for (r=nodes[node_num].tree_sibling_next; r; r=r->tree_sibling_next) + { + t = r->tree; + t->id = (int)((char*)t->dfs_parent - (char*)trees); + t->next = array[t->id]; + array[t->id] = t; + } + + for (c=component_num-1; c>=0; c--) + { + eps = PM_INFTY; + for (t=array[c]; t; t=t->next) + { + if (eps > t->eps_delta) eps = t->eps_delta; + FOR_ALL_TREE_EDGES(t, e, dir) + { + t2 = e->head[dir]; + REAL eps00 = (q=e->pq00.GetMin()) ? (q->slack-t->eps-t2->eps) : PM_INFTY; + REAL eps01[2]; + eps01[dir] = ((q=e->pq01[dir].GetMin())) ? (q->slack - t->eps + t2->eps) : PM_INFTY; + eps01[1-dir] = ((q=e->pq01[1-dir].GetMin())) ? (q->slack - t2->eps + t->eps) : PM_INFTY; + if (t2->id < c) + { + if (eps > eps01[dir]) eps = eps01[dir]; + if (eps > eps00) eps = eps00; + } + else if (t2->id == c) + { + if (2*eps > eps00) eps = eps00 / 2; + } + else + { + if (eps > eps01[dir] + t2->eps_delta) eps = eps01[dir] + t2->eps_delta; + if (eps > eps00 - t2->eps_delta) eps = eps00 - t2->eps_delta; + } + } + } + for (t=array[c]; t; t=t->next) t->eps_delta = eps; + } + + delete [] array; + //printf("%d SCCs ", component_num); +} + +void PerfectMatching::CommitEps() +{ + printf("CommitEps()\n"); + Node* i; + Node* j; + Node* r; + int dir; + Edge* a; + EdgeIterator I; + Tree* t; + TreeEdge* e; + TreeEdge** e_ptr; + REAL eps, eps2; + PriorityQueue::Item* q; + + for (r=nodes[node_num].tree_sibling_next; r; r=r->tree_sibling_next) + { + t = r->tree; + eps = t->eps; + + i = r; + while ( 1 ) + { + i->y += eps; + if (!i->is_tree_root) + { + Node* i0 = i; + i = ARC_HEAD(i0->match); + if (i->is_blossom) ARC_TO_EDGE_PTR(i0->match)->slack -= eps; + else i->y -= eps; + FOR_ALL_EDGES(i, a, dir, I) + { + GET_OUTER_HEAD(a, dir, j); + + a->slack += eps; + if (j->flag == 0) a->slack -= j->tree->eps; + } + i = i0; + } + + MOVE_NODE_IN_TREE(i); + } + + t->pq0.Update(-eps); + + PriorityQueue pq00 = t->pq00; + t->pq00.Reset(); + for (q=pq00.GetAndResetFirst(); q; q=pq00.GetAndResetNext()) + { + a = (Edge*)q; + if (ProcessEdge00(a)) t->pq00.Add(a); + } + + for (e_ptr=&t->first[0], e=*e_ptr; e; e=*e_ptr) + { + if (e->head[0] == NULL) { *e_ptr = e->next[0]; tree_edges->Delete(e); continue; } + e_ptr = &e->next[0]; + + eps2 = e->head[0]->eps; + e->pq00.Update( - eps - eps2 ); + } + } + + for (r=nodes[node_num].tree_sibling_next; r; r=r->tree_sibling_next) r->tree->eps = 0; +} + +bool PerfectMatching::UpdateDuals() +{ + Node* r; + + double start_time = get_time(); + + //////////////////////////////////////////////////////////////////////////////////// + for (r=nodes[node_num].tree_sibling_next; r; r=r->tree_sibling_next) + { + Tree* t = r->tree; + PriorityQueue::Item* q; + REAL eps = PM_INFTY; + if ((q=t->pq0.GetMin())) eps = q->slack; + if ((q=t->pq_blossoms.GetMin()) && eps > q->slack) eps = q->slack; + while ((q=t->pq00.GetMin())) + { + if (ProcessEdge00((Edge*)q, false)) break; + t->pq00.Remove(q, pq_buf); + } + if (q && 2*eps > q->slack) eps = q->slack/2; + t->eps_delta = eps - t->eps; + } + + if (tree_num >= options.dual_LP_threshold*node_num) + { + if (options.dual_greedy_update_option == 0) ComputeEpsCC(); + else if (options.dual_greedy_update_option == 1) ComputeEpsSCC(); + else ComputeEpsSingle(); + } + else ComputeEpsGlobal(); + + REAL delta = 0; + for (r=nodes[node_num].tree_sibling_next; r; r=r->tree_sibling_next) + { + if (r->tree->eps_delta > 0) + { + delta += r->tree->eps_delta; + r->tree->eps += r->tree->eps_delta; + } + } + + stat.dual_time += get_time() - start_time; + + return (delta > PM_THRESHOLD); +} diff --git a/src/blossom5/PMexpand.cpp b/src/blossom5/PMexpand.cpp new file mode 100644 index 0000000..2b22c27 --- /dev/null +++ b/src/blossom5/PMexpand.cpp @@ -0,0 +1,303 @@ +#include +#include +#include +#include "blossom5/PMimplementation.h" + + + + +inline void PerfectMatching::ProcessSelfloop(Node* b, Edge* a) +{ + int dir; + Node* j; + Node* prev[2]; + for (dir=0; dir<2; dir++) + { + j = a->head[dir]; + GET_PENULTIMATE_BLOSSOM(j); + prev[dir] = j; + } + if (prev[0] != prev[1]) + { + ADD_EDGE(prev[0], a, 1); + ADD_EDGE(prev[1], a, 0); + a->slack -= 2*prev[0]->blossom_eps; + } + else + { + a->next[0] = prev[0]->blossom_selfloops; + prev[0]->blossom_selfloops = a; + } + +} + + + +void PerfectMatching::Expand(Node* b) +{ + assert(b->is_blossom); + assert(b->is_outer); + assert(b->flag == 1); + + double start_time = get_time(); + + Node* i; + Node* j; + Node* k; + Edge* a; + EdgeIterator I; + int dir; + ExpandTmpItem* tmp_item; + Tree* t = b->tree; + REAL eps = t->eps; + Edge* a_augment = NULL; + + GET_TREE_PARENT(b, i); + a = ARC_TO_EDGE_PTR(b->tree_parent); + dir = ARC_TO_EDGE_DIR(b->tree_parent); + + j = a->head0[1-dir]; + GET_PENULTIMATE_BLOSSOM(j); + MOVE_EDGE(b, j, a, dir); + + a = ARC_TO_EDGE_PTR(b->match); + dir = ARC_TO_EDGE_DIR(b->match); + k = a->head0[1-dir]; + GET_PENULTIMATE_BLOSSOM(k); + MOVE_EDGE(b, k, a, dir); + + i = ARC_HEAD(k->blossom_sibling); + while ( 1 ) + { + tmp_item = expand_tmp_list->New(); + tmp_item->i = i; tmp_item->blossom_parent = i->blossom_parent; tmp_item->blossom_grandparent = i->blossom_grandparent; + i->flag = 2; + + // blossom_selfloops + i->is_outer = 1; + while ((a=i->blossom_selfloops)) + { + i->blossom_selfloops = a->next[0]; + ProcessSelfloop(i, a); + } + i->is_outer = 0; + + if (i == k) break; + i->match = i->blossom_sibling; + j = ARC_HEAD(i->match); + tmp_item = expand_tmp_list->New(); + tmp_item->i = j; tmp_item->blossom_parent = j->blossom_parent; tmp_item->blossom_grandparent = j->blossom_grandparent; + j->flag = 2; + + // blossom_selfloops + j->is_outer = 1; + while ((a=j->blossom_selfloops)) + { + j->blossom_selfloops = a->next[0]; + ProcessSelfloop(j, a); + } + j->is_outer = 0; + + j->match = ARC_REV(i->match); + i = ARC_HEAD(j->blossom_sibling); + } + k->match = b->match; + i = ARC_TAIL(b->tree_parent); + Arc* aa = i->blossom_sibling; + i->flag = 1; i->tree = b->tree; i->y += b->tree->eps; + i->tree_parent = b->tree_parent; + if (i != k) + { + Node** i_ptr; + if (i->match == aa) + { + i = ARC_HEAD(i->match); + i_ptr = &j; + while ( 1 ) + { + aa = i->blossom_sibling; + i->flag = 0; i->tree = b->tree; i->y -= t->eps; + *i_ptr = i; + i_ptr = &i->first_tree_child; + i->tree_sibling_prev = i; + i->tree_sibling_next = NULL; + i = ARC_HEAD(aa); + i->flag = 1; i->tree = b->tree; i->y += t->eps; + i->tree_parent = ARC_REV(aa); + if (i == k) break; + i = ARC_HEAD(i->match); + } + *i_ptr = ARC_HEAD(k->match); + } + else + { + i = k; + j = ARC_HEAD(k->match); + do + { + i->tree_parent = i->blossom_sibling; + i->flag = 1; i->tree = b->tree; i->y += b->tree->eps; + i = ARC_HEAD(i->tree_parent); + i->flag = 0; i->tree = b->tree; i->y -= b->tree->eps; + i->first_tree_child = j; + j = i; + i->tree_sibling_prev = i; + i->tree_sibling_next = NULL; + i = ARC_HEAD(i->match); + } while ( i->flag != 1 ); + } + i = ARC_HEAD(k->match); + + j->tree_sibling_prev = i->tree_sibling_prev; + j->tree_sibling_next = i->tree_sibling_next; + if (i->tree_sibling_prev->tree_sibling_next) i->tree_sibling_prev->tree_sibling_next = j; + else ARC_HEAD(b->tree_parent)->first_tree_child = j; + if (i->tree_sibling_next) i->tree_sibling_next->tree_sibling_prev = j; + else ARC_HEAD(b->tree_parent)->first_tree_child->tree_sibling_prev = j; + + i->tree_sibling_prev = i; + i->tree_sibling_next = NULL; + } + + // go through inner arcs + i = k; + while ( 1 ) + { + // "-" node + if (i->is_blossom) + { + a = ARC_TO_EDGE_PTR(i->match); + REAL tmp = a->slack; a->slack = i->y; i->y = tmp; + t->pq_blossoms.Add(a); + } + FOR_ALL_EDGES(i, a, dir, I) + { + j = a->head[dir]; + if (j->flag != 0) a->slack -= eps; + } + i->is_processed = 1; + if (i->tree_parent == b->tree_parent) break; + i = ARC_HEAD(i->tree_parent); + // "+" node + FOR_ALL_EDGES(i, a, dir, I) + { + j = a->head[dir]; + if (j->flag == 2) + { + a->slack += eps; + t->pq0.Add(a); + } + else if (j->flag == 0 && i < j) + { + a->slack += 2*eps; + t->pq00.Add(a); + } + } + i->is_processed = 1; + i = ARC_HEAD(i->match); + } + + // go through boundary arcs + for (tmp_item=expand_tmp_list->ScanFirst(); tmp_item; tmp_item=expand_tmp_list->ScanNext()) + { + i = tmp_item->i; + j = tmp_item->blossom_parent; tmp_item->blossom_parent = i->blossom_parent; i->blossom_parent = j; + j = tmp_item->blossom_grandparent; tmp_item->blossom_grandparent = i->blossom_grandparent; i->blossom_grandparent = j; + } + for (dir=0; dir<2; dir++) + { + if (!b->first[dir]) continue; + b->first[dir]->prev[dir]->next[dir] = NULL; + + Edge* a_next; + for (a=b->first[dir]; a; a=a_next) + { + a_next = a->next[dir]; + i = a->head0[1-dir]; + GET_PENULTIMATE_BLOSSOM2(i); + ADD_EDGE(i, a, dir); + GET_OUTER_HEAD(a, dir, j); + + if (i->flag == 1) continue; + + if (j->flag == 0 && j->tree != t) j->tree->pq_current->pq01[1-j->tree->dir_current].Remove(a, pq_buf); + + if (i->flag == 2) + { + a->slack += eps; + if (j->flag == 0) j->tree->pq0.Add(a); + } + else + { + a->slack += 2*eps; + if (j->flag == 2) t->pq0.Add(a); + else if (j->flag == 0) + { + if (j->tree != t) + { + if (!j->tree->pq_current) AddTreeEdge(t, j->tree); + if (a->slack <= j->tree->eps + eps) a_augment = a; + } + j->tree->pq_current->pq00.Add(a); + } + else if (j->tree != t) + { + if (!j->tree->pq_current) AddTreeEdge(t, j->tree); + j->tree->pq_current->pq01[j->tree->dir_current].Add(a); + } + + } + } + } + for (tmp_item=expand_tmp_list->ScanFirst(); tmp_item; tmp_item=expand_tmp_list->ScanNext()) + { + i = tmp_item->i; + i->blossom_parent = tmp_item->blossom_parent; + i->blossom_grandparent = tmp_item->blossom_grandparent; + i->is_outer = 1; + } + expand_tmp_list->Reset(); + + b->tree_sibling_next = removed_first; + removed_first = b; + removed_num ++; + if (4*removed_num > node_num) FreeRemoved(); + + blossom_num --; + stat.expand_count ++; + + stat.expand_time += get_time() - start_time; + + if (a_augment) Augment(a_augment); +} + +void PerfectMatching::FreeRemoved() +{ + Node* i0; + Node* i; + for (i0=nodes; i0is_outer && !i->is_marked; i=i->blossom_parent) + { + i->is_marked = 1; + if (i->blossom_grandparent->is_removed) i->blossom_grandparent = i->blossom_parent; + } + } + for (i0=nodes; i0is_outer && i->is_marked; i=i->blossom_parent) + { + i->is_marked = 0; + } + } + + while ((i=removed_first)) + { + removed_first = i->tree_sibling_next; + blossoms->Delete(i); + removed_num --; + } + + assert(removed_num == 0); +} + diff --git a/src/blossom5/PMimplementation.h b/src/blossom5/PMimplementation.h new file mode 100644 index 0000000..f64d26e --- /dev/null +++ b/src/blossom5/PMimplementation.h @@ -0,0 +1,356 @@ +/* + PMimplementation.h + + Copyright 2008 Vladimir Kolmogorov (vnk@adastral.ucl.ac.uk) + + This software can be used for research purposes only. Commercial use is prohibited. + Public redistribution of the code or its derivatives is prohibited. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef ASKHAKJSNTJAKSNBBAVASRA +#define ASKHAKJSNTJAKSNBBAVASRA + +#ifdef _MSC_VER +#pragma warning(disable: 4311) +#pragma warning(disable: 4312) +#endif + +#include "blossom5/PerfectMatching.h" +#include "blossom5/timer.h" +#include "blossom5/PQ.h" +#include "blossom5/LCA.h" + + +#define LCA_REPAIRS + + + + +#define IS_INT ( ((REAL)1 / 2) == 0 ) +#define COST_FACTOR 2 + +#define PM_THRESHOLD ((REAL)1e-12) + +struct PerfectMatching::Node +{ + unsigned int is_outer : 1; // 0 - the node is contained in another blossom, 1 - it's the outermost node + unsigned int flag : 2; // 0 corresponds to +, 1 corresponds to -, 2 corresponds to a free node + unsigned int is_tree_root : 1; + unsigned int is_processed : 1; + unsigned int is_blossom : 1; + unsigned int is_marked : 1; + unsigned int is_removed : 1; + + Edge* first[2]; + union + { + Arc* match; // used if not a tree root (is_tree_root = 0) or it's an inner node (is_outer == 0) + Node* blossom_grandparent; + }; + REAL y; + + union + { + struct // used when is_outer = 0 + { + Arc* blossom_sibling; + Node* blossom_parent; + union + { + Edge* blossom_selfloops; + Node* blossom_ptr; // used in repairs +#ifdef LCA_REPAIRS + int lca_preorder; // used in repairs +#endif + }; + REAL blossom_eps; // stores 'eps' of the tree at the moment when the node was shrunk into a blossom. + // (it is used for determining slacks of self-loops) + }; + struct // used when is_outer = 1 + { + union + { + struct // used for "+" nodes (flag = 0) + { + Node* first_tree_child; + Node* tree_sibling_prev; // circular list (with one exception: parent->first_tree_child->tree_sibling_prev->tree_sibling_next is NULL) + Node* tree_sibling_next; + }; + Arc* tree_parent; // used for "-" nodes (flag = 1) + }; + union + { + Tree* tree; + Edge* best_edge; // used during InitGlobal() for non-tree nodes +#ifdef LCA_REPAIRS + int lca_size; // used in repairs + LCATreeX* lca; // used in repairs +#endif + }; + }; + }; +}; + +struct PerfectMatching::Edge : PriorityQueue::Item +{ + Node* head[2]; + Node* head0[2]; + Edge* next[2]; + Edge* prev[2]; +}; + +typedef unsigned long POINTER_TYPE; +// if the declaration below fails, set POINTER_TYPE to be the appropriate integer type of the same length as (void*) +extern char dummy_array[2*(sizeof(void*)==sizeof(POINTER_TYPE))-1]; + +#define ARC_TO_EDGE_PTR(a) ( (Edge*) ( ((POINTER_TYPE)(a)) & (~1) ) ) +#define ARC_TO_EDGE_DIR(a) ( (int) ( ((POINTER_TYPE)(a)) & 1 ) ) +#define EDGE_DIR_TO_ARC(a, dir) ( (Arc*) ( (char*)(a) + (dir)) ) + +#define ARC_REV(a) ( (Arc*) ( ((POINTER_TYPE)(a)) ^ 1 ) ) + +#define ARC_TAIL(a) (ARC_TO_EDGE_PTR(a)->head [1-ARC_TO_EDGE_DIR(a)]) +#define ARC_TAIL0(a) (ARC_TO_EDGE_PTR(a)->head0[1-ARC_TO_EDGE_DIR(a)]) +#define ARC_HEAD(a) (ARC_TO_EDGE_PTR(a)->head [ARC_TO_EDGE_DIR(a)]) +#define ARC_HEAD0(a) (ARC_TO_EDGE_PTR(a)->head0[ARC_TO_EDGE_DIR(a)]) + +struct PerfectMatching::PQPointers +{ + PriorityQueue pq00; // plus-plus edges + union + { + PriorityQueue pq01[2]; // plus-minus, minus-plus edges. Used for tree edges. + struct // used for trees. + { + PriorityQueue pq0; // plus-free edges + PriorityQueue pq_blossoms; + }; + }; +}; + +struct PerfectMatching::Tree : PQPointers +{ + REAL eps; + TreeEdge* first[2]; + Node* root; + + PQPointers* pq_current; + int dir_current; + + ///////////////////////////////////////// + // used while computing dual updates + REAL eps_delta; + Tree* next; + union + { + int id; + TreeEdge* dfs_parent; + }; +}; + +struct PerfectMatching::TreeEdge : PQPointers +{ + Tree* head[2]; + TreeEdge* next[2]; +}; + + + +/////////////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////////// + + +#define GET_PENULTIMATE_BLOSSOM(j)\ + {\ + Node* jtmp1 = j;\ + while ( 1 )\ + {\ + if (!j->blossom_grandparent->is_outer) j = j->blossom_grandparent;\ + else if (j->blossom_grandparent != j->blossom_parent) j->blossom_grandparent = j->blossom_parent;\ + else break;\ + }\ + Node* jtmp2;\ + for ( ; jtmp1!=j; jtmp1=jtmp2)\ + {\ + jtmp2 = jtmp1->blossom_grandparent;\ + jtmp1->blossom_grandparent = j;\ + }\ + } +#define GET_PENULTIMATE_BLOSSOM2(j)\ + {\ + Node* jtmp1 = j;\ + Node* jtmp_prev = NULL;\ + while ( 1 )\ + {\ + if (!j->blossom_grandparent->is_outer) { jtmp_prev = j; j = j->blossom_grandparent; }\ + else if (j->blossom_grandparent != j->blossom_parent) j->blossom_grandparent = j->blossom_parent;\ + else break;\ + }\ + if (jtmp_prev)\ + {\ + Node* jtmp2;\ + for ( ; jtmp1!=jtmp_prev; jtmp1=jtmp2)\ + {\ + jtmp2 = jtmp1->blossom_grandparent;\ + jtmp1->blossom_grandparent = jtmp_prev;\ + }\ + }\ + } + + +/////////////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////////// + + +struct PerfectMatching::EdgeIterator +{ + Edge* a_last; + int start_flag; +}; + +#define FOR_ALL_EDGES(i, a, dir, I)\ + for ( dir = (i->first[0]) ? 0 : 1, I.a_last = a = i->first[dir], I.start_flag = (a) ? 0 : 1;\ + a != I.a_last || (I.start_flag ++ == 0) || (dir ++ == 0 && (I.a_last = a = i->first[1]));\ + a = a->next[dir] ) + +#define CONTINUE_FOR_ALL_EDGES(i, a, dir, I)\ + for ( a = a->next[dir];\ + a != I.a_last || (I.start_flag ++ == 0) || (dir ++ == 0 && (I.a_last = a = i->first[1]));\ + a = a->next[dir] ) + +#define REMOVE_EDGE(i, a, dir)\ + {\ + if ((a)->prev[dir]==(a)) (i)->first[dir] = NULL;\ + else\ + {\ + (a)->prev[dir]->next[dir] = (a)->next[dir];\ + (a)->next[dir]->prev[dir] = (a)->prev[dir];\ + (i)->first[dir] = (a)->next[dir];\ + }\ + } + +#define ADD_EDGE(i, a, dir)\ + {\ + if ((i)->first[dir])\ + {\ + (a)->prev[dir] = (i)->first[dir]->prev[dir];\ + (a)->next[dir] = (i)->first[dir];\ + (i)->first[dir]->prev[dir]->next[dir] = (a);\ + (i)->first[dir]->prev[dir] = (a);\ + }\ + else (i)->first[dir] = (a)->prev[dir] = (a)->next[dir] = (a);\ + (a)->head[1-(dir)] = (i);\ + } + +#define MOVE_EDGE(i_old, i_new, a, dir)\ + {\ + REMOVE_EDGE(i_old, a, dir);\ + ADD_EDGE(i_new, a, dir);\ + } + +#define GET_OUTER_HEAD(a, dir, j)\ + {\ + j = (a)->head[dir];\ + if (!j->is_outer)\ + {\ + Node* j_orig = j;\ + GET_PENULTIMATE_BLOSSOM(j);\ + j = j->blossom_parent;\ + int dir_rev = 1 - (dir);\ + MOVE_EDGE(j_orig, j, a, dir_rev);\ + }\ + } + +#define GET_TREE_PARENT(child, parent)\ + {\ + Arc* a = (child)->tree_parent;\ + Edge* e = ARC_TO_EDGE_PTR(a);\ + int dir = ARC_TO_EDGE_DIR(a);\ + GET_OUTER_HEAD(e, dir, parent);\ + } + +/////////////////////////////////////////////////////////////////////////////////////////////// + +struct PerfectMatching::TreeEdgeIterator +{ + TreeEdge** e_ptr; +}; + +#define FOR_ALL_TREE_EDGES(t, e, dir)\ + for ( dir = (t->first[0]) ? 0 : 1, e = t->first[dir];\ + e || (dir ++ == 0 && (e = t->first[1]));\ + e = e->next[dir] ) + +#define FOR_ALL_TREE_EDGES_X(t, e, dir, T)\ + for ( dir = (t->first[0]) ? 0 : 1, T.e_ptr = &t->first[dir], e = *T.e_ptr;\ + e || (dir ++ == 0 && (e = *(T.e_ptr = &t->first[1])));\ + e = *T.e_ptr )\ + if (e->head[dir] == NULL) { *T.e_ptr = e->next[dir]; tree_edges->Delete(e); }\ + else if ((T.e_ptr = &e->next[dir])) + +/////////////////////////////////////////////////////////////////////////////////////////////// + +#define MOVE_NODE_IN_TREE(i)\ + {\ + if ((i)->first_tree_child) (i) = (i)->first_tree_child;\ + else\ + {\ + while (!(i)->is_tree_root && !(i)->tree_sibling_next) { (i) = ARC_HEAD((i)->match); GET_TREE_PARENT(i, i); }\ + if ((i)->is_tree_root) break;\ + (i) = (i)->tree_sibling_next;\ + }\ + } + +// i=parent, j=child +#define ADD_TREE_CHILD(i, j)\ + {\ + (j)->flag = 0;\ + (j)->tree = (i)->tree;\ + (j)->first_tree_child = NULL;\ + (j)->tree_sibling_next = (i)->first_tree_child;\ + if ((i)->first_tree_child)\ + {\ + (j)->tree_sibling_prev = (i)->first_tree_child->tree_sibling_prev;\ + (i)->first_tree_child->tree_sibling_prev = j;\ + }\ + else\ + {\ + (j)->tree_sibling_prev = j;\ + }\ + (i)->first_tree_child = j;\ + } + + +#define REMOVE_FROM_TREE(i)\ + {\ + if ((i)->tree_sibling_next) (i)->tree_sibling_next->tree_sibling_prev = (i)->tree_sibling_prev;\ + else\ + {\ + Node* i_NEXT = ARC_HEAD((i)->match); i_NEXT = ARC_HEAD(i_NEXT->tree_parent); i_NEXT = i_NEXT->first_tree_child;\ + i_NEXT->tree_sibling_prev = (i)->tree_sibling_prev;\ + }\ + if ((i)->tree_sibling_prev->tree_sibling_next) (i)->tree_sibling_prev->tree_sibling_next = (i)->tree_sibling_next;\ + else\ + {\ + Node* i_PARENT = ARC_HEAD((i)->match); i_PARENT = ARC_HEAD(i_PARENT->tree_parent);\ + i_PARENT->first_tree_child = (i)->tree_sibling_next;\ + }\ + } + + +#endif + diff --git a/src/blossom5/PMinit.cpp b/src/blossom5/PMinit.cpp new file mode 100644 index 0000000..e68bd1e --- /dev/null +++ b/src/blossom5/PMinit.cpp @@ -0,0 +1,544 @@ +#include +#include +#include +#include "blossom5/PMimplementation.h" + + +void PerfectMatching::InitGreedy(bool allocate_trees) +{ + Node* i; + int dir; + Edge* a; + EdgeIterator I; + Tree* t = NULL; + Node* last_root = &nodes[node_num]; + REAL slack_min; + + for (i=nodes; iy = PM_INFTY; + for (a=edges; ahead[0]->y > a->slack) a->head[0]->y = a->slack; + if (a->head[1]->y > a->slack) a->head[1]->y = a->slack; + } + for (a=edges; ahead[0]; + if (!i->is_outer) + { + i->is_outer = 1; + i->y /= 2; + } + a->slack -= i->y; + i = a->head[1]; + if (!i->is_outer) + { + i->is_outer = 1; + i->y /= 2; + } + a->slack -= i->y; + } + + tree_num = node_num; + for (i=nodes; iflag == 2) continue; + slack_min = PM_INFTY; + FOR_ALL_EDGES(i, a, dir, I) if (slack_min > a->slack) slack_min = a->slack; + i->y += slack_min; + FOR_ALL_EDGES(i, a, dir, I) + { + if (a->slack <= slack_min && i->flag == 0 && a->head[dir]->flag == 0) + { + i->flag = 2; + a->head[dir]->flag = 2; + i->match = EDGE_DIR_TO_ARC(a, dir); + a->head[dir]->match = EDGE_DIR_TO_ARC(a, 1-dir); + tree_num -= 2; + } + a->slack -= slack_min; + } + } + if (allocate_trees) + { + if (tree_num > tree_num_max) + { + if (trees) free(trees); + tree_num_max = tree_num; + trees = (Tree*) malloc(tree_num_max*sizeof(Tree)); + } + t = trees; + } + for (i=nodes; iflag != 0) continue; + i->is_tree_root = 1; + i->first_tree_child = NULL; + i->tree_sibling_prev = last_root; + last_root->tree_sibling_next = i; + last_root = i; + if (allocate_trees) + { + i->tree = t; + t->root = i; + t->eps = 0; + t->first[0] = t->first[1] = NULL; + t->pq_current = NULL; + t->pq00.Reset(); + t->pq0.Reset(); + t->pq_blossoms.Reset(); + t ++; + } + } + last_root->tree_sibling_next = NULL; +} + +//////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////// + +PerfectMatching::Node* PerfectMatching::FindBlossomRootInit(Edge* a0) +{ + Node* i; + Node* j; + Node* _i[2]; + Node* r; + int branch; + + _i[0] = ARC_HEAD(a0); + _i[1] = ARC_TAIL(a0); + branch = 0; + while ( 1 ) + { + if (!_i[branch]->is_outer) + { + r = _i[branch]; + j = _i[1-branch]; + break; + } + _i[branch]->is_outer = 0; + if (_i[branch]->is_tree_root) + { + j = _i[branch]; + i = _i[1-branch]; + while (i->is_outer) + { + i->is_outer = 0; + i = ARC_HEAD(i->match); + i->is_outer = 0; + i = ARC_HEAD(i->tree_parent); + } + r = i; + break; + } + i = ARC_HEAD(_i[branch]->match); + i->is_outer = 0; + _i[branch] = ARC_HEAD(i->tree_parent); + branch = 1 - branch; + } + i = r; + while ( i != j ) + { + i = ARC_HEAD(i->match); + i->is_outer = 1; + i = ARC_HEAD(i->tree_parent); + i->is_outer = 1; + } + return r; +} + +void PerfectMatching::ShrinkInit(Edge* a0, Node* tree_root) +{ + int branch, flag; + Node* i; + Node* j; + Node* r; + Arc* a_prev; + Arc* aa; + + tree_root->flag = 2; + i = tree_root->first_tree_child; + if ( i ) + while ( 1 ) + { + ARC_HEAD(i->match)->flag = 2; + i->flag = 2; + + MOVE_NODE_IN_TREE(i); + } + + r = FindBlossomRootInit(a0); + + if ( !r->is_tree_root ) + { + j = ARC_HEAD(r->match); + j->match = aa = j->tree_parent; + i = ARC_HEAD(aa); + while ( !i->is_tree_root ) + { + j = ARC_HEAD(i->match); + i->match = ARC_REV(aa); + j->match = aa = j->tree_parent; + i = ARC_HEAD(aa); + } + i->match = ARC_REV(aa); + } + + tree_root->is_tree_root = 0; + + branch = 0; + flag = 0; + a_prev = EDGE_DIR_TO_ARC(a0, 0); + i = ARC_HEAD(a_prev); + while ( 1 ) + { + Arc* a_next = (flag == 0) ? i->match : i->tree_parent; + flag = 1 - flag; + i->flag = 0; + i->match = NULL; + if (branch == 0) + { + i->blossom_sibling = a_next; + if (i == r) + { + branch = 1; + flag = 0; + a_prev = ARC_REV(a0); + i = ARC_HEAD(a_prev); + if (i == r) break; + } + else + { + a_prev = i->blossom_sibling; + i = ARC_HEAD(a_prev); + } + } + else + { + i->blossom_sibling = ARC_REV(a_prev); + a_prev = a_next; + i = ARC_HEAD(a_prev); + if (i == r) break; + } + } + i->blossom_sibling = ARC_REV(a_prev); +} + +void PerfectMatching::ExpandInit(Node* k) +{ + Node* i = ARC_HEAD(k->blossom_sibling); + Node* j; + + while ( 1 ) + { + i->flag = 2; i->is_outer = 1; + if (i == k) break; + i->match = i->blossom_sibling; + j = ARC_HEAD(i->match); + j->flag = 2; j->is_outer = 1; + j->match = ARC_REV(i->match); + i = ARC_HEAD(j->blossom_sibling); + } +} + +void PerfectMatching::AugmentBranchInit(Node* i0, Node* r) +{ + Node* tree_root_prev = r->tree_sibling_prev; + Node* i; + Node* j; + Arc* aa; + + r->flag = 2; + i = r->first_tree_child; + if ( i ) + while ( 1 ) + { + ARC_HEAD(i->match)->flag = 2; + i->flag = 2; + + MOVE_NODE_IN_TREE(i); + } + i = i0; + if ( !i0->is_tree_root ) + { + j = ARC_HEAD(i0->match); + j->match = aa = j->tree_parent; + i = ARC_HEAD(aa); + while ( !i->is_tree_root ) + { + j = ARC_HEAD(i->match); + i->match = ARC_REV(aa); + j->match = aa = j->tree_parent; + i = ARC_HEAD(aa); + } + i->match = ARC_REV(aa); + } + r->is_tree_root = 0; + tree_root_prev->tree_sibling_next = r->tree_sibling_next; + if (r->tree_sibling_next) r->tree_sibling_next->tree_sibling_prev = tree_root_prev; + tree_num --; +} + +//////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////// + +// true_slack(a) = slack(a) + ... + +// i->flag=0, i->is_processed=1: true_slack -= eps +// i->flag=1, i->match->head->is_processed=1: true_slack += eps - slack(i->match) + +void PerfectMatching::InitGlobal() +{ + Node* i; + Node* j; + Node* r; + Node* r2; + Node* r3 = NULL; // initialize to prevent compiler warning + Edge* a; + EdgeIterator I; + int dir; + Tree TREE; + enum { NONE, AUGMENT, SHRINK } flag; + + InitGreedy(); + + for (i=nodes; ibest_edge = NULL; + + PriorityQueue pq; + + for (r=nodes[node_num].tree_sibling_next; r; ) + { + r2 = r->tree_sibling_next; + if (r2) r3 = r2->tree_sibling_next; + i = r; + + pq.Reset(); + + r->tree = &TREE; + + REAL eps = 0; + Arc* critical_arc = NULL; + REAL critical_eps = PM_INFTY; + flag = NONE; + Node* branch_root = i; + + while ( 1 ) + { + i->is_processed = 1; + i->y -= eps; + if (!i->is_tree_root) ARC_HEAD(i->match)->y += eps; + + FOR_ALL_EDGES(i, a, dir, I) + { + a->slack += eps; + j = a->head[dir]; + + if (j->tree == &TREE) + { + // same tree + if (j->flag == 0) + { + REAL slack = a->slack; + if (!j->is_processed) slack += eps; + if (2*critical_eps > slack || critical_arc == NULL) + { + flag = SHRINK; + critical_eps = slack/2; + critical_arc = EDGE_DIR_TO_ARC(a, dir); + if (critical_eps <= eps) break; + //pq.DecreaseUpperBound(critical_eps); + } + } + } + else if (j->flag == 0) + { + // different tree + if (critical_eps >= a->slack || critical_arc == NULL) + { + flag = AUGMENT; + critical_eps = a->slack; + critical_arc = EDGE_DIR_TO_ARC(a, dir); + if (critical_eps <= eps) break; + //pq.DecreaseUpperBound(critical_eps); + } + } + else + { + // free node + if (a->slack > eps) + { + if (a->slack < critical_eps) + { + if (j->best_edge == NULL) + { + j->best_edge = a; + pq.Add(a); + } + else + { + if (a->slack < j->best_edge->slack) + { + pq.Decrease(j->best_edge, a, pq_buf); + j->best_edge = a; + } + } + } + } + else + { + assert(j->flag == 2 && !j->is_blossom && !ARC_HEAD(j->match)->is_blossom); + if (j->best_edge) pq.Remove(j->best_edge, pq_buf); + j->flag = 1; + j->tree = i->tree; + j->tree_parent = EDGE_DIR_TO_ARC(a, 1-dir); + j = ARC_HEAD(j->match); + if (j->best_edge) pq.Remove(j->best_edge, pq_buf); + ADD_TREE_CHILD(i, j); + } + } + } + + if (dir < 2 && a) + { + Edge* atmp = a; + int dirtmp = dir; + CONTINUE_FOR_ALL_EDGES(i, atmp, dirtmp, I) atmp->slack += eps; + break; + } + + // move i + if (i->first_tree_child) i = i->first_tree_child; + else + { + while (i != branch_root && !i->tree_sibling_next) { i = ARC_HEAD(i->match); i = ARC_HEAD(i->tree_parent); } + if (i == branch_root) + { + PriorityQueue::Item* q = pq.GetMin(); + if (q == NULL || q->slack >= critical_eps) + { + eps = critical_eps; + break; + } + pq.Remove(q, pq_buf); + a = (Edge*)q; + dir = (a->head[0]->flag == 2) ? 0 : 1; + j = a->head[0]; + Arc* aa = EDGE_DIR_TO_ARC(a, dir); + eps = a->slack; + assert(eps < critical_eps); + + // continue growth + i = ARC_TAIL(aa); + j = ARC_HEAD(aa); + + assert(j->flag == 2 && !j->is_blossom && !ARC_HEAD(j->match)->is_blossom); + j->flag = 1; + j->tree = i->tree; + j->tree_parent = ARC_REV(aa); + j = ARC_HEAD(j->match); + if (j->best_edge) pq.Remove(j->best_edge, pq_buf); + ADD_TREE_CHILD(i, j); + i = branch_root = j; + continue; + } + i = i->tree_sibling_next; + } + } + + // update slacks + i = r; + while ( 1 ) + { + if (i->is_processed) + { + i->y += eps; + if (!i->is_tree_root) + { + j = ARC_HEAD(i->match); + j->y -= eps; + REAL delta = eps - ARC_TO_EDGE_PTR(i->match)->slack; + FOR_ALL_EDGES(j, a, dir, I) a->slack += delta; + j->best_edge = NULL; + } + FOR_ALL_EDGES(i, a, dir, I) + { + if (!PriorityQueue::isReset(a)) + { + assert(a->head[dir]->flag == 2 && a->head[dir]->best_edge == a); + a->head[dir]->best_edge = NULL; + PriorityQueue::ResetItem(a); + } + a->slack -= eps; + } + + i->is_processed = 0; + } + else + { + if (!i->is_tree_root) ARC_HEAD(i->match)->best_edge = NULL; + } + i->best_edge = NULL; + + MOVE_NODE_IN_TREE(i); + } + + i = ARC_TAIL(critical_arc); + j = ARC_HEAD(critical_arc); + if (flag == SHRINK) + { + // shrink + ShrinkInit(ARC_TO_EDGE_PTR(critical_arc), r); + } + else + { + // augment + AugmentBranchInit(i, r); + if (j->is_outer) + { + AugmentBranchInit(j, j); + } + else + { + ExpandInit(j); + tree_num --; + } + i->match = critical_arc; + j->match = ARC_REV(critical_arc); + } + + r = r2; + if (r && !r->is_tree_root) r = r3; + } + + if (tree_num > tree_num_max) + { + if (trees) free(trees); + tree_num_max = tree_num; + trees = (Tree*) malloc(tree_num_max*sizeof(Tree)); + } + Tree* t = trees; + for (r=nodes; ris_outer) + { + ExpandInit(r); + r->is_tree_root = 1; + r->flag = 0; + r->first_tree_child = NULL; + if (t == trees) { nodes[node_num].tree_sibling_next = r; r->tree_sibling_prev = &nodes[node_num]; } + else { (t-1)->root->tree_sibling_next = r; r->tree_sibling_prev = (t-1)->root; } + r->tree = t; + t->root = r; + t->eps = 0; + t->first[0] = t->first[1] = NULL; + t->pq_current = NULL; + t->pq00.Reset(); + t->pq0.Reset(); + t->pq_blossoms.Reset(); + t ++; + } + } + assert(t == trees+tree_num); + if (t == trees) nodes[node_num].tree_sibling_next = NULL; + else (t-1)->root->tree_sibling_next = NULL; +} diff --git a/src/blossom5/PMinterface.cpp b/src/blossom5/PMinterface.cpp new file mode 100644 index 0000000..4cf138c --- /dev/null +++ b/src/blossom5/PMinterface.cpp @@ -0,0 +1,270 @@ +#include +#include +#include +#include "blossom5/PMimplementation.h" + + +PerfectMatching::PerfectMatching(int nodeNum, int edgeNumMax) + : node_num(nodeNum), + edge_num(0), + edge_num_max(edgeNumMax), + trees(NULL), + tree_num_max(0), + removed_first(NULL), + blossom_num(0), + removed_num(0), + first_solve(true) +{ + if (node_num & 1) { printf("# of nodes is odd: perfect matching cannot exist\n"); exit(1); } + nodes = (Node*) malloc((node_num+1)*sizeof(Node)); + edges_orig = (char*) malloc(edge_num_max*sizeof(Edge)+1); + edges = (Edge*) ( ( ((POINTER_TYPE)edges_orig) & 1 ) ? (edges_orig + 1) : edges_orig ); + memset(nodes, 0, (node_num+1)*sizeof(Node)); + + blossoms = new DBlock(256); + tree_edges = new DBlock(256); + expand_tmp_list = new Block(256); + pq_buf = PriorityQueue::AllocateBuf(); +} + + +void PerfectMatching::Save(char* filename, int format) +{ + if (!first_solve) { printf("Save() cannot be called after Solve()!\n"); exit(1); } + int e; + FILE* fp = fopen(filename, "w"); + if (!fp) { printf("Can't open %s\n", filename); exit(1); } + if (format == 0) + { + fprintf(fp, "p edge %d %d\n", node_num, edge_num); + for (e=0; e::DeallocateBuf(pq_buf); +} + + +PerfectMatching::EdgeId PerfectMatching::AddEdge(NodeId _i, NodeId _j, REAL cost) +{ + if (_i<0 || _i>=node_num || _j<0 || _j>node_num || _i==_j) + { + printf("wrong node id's! (%d,%d)\n", _i, _j); exit(1); + } + if (edge_num >= edge_num_max) ReallocateEdges(); + Node* i = nodes + _i; + Node* j = nodes + _j; + Edge* a = edges + edge_num; + + ADD_EDGE(i, a, 0); + ADD_EDGE(j, a, 1); + a->head0[0] = j; + a->head0[1] = i; + + a->slack = cost*COST_FACTOR; + PriorityQueue::ResetItem(a); + + return edge_num ++; +} + +int PerfectMatching::GetSolution(EdgeId e) +{ + assert(e>=0 && ehead0[1]->match == EDGE_DIR_TO_ARC(a, 0)) ? 1 : 0; +} + +PerfectMatching::NodeId PerfectMatching::GetMatch(NodeId i) +{ + assert(i>=0 && ihead0[1]; !i->is_outer; i=i->blossom_parent, delta--) {} + for (j=a->head0[0]; !j->is_outer; j=j->blossom_parent, delta++) {} + if ( i == j ) + { + i = a->head0[1]; + j = a->head0[0]; + while ( delta < 0 ) { i = i->blossom_parent; delta ++; } + while ( delta > 0 ) { j = j->blossom_parent; delta --; } + while ( i->blossom_parent != j->blossom_parent ) + { + i = i->blossom_parent; + j = j->blossom_parent; + } + } + tail = i; + head = j; + assert((i->is_outer && j->is_outer) || (i->blossom_parent==j->blossom_parent && !i->is_outer && !j->is_outer)); +} + +void PerfectMatching::ReallocateEdges() +{ + printf("Warning: reallocating edges. Increasing edge_num_max in the constructor may improve memory efficiency!\n"); + edge_num_max = edge_num_max*3/2 + 16; + char* edges_orig_old = edges_orig; + Edge* edges_old = edges; + edges_orig = (char*) realloc(edges_orig_old, edge_num_max*sizeof(Edge)+1); + edges = (Edge*) ( ( ((POINTER_TYPE)edges_orig_old) & 1 ) ? (edges_orig + 1) : edges_orig ); + if ( ((POINTER_TYPE)edges) & 1 ) + { + char* edges_orig_old2 = edges_orig; + Edge* edges_old2 = edges; + + edges_orig = (char*) malloc(edge_num_max*sizeof(Edge)+1); + edges = (Edge*) ( ( ((POINTER_TYPE)edges_orig_old) & 1 ) ? (edges_orig + 1) : edges_orig ); + memcpy(edges, edges_old2, edge_num*sizeof(Edge)); + free(edges_orig_old2); + } + +#define UPDATE_EDGE_PTR(ptr) ptr = (Edge*)((char*)(ptr) + ((char*)edges - (char*)edges_old)) +#define UPDATE_ARC_PTR(ptr) ptr = (Arc*)((char*)(ptr) + ((char*)edges - (char*)edges_old)) + + Node* i; + Edge* a; + for (a=edges; anext[0]) UPDATE_EDGE_PTR(a->next[0]); + if (a->next[1]) UPDATE_EDGE_PTR(a->next[1]); + if (a->prev[0]) UPDATE_EDGE_PTR(a->prev[0]); + if (a->prev[1]) UPDATE_EDGE_PTR(a->prev[1]); + } + if (first_solve) + { + for (i=nodes; ifirst[0]) UPDATE_EDGE_PTR(i->first[0]); + if (i->first[1]) UPDATE_EDGE_PTR(i->first[1]); + } + } + else + { + Node* i0; + for (i0=nodes; i0is_outer) + { + UPDATE_ARC_PTR(i->match); + if (i->first[0]) UPDATE_EDGE_PTR(i->first[0]); + if (i->first[1]) UPDATE_EDGE_PTR(i->first[1]); + break; + } + UPDATE_ARC_PTR(i->blossom_sibling); + if (i->first[0]) UPDATE_EDGE_PTR(i->first[0]); + if (i->first[1]) UPDATE_EDGE_PTR(i->first[1]); + + i = i->blossom_parent; + if (i->is_outer) { if ( i->is_marked) break; i->is_marked = 1; } + else { if (!i->is_marked) break; i->is_marked = 0; } + } + } + for (i0=nodes; i0is_outer) break; + + i = i->blossom_parent; + if (i->is_outer) { if (!i->is_marked) break; i->is_marked = 0; } + else { if ( i->is_marked) break; i->is_marked = 1; } + } + } + } +} + +int PerfectMatching::GetBlossomNum() +{ + return blossom_num; +} + +void PerfectMatching::GetDualSolution(int* blossom_parents, REAL* twice_y) +{ + int _i0, id = node_num; + int* child_ptr; + Node* i0; + Node* i; + int* tmp_array = new int[blossom_num]; + + int* tmp_array_ptr = tmp_array; + for (_i0=0, i0=nodes; _i0y; + if (i0->is_outer) + { + blossom_parents[_i0] = -1; + continue; + } + child_ptr = &blossom_parents[_i0]; + i = i0->blossom_parent; + while ( 1 ) + { + if (i->is_marked) + { + *child_ptr = i->lca_preorder; + break; + } + i->is_marked = 1; + *tmp_array_ptr ++ = i->lca_preorder; + *child_ptr = i->lca_preorder = id ++; + child_ptr = &blossom_parents[i->lca_preorder]; + twice_y[i->lca_preorder] = i->y; + if (i->is_outer) + { + *child_ptr = -1; + break; + } + i = i->blossom_parent; + } + } + + assert(id == node_num+blossom_num && tmp_array_ptr == tmp_array + blossom_num); + + tmp_array_ptr = tmp_array; + for (_i0=0, i0=nodes; _i0is_outer) continue; + i = i0->blossom_parent; + while ( 1 ) + { + if (!i->is_marked) break; + i->is_marked = 0; + i->lca_preorder = *tmp_array_ptr ++; + if (i->is_outer) break; + i = i->blossom_parent; + } + } + + delete [] tmp_array; +} diff --git a/src/blossom5/PMmain.cpp b/src/blossom5/PMmain.cpp new file mode 100644 index 0000000..097c020 --- /dev/null +++ b/src/blossom5/PMmain.cpp @@ -0,0 +1,694 @@ +#include +#include +#include +#include "blossom5/PMimplementation.h" + + +void PerfectMatching::Finish() +{ + +#define IS_VALID_MATCH(i) ((Edge*)(i->match) >= edges && (Edge*)(i->match) < edges + edge_num) + + Node* i0; + Node* i; + Node* j; + Node* k; + Node* b; + Node* b_prev; + Node* b_prev_prev; + + for (i0=nodes; i0blossom_grandparent = b_prev; + b_prev = b; + b = b->blossom_parent; + } while (!IS_VALID_MATCH(b)); + + b_prev_prev = b_prev->blossom_grandparent; + while ( 1 ) + { + for (k=ARC_TAIL0(b->match); k->blossom_parent!=b; k=k->blossom_parent) {} + k->match = b->match; + i = ARC_HEAD(k->blossom_sibling); + while ( i != k ) + { + i->match = i->blossom_sibling; + j = ARC_HEAD(i->match); + j->match = ARC_REV(i->match); + i = ARC_HEAD(j->blossom_sibling); + } + + b = b_prev; + if (!b->is_blossom) break; + b_prev = b_prev_prev; + b_prev_prev = b_prev->blossom_grandparent; + } + } +} + + +void PerfectMatching::AddTreeEdge(Tree* t0, Tree* t1) +{ + TreeEdge* e = tree_edges->New(); + e->head[0] = t1; + e->head[1] = t0; + e->next[0] = t0->first[0]; + t0->first[0] = e; + e->next[1] = t1->first[1]; + t1->first[1] = e; + + e->pq00.Reset(); + e->pq01[0].Reset(); + e->pq01[1].Reset(); + + t1->pq_current = e; + t1->dir_current = 0; +} + +bool PerfectMatching::ProcessEdge00(Edge* a, bool update_boundary_edge) +{ + int dir; + Node* j; + Node* prev[2]; + Node* last[2]; + for (dir=0; dir<2; dir++) + { + if (a->head[dir]->is_outer) { prev[dir] = NULL; last[dir] = a->head[dir]; } + else + { + j = a->head[dir]; + GET_PENULTIMATE_BLOSSOM(j); + prev[dir] = j; + last[dir] = prev[dir]->blossom_parent; + //assert(last[dir]->is_outer); + } + } + + if (last[0] != last[1]) + { + for (dir=0; dir<2; dir++) + { + j = a->head[dir]; + if (j != last[dir]) { int dir_rev = 1 - dir; MOVE_EDGE(j, last[dir], a, dir_rev); } + } + if (update_boundary_edge) a->slack -= 2*a->head[0]->tree->eps; + return true; + } + + if (prev[0] != prev[1]) + { + for (dir=0; dir<2; dir++) + { + j = a->head[dir]; + if (j != prev[dir]) { int dir_rev = 1 - dir; MOVE_EDGE(j, prev[dir], a, dir_rev); } + } + a->slack -= 2*prev[0]->blossom_eps; + return false; + } + + for (dir=0; dir<2; dir++) + { + j = a->head[1-dir]; + REMOVE_EDGE(j, a, dir); + } + a->next[0] = prev[0]->blossom_selfloops; + prev[0]->blossom_selfloops = a; + return false; +} + + +inline void PerfectMatching::AugmentBranch(Node* i0) +{ + int dir; + Tree* t = i0->tree; + Node* r = t->root; + Node* tree_root_prev = r->tree_sibling_prev; + Node* i; + Node* j; + Edge* a; + EdgeIterator I; + Arc* aa; + REAL eps = t->eps; + PriorityQueue::Item* q; + TreeEdge* e; + TreeEdgeIterator T; + Tree* t2; + + t = r->tree; + t->pq_current = t; + + FOR_ALL_TREE_EDGES_X(t, e, dir, T) + { + t2 = e->head[dir]; + e->head[1-dir] = NULL; // mark it for deletion + + t2->pq_current = e; + t2->dir_current = dir; + } + + i = r->first_tree_child; + if ( i ) + while ( 1 ) + { + Node* i0 = i; + i = ARC_HEAD(i->match); + if (i->is_processed) + { + if (i->is_blossom) + { + a = ARC_TO_EDGE_PTR(i->match); + REAL tmp = a->slack; a->slack = i->y; i->y = tmp; + PriorityQueue::ResetItem(a); + } + FOR_ALL_EDGES(i, a, dir, I) + { + GET_OUTER_HEAD(a, dir, j); + + if (j->flag == 0 && j->is_processed) + { + if (j->tree != t) + { + a->slack += eps; + if (PriorityQueue::isReset(a)) j->tree->pq0.Add(a); + } + } + else a->slack += eps; + } + } + + i = i0; + MOVE_NODE_IN_TREE(i); + } + + /////////////////////////////////////////////////////////////////// + + FOR_ALL_TREE_EDGES(t, e, dir) + { + t2 = e->head[dir]; + t2->pq_current = NULL; + + e->pq01[1-dir].Merge(t2->pq0); + for (q=e->pq00.GetFirst(); q; q=e->pq00.GetNext(q)) + { + q->slack -= eps; + int dir2; + for (dir2=0; dir2<2; dir2++) GET_OUTER_HEAD((Edge*)q, dir2, j); + } + e->pq00.Merge(t2->pq0); + for (q=e->pq01[dir].GetAndResetFirst(); q; q=e->pq01[dir].GetAndResetNext()) + { + q->slack -= eps; + int dir2; + for (dir2=0; dir2<2; dir2++) GET_OUTER_HEAD((Edge*)q, dir2, j); + } + } + for (q=t->pq0.GetAndResetFirst(); q; q=t->pq0.GetAndResetNext()) + { + q->slack -= eps; + int dir2; + for (dir2=0; dir2<2; dir2++) GET_OUTER_HEAD((Edge*)q, dir2, j); + } + for (q=t->pq00.GetAndResetFirst(); q; q=t->pq00.GetAndResetNext()) + { + ProcessEdge00((Edge*)q); + } + + /////////////////////////////////////////////////////////////////// + + r->flag = 2; + r->is_processed = 0; + i = r->first_tree_child; + r->y += eps; + if ( i ) + while ( 1 ) + { + j = ARC_HEAD(i->match); + j->flag = 2; + i->flag = 2; + j->is_processed = 0; + i->is_processed = 0; + j->y -= eps; + i->y += eps; + + MOVE_NODE_IN_TREE(i); + } + + /////////////////////////////////////////////////////////////////// + + i = i0; + if ( !i0->is_tree_root ) + { + j = ARC_HEAD(i0->match); + GET_TREE_PARENT(j, i); + j->match = aa = j->tree_parent; + while ( !i->is_tree_root ) + { + j = ARC_HEAD(i->match); + i->match = ARC_REV(aa); + GET_TREE_PARENT(j, i); + j->match = aa = j->tree_parent; + } + i->match = ARC_REV(aa); + } + r->is_tree_root = 0; + tree_root_prev->tree_sibling_next = r->tree_sibling_next; + if (r->tree_sibling_next) r->tree_sibling_next->tree_sibling_prev = tree_root_prev; + tree_num --; +} + + +void PerfectMatching::Augment(Edge* a) +{ + Node* j; + int dir; + + for (dir=0; dir<2; dir++) + { + GET_OUTER_HEAD(a, dir, j); + AugmentBranch(j); + j->match = EDGE_DIR_TO_ARC(a, 1-dir); + } + if (options.verbose) + { + int k = 1; + while (k < tree_num) k *= 2; + if (k == tree_num || tree_num<=8 || (tree_num<=64 && (tree_num%8)==0)) { printf("%d.", tree_num); fflush(stdout); } + } +} + +inline void PerfectMatching::GrowNode(Node* i) +{ + //assert(i->is_outer); + //assert(i->flag == 0); + + Edge* a; + EdgeIterator I; + int dir; + Node* j; + Tree* t = i->tree; + REAL eps = t->eps; + Edge* a_augment = NULL; + + FOR_ALL_EDGES(i, a, dir, I) + { + GET_OUTER_HEAD(a, dir, j); + + if (j->flag == 2) + { + a->slack += eps; + if (a->slack > 0) + { + t->pq0.Add(a); + } + else + { + j->flag = 1; + j->tree = i->tree; + j->tree_parent = EDGE_DIR_TO_ARC(a, 1-dir); + j->y += eps; + j = ARC_HEAD(j->match); + j->y -= eps; + ADD_TREE_CHILD(i, j); + } + } + else + { + if (j->flag == 0 && j->is_processed) + { + if (!PriorityQueue::isReset(a)) j->tree->pq0.Remove(a, pq_buf); + if (a->slack <= j->tree->eps && j->tree != t) a_augment = a; + a->slack += eps; + if (!j->tree->pq_current) AddTreeEdge(t, j->tree); + j->tree->pq_current->pq00.Add(a); + } + else + { + a->slack += eps; + if (j->flag == 1 && j->tree != t) + { + if (!j->tree->pq_current) AddTreeEdge(t, j->tree); + j->tree->pq_current->pq01[j->tree->dir_current].Add(a); + } + } + } + } + + //assert(!i->is_processed); + i->is_processed = 1; + + if (!i->is_tree_root) + { + j = ARC_HEAD(i->match); + //assert(!j->is_processed); + j->is_processed = 1; + if (j->is_blossom) + { + a = ARC_TO_EDGE_PTR(i->match); + REAL tmp = a->slack; a->slack = j->y; j->y = tmp; + t->pq_blossoms.Add(a); + } + } + + if (a_augment) Augment(a_augment); + + stat.grow_count ++; +} + + + +void PerfectMatching::GrowTree(Node* r, bool new_subtree) +{ + //assert(r->flag == 0); + + Node* i = r; + Node* j; + Node* stop = r->tree_sibling_next; + if (new_subtree && r->first_tree_child) stop = r->first_tree_child; + Edge* a; + EdgeIterator I; + int dir; + Tree* t = r->tree; + REAL eps = t->eps; + int tree_num0 = tree_num; + + while ( 1 ) + { + if (!i->is_tree_root) + { + // process "-" node + i = ARC_HEAD(i->match); + FOR_ALL_EDGES(i, a, dir, I) + { + GET_OUTER_HEAD(a, dir, j); + + if (j->flag == 2) a->slack -= eps; + else + { + if (j->flag == 0 && j->is_processed) + { + if (!PriorityQueue::isReset(a)) j->tree->pq0.Remove(a, pq_buf); + a->slack -= eps; + if (j->tree != t) + { + if (!j->tree->pq_current) AddTreeEdge(t, j->tree); + j->tree->pq_current->pq01[1-j->tree->dir_current].Add(a); + } + } + else a->slack -= eps; + } + } + i = ARC_HEAD(i->match); + } + // process "+" node + GrowNode(i); + if (tree_num != tree_num0) break; + + if (i->first_tree_child) i = i->first_tree_child; + else + { + while (i != r && !i->tree_sibling_next) { i = ARC_HEAD(i->match); GET_TREE_PARENT(i, i); } + i = i->tree_sibling_next; + } + if (i == stop) break; + } +} + +void PerfectMatching::Solve(bool finish) +{ + Node* i; + Node* j; + Node* r; + Node* r2; + Node* r3 = NULL; // initialize to prevent compiler warning + PriorityQueue::Item* q; + Edge* a; + Tree* t; + Tree* t2; + TreeEdge* e; + TreeEdgeIterator T; + int dir; + REAL eps; + + double start_time = get_time(); + + if (IS_INT) + { + if (options.dual_greedy_update_option == 2) + { + printf("Fixed eps approach can only be used with floating point REAL!\n"); + printf("Change REAL to double in PerfectMatching.h and recompile\n"); + exit(1); + } + if (options.dual_LP_threshold > 0) + { + printf("LP approach can only be used with floating point REAL!\n"); + printf("Change REAL to double in PerfectMatching.h and recompile\n"); + exit(1); + } + } + if (options.verbose) { printf("perfect matching with %d nodes and %d edges\n", node_num, edge_num); fflush(stdout); } + + if (first_solve) + { + if (options.verbose) { printf(" starting init..."); fflush(stdout); } + if (options.fractional_jumpstart) InitGlobal(); + else InitGreedy(); + if (options.verbose) printf("done [%.3f secs]. ", get_time() - start_time); + first_solve = false; + } + else if (options.verbose) printf(" solving updated problem. "); + + if (options.verbose) { printf("%d trees\n .", tree_num); fflush(stdout); } + + memset(&stat, 0, sizeof(Stat)); + + /////////////////////////////////////////////////////// + // first pass - initialize auxiliary graph // + /////////////////////////////////////////////////////// + + for (r=nodes[node_num].tree_sibling_next; r; r=r->tree_sibling_next) + { + //assert(!r->is_processed); + t = r->tree; + //assert(!t->first[0] && !t->first[1]); + + EdgeIterator I; + FOR_ALL_EDGES(r, a, dir, I) + { + j = a->head[dir]; + if (j->flag == 2) t->pq0.Add(a); + else if (j->is_processed) + { + //assert(j->flag == 0); + if (!j->tree->pq_current) AddTreeEdge(t, j->tree); + j->tree->pq_current->pq00.Add(a); + } + } + r->is_processed = 1; + FOR_ALL_TREE_EDGES(t, e, dir) e->head[dir]->pq_current = NULL; + } + + /////////////////////////////////////////////////////// + // main loop // + /////////////////////////////////////////////////////// + + while ( 1 ) + { + int tree_num0 = tree_num; + Stat stat0 = stat; + REAL delta = 0; + + for (r=nodes[node_num].tree_sibling_next; r; ) + { + r2 = r->tree_sibling_next; + if (r2) r3 = r2->tree_sibling_next; + t = r->tree; + + int tree_num1 = tree_num; + + ////////////////////////////////////////////////////////////////////// + // step 1 - traversing auxiliary graph, setting pq_current pointers // + ////////////////////////////////////////////////////////////////////// + t->pq_current = t; + if (options.update_duals_before) + { + eps = PM_INFTY; + Edge* a_augment = NULL; + REAL eps_augment = PM_INFTY; + if ((q=t->pq0.GetMin())) eps = q->slack; + if ((q=t->pq_blossoms.GetMin()) && eps > q->slack) eps = q->slack; + while ((q=t->pq00.GetMin())) + { + if (ProcessEdge00((Edge*)q, false)) break; + t->pq00.Remove(q, pq_buf); + } + if (q && 2*eps > q->slack) eps = q->slack/2; + FOR_ALL_TREE_EDGES_X(t, e, dir, T) + { + t2 = e->head[dir]; + t2->pq_current = e; + t2->dir_current = dir; + if ((q=e->pq00.GetMin()) && (!a_augment || eps_augment > q->slack-t2->eps)) { a_augment = (Edge*)q; eps_augment = q->slack-t2->eps; } + if ((q=e->pq01[dir].GetMin()) && eps > q->slack+t2->eps) eps = q->slack+t2->eps; + } + if (eps > eps_augment) eps = eps_augment; + if (eps > t->eps) + { + delta += eps - t->eps; + t->eps = eps; + } + if (a_augment && eps_augment <= t->eps) Augment(a_augment); + } + else + { + FOR_ALL_TREE_EDGES_X(t, e, dir, T) + { + t2 = e->head[dir]; + t2->pq_current = e; + t2->dir_current = dir; + + if ((q=e->pq00.GetMin()) && (q->slack - t->eps <= t2->eps)) + { + Augment((Edge*)q); + break; + } + } + } + + ///////////////////////////////// + // step 2 - growing tree // + ///////////////////////////////// + eps = t->eps; + REAL twice_eps = 2*eps; + + while ( tree_num1 == tree_num ) + { + if ((q=t->pq0.GetMin()) && q->slack <= t->eps) + { + a = (Edge*)q; + dir = (a->head[1]->flag == 2 && a->head[1]->is_outer) ? 1 : 0; + GET_OUTER_HEAD(a, 1-dir, i); + j = a->head[dir]; + //assert(i->flag==0 && j->flag==2 && i->is_outer && j->is_outer && i->tree==t); + + j->flag = 1; + j->tree = i->tree; + j->tree_parent = EDGE_DIR_TO_ARC(a, 1-dir); + j->y += eps; + j = ARC_HEAD(j->match); + j->y -= eps; + ADD_TREE_CHILD(i, j); + + GrowTree(j, true); + } + else if ((q=t->pq00.GetMin()) && q->slack <= twice_eps) + { + t->pq00.Remove(q, pq_buf); + a = (Edge*)q; + if (ProcessEdge00(a)) Shrink(a); + } + else if ((q=t->pq_blossoms.GetMin()) && q->slack <= eps) + { + t->pq_blossoms.Remove(q, pq_buf); + a = (Edge*)q; + j = (a->head[0]->flag == 1) ? a->head[0] : a->head[1]; + REAL tmp = a->slack; a->slack = j->y; j->y = tmp; + Expand(j); + } + else break; + } + + /////////////////////////////////////////////////////////////////////// + // step 3 - traversing auxiliary graph, clearing pq_current pointers // + /////////////////////////////////////////////////////////////////////// + if ( tree_num1 == tree_num ) + { + t->pq_current = NULL; + if (options.update_duals_after) + { + eps = PM_INFTY; + Edge* a_augment = NULL; + REAL eps_augment = PM_INFTY; + if ((q=t->pq0.GetMin())) eps = q->slack; + if ((q=t->pq_blossoms.GetMin()) && eps > q->slack) eps = q->slack; + while ((q=t->pq00.GetMin())) + { + if (ProcessEdge00((Edge*)q, false)) break; + t->pq00.Remove(q, pq_buf); + } + if (q && 2*eps > q->slack) eps = q->slack/2; + FOR_ALL_TREE_EDGES(t, e, dir) + { + t2 = e->head[dir]; + e->head[dir]->pq_current = NULL; + if ((q=e->pq00.GetMin()) && (!a_augment || eps_augment > q->slack-t2->eps)) { a_augment = (Edge*)q; eps_augment = q->slack-t2->eps; } + if ((q=e->pq01[dir].GetMin()) && eps > q->slack+t2->eps) eps = q->slack+t2->eps; + } + if (eps > eps_augment) eps = eps_augment; + bool progress = false; + if (eps > t->eps) + { + delta += eps - t->eps; + t->eps = eps; + progress = true; + } + if (a_augment && eps_augment <= t->eps) Augment(a_augment); + else if (progress && tree_num >= options.single_tree_threshold*node_num) + { + // continue with the same tree + r = t->root; + continue; + } + } + else + { + FOR_ALL_TREE_EDGES(t, e, dir) e->head[dir]->pq_current = NULL; + } + } + + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + + r = r2; + if (r && !r->is_tree_root) r = r3; + } + + if (tree_num == 0) break; + + if ( tree_num == tree_num0 ) + //&& stat.grow_count == stat0.grow_count + //&& stat.shrink_count == stat0.shrink_count + //&& stat.expand_count == stat0.expand_count ) + { + if (!UpdateDuals()) + { + if (!IS_INT && delta <= PM_THRESHOLD) // for numerical stability + { + //CommitEps(); + int dual_greedy_update_option = options.dual_greedy_update_option; + options.dual_greedy_update_option = 2; + UpdateDuals(); + options.dual_greedy_update_option = dual_greedy_update_option; + } + } + } + } + + if (finish) Finish(); + + if (options.verbose) + { + printf("\ndone [%.3f secs]. %d grows, %d expands, %d shrinks\n", get_time()-start_time, stat.grow_count, stat.expand_count, stat.shrink_count); + printf(" expands: [%.3f secs], shrinks: [%.3f secs], dual updates: [%.3f secs]\n", stat.expand_time, stat.shrink_time, stat.dual_time); + fflush(stdout); + } +} + + + diff --git a/src/blossom5/PMrepair.cpp b/src/blossom5/PMrepair.cpp new file mode 100644 index 0000000..770c88a --- /dev/null +++ b/src/blossom5/PMrepair.cpp @@ -0,0 +1,431 @@ +#include +#include +#include +#include "blossom5/PMimplementation.h" + + +struct PerfectMatching::LCATreeX : LCATree +{ + LCATreeX(int size) : LCATree(size) { rev_mapping = new Node*[size]; } + ~LCATreeX() { delete [] rev_mapping; } + Node** rev_mapping; +}; + +void PerfectMatching::StartUpdate() +{ + Node* i0; + Node* i; + Node* j; + Node* b; + + while ((i=removed_first)) + { + removed_first = i->tree_sibling_next; + blossoms->Delete(i); + removed_num --; + } + + Edge* a; + Edge* selfloop_first = NULL; + Edge* selfloop_last = NULL; + + for (i0=nodes; i0is_processed = 0; + if (i0->is_outer) continue; + + i0->is_tree_root = 0; + i0->blossom_ptr = NULL; + i = i0; + while ( 1 ) + { + j = i->blossom_parent; + j->is_processed = 0; + if (j->is_outer) { j->first_tree_child = i; break; } + if (j->is_marked) break; + if ((a=j->blossom_selfloops)) + { + if (selfloop_last) selfloop_last->next[1] = a; + else selfloop_first = a; + selfloop_last = a; + a->next[1] = NULL; + } + j->blossom_ptr = i; + i = j; + } + b = (i->blossom_parent->is_outer) ? i->blossom_parent : i->blossom_parent->blossom_grandparent; +#ifdef LCA_REPAIRS + if (!b->is_marked) + { + b->lca_size = 1; + b->is_marked = 1; + } +#endif + while ( 1 ) + { +#ifdef LCA_REPAIRS + b->lca_size ++; +#endif + ARC_TO_EDGE_PTR(i->blossom_sibling)->y_saved = i->y; + i->y += i->blossom_parent->y; + if (!i->is_blossom) break; + i->is_marked = 1; + j = i; + i = i->blossom_ptr; + j->blossom_grandparent = b; + } + i->blossom_grandparent = b; + } + +#ifdef LCA_REPAIRS + for (i0=nodes; i0is_outer) continue; + b = i0->blossom_grandparent; + if (!b->is_marked) continue; + b->is_marked = 0; + LCATreeX* lca = new LCATreeX(b->lca_size); + b->blossom_ptr = b->first_tree_child; + i = b; + while ( 1 ) + { + if (i->blossom_ptr) i = i->blossom_ptr; + else + { + while ( 1 ) + { + if (i->is_outer) break; + i->lca_preorder = lca->Add(i, i->blossom_parent); + lca->rev_mapping[i->lca_preorder] = i; + i = ARC_HEAD(i->blossom_sibling); + if (i != i->blossom_parent->blossom_ptr) break; + i = i->blossom_parent; + } + if (i->is_outer) + { + lca->AddRoot(i); + break; + } + } + } + b->lca = lca; + } +#endif + + while ((a=selfloop_first)) + { + selfloop_first = a->next[1]; + do + { + Edge* a_next = a->next[0]; + +#ifdef LCA_REPAIRS + int _i = a->head0[1]->lca_preorder; + int _j = a->head0[0]->lca_preorder; + Node* b = a->head0[1]->blossom_grandparent; + b->lca->GetPenultimateNodes(_i, _j); + i = b->lca->rev_mapping[_i]; + j = b->lca->rev_mapping[_j]; +#else + GetRealEndpoints(a, i, j); +#endif + ADD_EDGE(i, a, 0); + ADD_EDGE(j, a, 1); + a->slack -= 2*i->blossom_eps; + a = a_next; + } while ( a ); + } + + /* + for (i0=nodes; i0is_outer) continue; + b = i0->blossom_grandparent; + if (b->lca) + { + delete b->lca; + b->lca = NULL; + } + } + */ + + nodes[node_num].first_tree_child = NULL; +} + +void PerfectMatching::FinishUpdate() +{ + Node* i0; + Node* i; + Node* j; + Edge* a; + EdgeIterator I; + int dir; + Tree* t; + + for (i0=nodes; i0is_outer) continue; + +#ifdef LCA_REPAIRS + if (i0->blossom_grandparent->lca) + { + delete i0->blossom_grandparent->lca; + i0->blossom_grandparent->lca = NULL; + } +#endif + + ////////////////////////////////////////////////////////////// + if (!i0->blossom_grandparent->is_removed) + { + i = i0; + do + { + i->y = ARC_TO_EDGE_PTR(i->blossom_sibling)->y_saved; + i->is_marked = 0; + i->blossom_selfloops = NULL; + i = i->blossom_parent; + } while (i->is_marked); + continue; + } + ////////////////////////////////////////////////////////////// + + i = i0->blossom_parent; + while ( 1 ) + { + if (i->is_removed && !i->is_outer) break; + REAL y_parent = (i->is_outer) ? 0 : i->blossom_parent->y; + for (dir=0; dir<2; dir++) + { + if (!i->first[dir]) continue; + i->first[dir]->prev[dir]->next[dir] = NULL; + Edge* a_next; + for (a=i->first[dir]; a; a=a_next) + { + a_next = a->next[dir]; + j = a->head0[1-dir]; + ADD_EDGE(j, a, dir); + a->slack += j->blossom_parent->y - y_parent; + } + i->first[dir] = NULL; + } + if (i->is_removed) break; + + j = i->blossom_parent; + i->is_removed = 1; + i->tree_sibling_next = removed_first; + removed_first = i; + i = j; + } + i0->y = ARC_TO_EDGE_PTR(i0->blossom_sibling)->y_saved; + i0->is_outer = 1; + i0->flag = 2; + i0->is_tree_root = 1; + } + + Node* blossom_list = nodes[node_num].first_tree_child; + + + + for (i=nodes; iis_tree_root) continue; + i->first_tree_child = nodes[node_num].first_tree_child; + nodes[node_num].first_tree_child = i; + REAL slack_min = PM_INFTY; + FOR_ALL_EDGES(i, a, dir, I) + { + if (slack_min > a->slack) slack_min = a->slack; + } + i->y += slack_min; + FOR_ALL_EDGES(i, a, dir, I) a->slack -= slack_min; + } + + tree_num = 0; + for (i=nodes[node_num].first_tree_child; i!=blossom_list; i=i->first_tree_child) + { + tree_num ++; + if (!i->is_tree_root) continue; + FOR_ALL_EDGES(i, a, dir, I) + { + j = a->head[dir]; + if (a->slack <= 0 && j->is_tree_root) + { + i->is_tree_root = j->is_tree_root = 0; + i->match = EDGE_DIR_TO_ARC(a, dir); + j->match = EDGE_DIR_TO_ARC(a, 1-dir); + tree_num -= 2; + break; + } + } + } + for ( ; i; i=i->first_tree_child) + { + if (i->is_removed) { i->is_tree_root = 0; continue; } + tree_num ++; + } + + if (tree_num > tree_num_max) + { + if (trees) free(trees); + tree_num_max = tree_num; + trees = (Tree*) malloc(tree_num_max*sizeof(Tree)); + } + t = trees; + + Node* last_root = &nodes[node_num]; + Node* i_next; + for (i=nodes; i; i=i_next) + { + if (!i->is_blossom) i_next = (ifirst_tree_child; + if (!i->is_tree_root) continue; + + i->flag = 0; + i->first_tree_child = NULL; + i->tree_sibling_prev = last_root; + last_root->tree_sibling_next = i; + last_root = i; + i->tree = t; + t->root = i; + t->eps = 0; + t->first[0] = t->first[1] = NULL; + t->pq_current = NULL; + t->pq00.Reset(); + t->pq0.Reset(); + t->pq_blossoms.Reset(); + t ++; + } + + assert(t == trees + tree_num); + last_root->tree_sibling_next = NULL; + + while ((i=removed_first)) + { + removed_first = i->tree_sibling_next; + blossoms->Delete(i); + blossom_num --; + } +} + +PerfectMatching::REAL PerfectMatching::GetTwiceSum(NodeId i) +{ + assert(i>=0 && ihead0[dir]; + if (i->is_outer) + { + if (!i->is_tree_root) + { + i->is_tree_root = 1; + i = ARC_HEAD(i->match); + assert(!i->is_tree_root && i->is_outer); + i->is_tree_root = 1; + if (i->is_blossom) + { + i->first_tree_child = nodes[node_num].first_tree_child; + nodes[node_num].first_tree_child = i; + } + } + return; + } + if (i->blossom_grandparent->is_removed) return; + } + + Node* b = i->blossom_grandparent; + assert(b->is_outer); + + if (!b->is_tree_root) + { + b->is_tree_root = 1; + i = ARC_HEAD(b->match); + assert(!i->is_tree_root && i->is_outer); + i->is_tree_root = 1; + if (i->is_blossom) + { + i->first_tree_child = nodes[node_num].first_tree_child; + nodes[node_num].first_tree_child = i; + } + } + + b->is_removed = 1; + b->tree_sibling_next = removed_first; + removed_first = b; +} + +PerfectMatching::EdgeId PerfectMatching::AddNewEdge(NodeId _i, NodeId _j, REAL cost, bool do_not_add_if_positive_slack) +{ + assert(_i>=0 && _i=0 && _j= edge_num_max) ReallocateEdges(); + Node* i = nodes + _i; + Node* j = nodes + _j; + Edge* a = edges + edge_num; + + a->slack = cost*COST_FACTOR; + a->head0[0] = j; + a->head0[1] = i; + Node* bi = (i->is_outer) ? i : i->blossom_grandparent; + Node* bj = (j->is_outer) ? j : j->blossom_grandparent; + if (bi == bj) + { +#ifdef LCA_REPAIRS + int _i = i->lca_preorder; + int _j = j->lca_preorder; + bi->lca->GetPenultimateNodes(_i, _j); + i = bi->lca->rev_mapping[_i]; + j = bi->lca->rev_mapping[_j]; +#else + GetRealEndpoints(a, i, j); +#endif + a->slack += i->blossom_parent->y + j->blossom_parent->y; + } + else + { + i = bi; + j = bj; + } + a->slack -= a->head0[0]->y + a->head0[1]->y; + + if (a->slack >= 0 && do_not_add_if_positive_slack) return -1; + + ADD_EDGE(i, a, 0); + ADD_EDGE(j, a, 1); + PriorityQueue::ResetItem(a); + + if (a->slack < 0) + { + ProcessNegativeEdge(a); + } + + return edge_num ++; +} + +void PerfectMatching::UpdateCost(EdgeId e, REAL delta_cost) +{ + assert(e>=0 && eslack += delta_cost*COST_FACTOR; + if (a->slack == 0) return; + if (a->slack > 0) + { + Node* i = a->head[1]; + Node* j = a->head[0]; + if (i->is_outer) + { + if (ARC_TO_EDGE_PTR(i->match) != a && ARC_TO_EDGE_PTR(j->match) != a) return; + } + else + { + if (ARC_TO_EDGE_PTR(i->blossom_sibling) != a && ARC_TO_EDGE_PTR(j->blossom_sibling) != a) return; + } + } + ProcessNegativeEdge(a); +} + diff --git a/src/blossom5/PMshrink.cpp b/src/blossom5/PMshrink.cpp new file mode 100644 index 0000000..0417a89 --- /dev/null +++ b/src/blossom5/PMshrink.cpp @@ -0,0 +1,318 @@ +#include +#include +#include +#include "blossom5/PMimplementation.h" + + +PerfectMatching::Node* PerfectMatching::FindBlossomRoot(Edge* a0) +{ + Node* i; + Node* j; + Node* _i[2]; + Node* r; + int branch; + + _i[0] = ARC_HEAD(a0); + _i[1] = ARC_TAIL(a0); + branch = 0; + while ( 1 ) + { + if (_i[branch]->is_marked) + { + r = _i[branch]; + j = _i[1-branch]; + break; + } + _i[branch]->is_marked = 1; + if (_i[branch]->is_tree_root) + { + j = _i[branch]; + i = _i[1-branch]; + while (!i->is_marked) + { + i->is_marked = 1; + i = ARC_HEAD(i->match); + GET_TREE_PARENT(i, i); + } + r = i; + break; + } + i = ARC_HEAD(_i[branch]->match); + GET_TREE_PARENT(i, _i[branch]); + branch = 1 - branch; + } + i = r; + while ( i != j ) + { + i = ARC_HEAD(i->match); + i = ARC_HEAD(i->tree_parent); + i->is_marked = 0; + } + // clear is_marked and is_outer + i = ARC_HEAD(a0); + while (i != r) + { + i->is_marked = 0; + i->is_outer = 0; + i = ARC_HEAD(i->match); + i->is_outer = 0; + i = ARC_HEAD(i->tree_parent); + } + i = ARC_TAIL(a0); + while (i != r) + { + i->is_marked = 0; + i->is_outer = 0; + i = ARC_HEAD(i->match); + i->is_outer = 0; + i = ARC_HEAD(i->tree_parent); + } + r->is_marked = 0; + r->is_outer = 0; + + return r; +} + + +void PerfectMatching::Shrink(Edge* a0) +{ + //assert(a0->head[0]->is_outer && a0->head[1]->is_outer); + //assert(a0->head[0]->flag == 0 && a0->head[1]->flag == 0); + + double start_time = get_time(); + + int branch, dir; + Node* r; + Node* i; + Node* j; + Edge* a; + Edge** a_inner_ptr; + Arc* a_prev; + Node* b = blossoms->New(); + Edge* a_augment = NULL; + Edge* b_match; + + b->first[0] = b->first[1] = NULL; + + // set is_outer=0 for all nodes in the blossom + r = FindBlossomRoot(a0); + Tree* t = r->tree; + REAL eps = t->eps; + + b->first_tree_child = NULL; + i = ARC_HEAD(a0); + branch = 0; + while ( 1 ) + { + if (i == r && branch) break; + i->is_marked = 1; + if (i == r) + { + branch = 1; + i = ARC_TAIL(a0); + continue; + } + + // remove i from the list of children + REMOVE_FROM_TREE(i); + + // move children of i to the list of children of b + if (i->first_tree_child) + { + j = i->first_tree_child; + if (!b->first_tree_child) b->first_tree_child = j; + else + { + Node* j_last = j->tree_sibling_prev; + j->tree_sibling_prev = b->first_tree_child->tree_sibling_prev; + b->first_tree_child->tree_sibling_prev->tree_sibling_next = j; + b->first_tree_child->tree_sibling_prev = j_last; + } + } + + // go to parent + i = ARC_HEAD(i->match); + i->is_marked = 1; + if (i->is_blossom) + { + a = ARC_TO_EDGE_PTR(i->match); + t->pq_blossoms.Remove(a, pq_buf); + REAL tmp = a->slack; a->slack = i->y; i->y = tmp; + } + i = ARC_HEAD(i->tree_parent); + } + + // move children of r to the list of children of b + if (i->first_tree_child) + { + j = i->first_tree_child; + if (!b->first_tree_child) b->first_tree_child = j; + else + { + Node* j_last = j->tree_sibling_prev; + j->tree_sibling_prev = b->first_tree_child->tree_sibling_prev; + b->first_tree_child->tree_sibling_prev->tree_sibling_next = j; + b->first_tree_child->tree_sibling_prev = j_last; + } + } + + // init b + b->is_removed = 0; + b->is_outer = 1; + b->flag = 0; + b->is_blossom = 1; + b->is_tree_root = r->is_tree_root; + b->is_processed = 1; + b->tree = t; + b->y = -eps; + b->is_marked = 0; + + // replace r with b in the tree + b->tree_sibling_prev = r->tree_sibling_prev; + b->tree_sibling_next = r->tree_sibling_next; + Node* b_parent = NULL; + if (!b->is_tree_root) + { + b_parent = ARC_HEAD(r->match); GET_TREE_PARENT(b_parent, b_parent); + } + if (b->tree_sibling_prev->tree_sibling_next) b->tree_sibling_prev->tree_sibling_next = b; + else b_parent->first_tree_child = b; + if (b->tree_sibling_next) b->tree_sibling_next->tree_sibling_prev = b; + else if (b_parent) b_parent->first_tree_child->tree_sibling_prev = b; + + if (b->is_tree_root) + { + b->tree->root = b; + b_match = NULL; + } + else + { + b->match = r->match; + b_match = ARC_TO_EDGE_PTR(b->match); + } + REAL b_match_slack = 0; // initialize to prevent compiler warning + if (b_match && ARC_HEAD(b->match)->is_blossom) + { + b_match_slack = b_match->slack; + b_match->slack = ARC_HEAD(b->match)->y; + } + + // second pass over nodes in the blossom + branch = 0; + a_prev = EDGE_DIR_TO_ARC(a0, 0); + i = ARC_HEAD(a_prev); + while ( 1 ) + { + // update Arc::next and Arc::head pointers + if (i->flag == 0) i->y += eps; + else i->y -= eps; + i->is_processed = 0; + + if (i->flag == 1) + { + Edge* a_prev; + for (dir=0; dir<2; dir++) + if (i->first[dir]) + { + for (a_inner_ptr=&i->first[dir], a=*a_inner_ptr, a_prev=a->prev[dir], a_prev->next[dir]=NULL; a; a=*a_inner_ptr) + { + Node* j0 = a->head[dir]; + for (j=j0; !j->is_outer && !j->is_marked; j = j->blossom_parent) {} + if (j != j0) { /*assert(j->flag == 0);*/ int dir_rev = 1 - dir; MOVE_EDGE(j0, j, a, dir_rev); } + if (j->is_marked) // "inner" arc + { + a_inner_ptr = &a->next[dir]; + a->prev[dir] = a_prev; + a_prev = a; + + if (j->flag == 1) a->slack += eps; + } + else // "boundary" arc + { + *a_inner_ptr = a->next[dir]; + ADD_EDGE(b, a, dir); + + if (j->flag == 0 && j->tree != t) + { + j->tree->pq_current->pq01[1-j->tree->dir_current].Remove(a, pq_buf); + if (a->slack + eps <= j->tree->eps) a_augment = a; + } + a->slack += 2*eps; + if (j->flag == 2) t->pq0.Add(a); + else if (j->flag == 0) + { + if (!j->tree->pq_current) AddTreeEdge(t, j->tree); + j->tree->pq_current->pq00.Add(a); + } + else if (j->tree != t) + { + if (!j->tree->pq_current) AddTreeEdge(t, j->tree); + j->tree->pq_current->pq01[j->tree->dir_current].Add(a); + } + } + } + if (i->first[dir]) + { + a_prev->next[dir] = i->first[dir]; + i->first[dir]->prev[dir] = a_prev; + } + } + } + + Arc* a_next = (i->flag == 0) ? i->match : i->tree_parent; + i->blossom_parent = b; + i->match = NULL; + i->blossom_grandparent = b; + i->blossom_selfloops = NULL; + if (branch == 0) + { + i->blossom_sibling = a_next; + if (i == r) + { + branch = 1; + a_prev = ARC_REV(a0); + i = ARC_HEAD(a_prev); + if (i == r) break; + } + else + { + a_prev = i->blossom_sibling; + i = ARC_HEAD(a_prev); + } + } + else + { + i->blossom_sibling = ARC_REV(a_prev); + a_prev = a_next; + i = ARC_HEAD(a_prev); + if (i == r) break; + } + } + i->blossom_sibling = ARC_REV(a_prev); + r->is_tree_root = 0; + + for (i=ARC_HEAD(r->blossom_sibling); ; i = ARC_HEAD(i->blossom_sibling)) + { + i->is_marked = 0; + i->blossom_eps = eps; + if (i == r) break; + } + + if (b_match) + { + if (ARC_HEAD(b->match)->is_blossom) + { + b_match->slack = b_match_slack; + } + dir = ARC_TO_EDGE_DIR(b->match); + //assert(b_match->head[1-dir] == r); + MOVE_EDGE(r, b, b_match, dir); + } + + stat.shrink_count ++; + blossom_num ++; + stat.shrink_time += get_time() - start_time; + + if (a_augment) Augment(a_augment); +} + diff --git a/src/blossom5/PQ.h b/src/blossom5/PQ.h new file mode 100644 index 0000000..42f9221 --- /dev/null +++ b/src/blossom5/PQ.h @@ -0,0 +1,396 @@ +/* + PQ.h - implements pairing heaps priority queue (with multipass 'delete min') + + Copyright 2008 Vladimir Kolmogorov (vnk@adastral.ucl.ac.uk) + + This software can be used for research purposes only. Commercial use is prohibited. + Public redistribution of the code or its derivatives is prohibited. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef HFKSJHFKJHARBABDAKFAF +#define HFKSJHFKJHARBABDAKFAF + +// exactly one flag must be defined +//#define PQ_MULTIPASS +#define PQ_INTERLEAVED_MULTIPASS + +#include + +template class PriorityQueue +{ +public: + struct Item + { + REAL slack; + + Item* parentPQ; + union + { + struct + { + Item* leftPQ; + Item* rightPQ; + }; + REAL y_saved; // used in repairs + }; + }; + static void* AllocateBuf(); + static void DeallocateBuf(void* buf); + + static void ResetItem(Item* i); + static bool isReset(Item* i); + + ////////////////////////////////////////////////////////// + + void Reset(); + void Add(Item* i); +#define Remove(i, buf) _Remove(i) + void _Remove(Item* i); + void Decrease(Item* i_old, Item* i_new, void* buf); + Item* GetMin(); + + ////////////////////////////////////////////////////////// + + void Update(REAL delta); + void Merge(PriorityQueue& dest); + + // traversing items in the order they are stored (irrespective of slack). + // The caller must go through all items, no other member functions can be called during the scan. + Item* GetAndResetFirst(); + Item* GetAndResetNext(); + + Item* GetFirst(); + Item* GetNext(Item* i); + + ////////////////////////////////////////////////////////// + +private: + struct Buf + { + }; + Item* rootPQ; + void RemoveRoot(); +}; + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// + +template inline void* PriorityQueue::AllocateBuf() +{ + return NULL; +} + +template inline void PriorityQueue::DeallocateBuf(void* _buf) +{ +} + +template inline void PriorityQueue::ResetItem(Item* i) +{ + i->parentPQ = NULL; +} + +template inline bool PriorityQueue::isReset(Item* i) +{ + return (i->parentPQ == NULL); +} + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// + +template inline void PriorityQueue::Reset() +{ + rootPQ = NULL; +} + +/* +template inline void PriorityQueue::RemoveRoot() +{ + Item* r = rootPQ; + PriorityQueue pq; + pq.rootPQ = rootPQ; + rootPQ = NULL; + Item* i; + for (i=pq.GetAndResetFirst(); i; i=pq.GetAndResetNext()) + { + if (i != r) Add(i); + } + r->parentPQ = NULL; +} +*/ + +// sets i = merge(i, j). Ignores parentPQ and rightPQ for i and j. +#define MERGE_PQ(i, j)\ + {\ + if (i->slack <= j->slack)\ + {\ + j->rightPQ = i->leftPQ;\ + if (j->rightPQ) j->rightPQ->parentPQ = j;\ + j->parentPQ = i;\ + i->leftPQ = j;\ + }\ + else\ + {\ + i->rightPQ = j->leftPQ;\ + if (i->rightPQ) i->rightPQ->parentPQ = i;\ + i->parentPQ = j;\ + j->leftPQ = i;\ + i = j;\ + }\ + } + +template inline void PriorityQueue::RemoveRoot() +{ + Item* i = rootPQ->leftPQ; + rootPQ->parentPQ = NULL; + if (i) + { +#ifdef PQ_MULTIPASS + while ( i->rightPQ ) + { + Item** prev_ptr = &rootPQ; + while ( 1 ) + { + if (i->rightPQ) + { + Item* j = i->rightPQ; + Item* next = j->rightPQ; + MERGE_PQ(i, j); + *prev_ptr = i; + if (!next) { i->rightPQ = NULL; break; } + prev_ptr = &i->rightPQ; + i = next; + } + else + { + *prev_ptr = i; + i->rightPQ = NULL; + break; + } + } + i = rootPQ; + } +#endif + +#ifdef PQ_INTERLEAVED_MULTIPASS + while ( i->rightPQ ) + { + Item* prev = NULL; + while ( i ) + { + Item* next; + if (i->rightPQ) + { + Item* j = i->rightPQ; + next = j->rightPQ; + MERGE_PQ(i, j); + } + else next = NULL; + i->rightPQ = prev; + prev = i; + i = next; + } + i = prev; + } +#endif + i->parentPQ = i; + } + rootPQ = i; +} + +template inline void PriorityQueue::Add(Item* i) +{ + if (!rootPQ) + { + rootPQ = i; + i->parentPQ = i; + i->leftPQ = i->rightPQ = NULL; + } + else if (i->slack <= rootPQ->slack) + { + rootPQ->parentPQ = i; + i->leftPQ = rootPQ; + i->rightPQ = NULL; + rootPQ = i; + i->parentPQ = i; + } + else + { + i->leftPQ = NULL; + i->rightPQ = rootPQ->leftPQ; + if (i->rightPQ) i->rightPQ->parentPQ = i; + rootPQ->leftPQ = i; + i->parentPQ = rootPQ; + } +} + + +template inline void PriorityQueue::_Remove(Item* i) +{ + Item* p = i->parentPQ; + if (p == i) RemoveRoot(); + else + { + if (i->rightPQ) i->rightPQ->parentPQ = p; + if (p->leftPQ == i) p->leftPQ = i->rightPQ; + else p->rightPQ = i->rightPQ; + if (i->leftPQ) + { + i->parentPQ = i; + i->rightPQ = NULL; + PriorityQueue pq; + pq.rootPQ = i; + pq.RemoveRoot(); + pq.Merge(*this); + } + else i->parentPQ = NULL; + } +} + +template inline void PriorityQueue::Decrease(Item* i_old, Item* i_new, void* _buf) +{ + if (i_old->parentPQ == i_old) + { + if (i_old != i_new) + { + rootPQ = i_new; + i_new->parentPQ = i_new; + i_new->leftPQ = i_old->leftPQ; + i_new->rightPQ = NULL; + if (i_new->leftPQ) i_new->leftPQ->parentPQ = i_new; + i_old->parentPQ = NULL; + } + } + else + { + Remove(i_old, _buf); + Add(i_new); + } +} + +template inline typename PriorityQueue::Item* PriorityQueue::GetMin() +{ + return rootPQ; +} + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// + + + +template inline void PriorityQueue::Merge(PriorityQueue& dest) +{ + if (!rootPQ) return; + if (!dest.rootPQ) dest.rootPQ = rootPQ; + else + { + if (rootPQ->slack < dest.rootPQ->slack) + { + Item* j = rootPQ; rootPQ = dest.rootPQ; dest.rootPQ = j; + } + rootPQ->rightPQ = dest.rootPQ->leftPQ; + if (rootPQ->rightPQ) rootPQ->rightPQ->parentPQ = rootPQ; + rootPQ->parentPQ = dest.rootPQ; + dest.rootPQ->leftPQ = rootPQ; + } + rootPQ = NULL; +} + + + +template inline void PriorityQueue::Update(REAL delta) +{ + if (!rootPQ) return; + + Item* i = rootPQ; + while (i->leftPQ) i = i->leftPQ; + + while ( 1 ) + { + i->slack += delta; + + if (i->rightPQ) + { + i = i->rightPQ; + while (i->leftPQ) i = i->leftPQ; + } + else + { + while ( 1 ) + { + Item* j = i; + i = i->parentPQ; + if (i == j) return; + if (i->leftPQ == j) break; + } + } + } +} + + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// + +template inline typename PriorityQueue::Item* PriorityQueue::GetAndResetFirst() +{ + if (!rootPQ) return NULL; + return GetAndResetNext(); +} + +template inline typename PriorityQueue::Item* PriorityQueue::GetAndResetNext() +{ + if (!rootPQ) return NULL; + Item* result = rootPQ; + result->parentPQ = NULL; + Item* i = rootPQ->leftPQ; + if (!i) rootPQ = result->rightPQ; + else + { + rootPQ = i; + while (i->rightPQ) i = i->rightPQ; + i->rightPQ = result->rightPQ; + } + return result; +} + +template inline typename PriorityQueue::Item* PriorityQueue::GetFirst() +{ + if (!rootPQ) return NULL; + Item* i = rootPQ; + while (i->leftPQ) i = i->leftPQ; + return i; +} + +template inline typename PriorityQueue::Item* PriorityQueue::GetNext(Item* i) +{ + if (i->rightPQ) + { + i = i->rightPQ; + while (i->leftPQ) i = i->leftPQ; + return i; + } + while ( 1 ) + { + Item* j = i; + i = i->parentPQ; + if (i == j) return NULL; + if (i->leftPQ == j) return i; + } +} + +#endif diff --git a/src/blossom5/PerfectMatching.cpp b/src/blossom5/PerfectMatching.cpp new file mode 100644 index 0000000..90f8508 --- /dev/null +++ b/src/blossom5/PerfectMatching.cpp @@ -0,0 +1,3018 @@ +#include +#include +#include +#include "blossom5/PMimplementation.h" +#include "blossom5/MinCost/MinCost.h" + + +//---------// +// Duals // +//---------// + + +void PerfectMatching::ComputeEpsGlobal() +{ + Node* r; + PriorityQueue::Item* q; + Tree* t; + Tree* t2; + TreeEdge* e; + int i, j, k, N = 0, E = 0; + + for (r=nodes[node_num].tree_sibling_next; r; r=r->tree_sibling_next) + { + t = r->tree; + t->id = N; + N += 2; + for (k=0; k<2; k++) + for (e=t->first[k]; e; e=e->next[k]) E += 6; + } + DualMinCost* m = new DualMinCost(N, E); + for (r=nodes[node_num].tree_sibling_next; r; r=r->tree_sibling_next) + { + t = r->tree; + i = t->id; + m->AddUnaryTerm(i, -1); + m->SetLowerBound(i, 0); + m->AddUnaryTerm(i+1, 1); + m->SetUpperBound(i+1, 0); + + if (t->eps_delta < PM_INFTY) + { + m->SetUpperBound(i, t->eps_delta); + m->SetLowerBound(i+1, -t->eps_delta); + } + for (e=t->first[0]; e; e=e->next[0]) + { + t2 = e->head[0]; + if (t2 == NULL) continue; + j = e->head[0]->id; + if ((q=e->pq01[0].GetMin())) + { + m->AddConstraint(j, i, q->slack - t->eps + t2->eps); + m->AddConstraint(i+1, j+1, q->slack - t->eps + t2->eps); + } + if ((q=e->pq01[1].GetMin())) + { + m->AddConstraint(i, j, q->slack - t2->eps + t->eps); + m->AddConstraint(j+1, i+1, q->slack - t2->eps + t->eps); + } + if ((q=e->pq00.GetMin())) + { + m->AddConstraint(i+1, j, q->slack - t->eps - t2->eps); + m->AddConstraint(j+1, i, q->slack - t->eps - t2->eps); + } + } + } + m->Solve(); + for (r=nodes[node_num].tree_sibling_next; r; r=r->tree_sibling_next) + { + t = r->tree; + i = t->id; + t->eps_delta = (m->GetSolution(i) - m->GetSolution(i+1))/2; + } + delete m; +} + +void PerfectMatching::ComputeEpsSingle() +{ + Node* r; + PriorityQueue::Item* q; + Tree* t; + Tree* t2; + TreeEdge* e; + REAL eps = PM_INFTY; + + for (r=nodes[node_num].tree_sibling_next; r; r=r->tree_sibling_next) + { + t = r->tree; + if (eps > t->eps_delta) eps = t->eps_delta; + for (e=t->first[0]; e; e=e->next[0]) + { + t2 = e->head[0]; + if ((q=e->pq00.GetMin()) && 2*eps > q->slack-t->eps-t2->eps) + { + eps = (q->slack-t->eps-t2->eps)/2; + } + } + } + for (r=nodes[node_num].tree_sibling_next; r; r=r->tree_sibling_next) + { + r->tree->eps_delta = eps; + } +} + + +void PerfectMatching::ComputeEpsCC() +{ + Node* r; + PriorityQueue::Item* q; + Tree* t0; + Tree* t; + Tree* t2; + Tree* t_next; + TreeEdge* e; + REAL eps, eps2; + Tree* queue_last; + int dir; + Tree* FIXED_TREE = trees-1; + int component_num = 0; + TreeEdge** e_ptr; + + for (r=nodes[node_num].tree_sibling_next; r; r=r->tree_sibling_next) + { + t0 = r->tree; + t0->next = NULL; + } + for (r=nodes[node_num].tree_sibling_next; r; r=r->tree_sibling_next) + { + t0 = r->tree; + if (t0->next) continue; + eps = t0->eps_delta; + + t0->next = queue_last = t = t0; + while ( 1 ) + { + for (dir=0; dir<2; dir++) + for (e_ptr=&t->first[dir], e=*e_ptr; e; e=*e_ptr) + { + t2 = e->head[dir]; + if (t2 == NULL) { *e_ptr = e->next[dir]; tree_edges->Delete(e); continue; } + e_ptr = &e->next[dir]; + + REAL eps00 = ((q=e->pq00.GetMin())) ? (q->slack - t->eps - t2->eps) : PM_INFTY; + if (t2->next && t2->next != FIXED_TREE) + { + if (2*eps > eps00) eps = eps00/2; + continue; + } + + REAL eps01[2]; + eps01[dir] = ((q=e->pq01[dir].GetMin())) ? (q->slack - t->eps + t2->eps) : PM_INFTY; + eps01[1-dir] = ((q=e->pq01[1-dir].GetMin())) ? (q->slack - t2->eps + t->eps) : PM_INFTY; + + if (t2->next == FIXED_TREE) eps2 = t2->eps_delta; + else if (eps01[0] > 0 && eps01[1] > 0) eps2 = 0; + else + { + queue_last->next = t2; + queue_last = t2; + t2->next = t2; + if (eps > eps00) eps = eps00; + if (eps > t2->eps_delta) eps = t2->eps_delta; + continue; + } + if (eps > eps00 - eps2) eps = eps00 - eps2; + if (eps > eps2 + eps01[dir]) eps = eps2 + eps01[dir]; + } + + if (t->next == t) break; + t = t->next; + } + for (t=t0; ; t=t_next) + { + t->eps_delta = eps; + t_next = t->next; + t->next = FIXED_TREE; + if (t_next == t) break; + } + component_num ++; + } + //printf("%d CCs ", component_num); +} + + +void PerfectMatching::ComputeEpsSCC() +{ + PriorityQueue::Item* q; + Node* r; + Tree* t0; + Tree* t; + Tree* t2; + TreeEdge* e; + TreeEdge** e_ptr; + REAL eps; + int c, dir; + + for (r=nodes[node_num].tree_sibling_next; r; r=r->tree_sibling_next) + { + t0 = r->tree; + t0->dfs_parent = NULL; + + for (dir=0; dir<2; dir++) + for (e_ptr=&t0->first[dir], e=*e_ptr; e; e=*e_ptr) + { + t2 = e->head[dir]; + if (t2 == NULL) { *e_ptr = e->next[dir]; tree_edges->Delete(e); continue; } + e_ptr = &e->next[dir]; + } + } + Tree* stack = NULL; + + // first DFS + for (r=nodes[node_num].tree_sibling_next; r; r=r->tree_sibling_next) + { + t0 = r->tree; + if (t0->dfs_parent) continue; + t = t0; + e = (t->first[0]) ? t->first[0] : t->first[1]; + t->dfs_parent = (TreeEdge*)trees; + while ( 1 ) + { + if (e == NULL) + { + t->next = stack; + stack = t; + + if (t == t0) break; + + e = t->dfs_parent; + if (t == e->head[0]) { t = e->head[1]; e = (e->next[0]) ? e->next[0] : t->first[1]; } + else { t = e->head[0]; e = e->next[1]; } + continue; + } + + if (e->head[1] == t) + { + if (e->head[0]->dfs_parent || !(q=e->pq01[0].GetMin()) || q->slack - t->eps + e->head[0]->eps > 0) { e = (e->next[0]) ? e->next[0] : t->first[1]; continue; } + t = e->head[0]; + } + else + { + if (e->head[1]->dfs_parent || !(q=e->pq01[1].GetMin()) || q->slack - t->eps + e->head[1]->eps > 0) { e = e->next[1]; continue; } + t = e->head[1]; + } + t->dfs_parent = e; + e = (t->first[0]) ? t->first[0] : t->first[1]; + } + } + + for (r=nodes[node_num].tree_sibling_next; r; r=r->tree_sibling_next) r->tree->dfs_parent = NULL; + + int component_num = 0; + while (stack) + { + t0 = stack; + stack = t0->next; + if (t0->dfs_parent) continue; + t = t0; + e = (t->first[0]) ? t->first[0] : t->first[1]; + t->dfs_parent = (TreeEdge*)trees; + while ( 1 ) + { + if (e == NULL) + { + e = t->dfs_parent; + t->dfs_parent = (TreeEdge*)((char*)trees + component_num); + if (t == t0) break; + if (t == e->head[0]) { t = e->head[1]; e = (e->next[0]) ? e->next[0] : t->first[1]; } + else { t = e->head[0]; e = e->next[1]; } + continue; + } + + if (e->head[1] == t) + { + if (e->head[0]->dfs_parent || !(q=e->pq01[1].GetMin()) || q->slack - e->head[0]->eps + t->eps > 0) { e = (e->next[0]) ? e->next[0] : t->first[1]; continue; } + t = e->head[0]; + } + else + { + if (e->head[1]->dfs_parent || !(q=e->pq01[0].GetMin()) || q->slack - e->head[1]->eps + t->eps > 0) { e = e->next[1]; continue; } + t = e->head[1]; + } + t->dfs_parent = e; + e = (t->first[0]) ? t->first[0] : t->first[1]; + } + component_num ++; + } + + Tree** array = new Tree*[component_num]; + memset(array, 0, component_num*sizeof(Tree*)); + + for (r=nodes[node_num].tree_sibling_next; r; r=r->tree_sibling_next) + { + t = r->tree; + t->id = (int)((char*)t->dfs_parent - (char*)trees); + t->next = array[t->id]; + array[t->id] = t; + } + + for (c=component_num-1; c>=0; c--) + { + eps = PM_INFTY; + for (t=array[c]; t; t=t->next) + { + if (eps > t->eps_delta) eps = t->eps_delta; + FOR_ALL_TREE_EDGES(t, e, dir) + { + t2 = e->head[dir]; + REAL eps00 = (q=e->pq00.GetMin()) ? (q->slack-t->eps-t2->eps) : PM_INFTY; + REAL eps01[2]; + eps01[dir] = ((q=e->pq01[dir].GetMin())) ? (q->slack - t->eps + t2->eps) : PM_INFTY; + eps01[1-dir] = ((q=e->pq01[1-dir].GetMin())) ? (q->slack - t2->eps + t->eps) : PM_INFTY; + if (t2->id < c) + { + if (eps > eps01[dir]) eps = eps01[dir]; + if (eps > eps00) eps = eps00; + } + else if (t2->id == c) + { + if (2*eps > eps00) eps = eps00 / 2; + } + else + { + if (eps > eps01[dir] + t2->eps_delta) eps = eps01[dir] + t2->eps_delta; + if (eps > eps00 - t2->eps_delta) eps = eps00 - t2->eps_delta; + } + } + } + for (t=array[c]; t; t=t->next) t->eps_delta = eps; + } + + delete [] array; + //printf("%d SCCs ", component_num); +} + +void PerfectMatching::CommitEps() +{ + printf("CommitEps()\n"); + Node* i; + Node* j; + Node* r; + int dir; + Edge* a; + EdgeIterator I; + Tree* t; + TreeEdge* e; + TreeEdge** e_ptr; + REAL eps, eps2; + PriorityQueue::Item* q; + + for (r=nodes[node_num].tree_sibling_next; r; r=r->tree_sibling_next) + { + t = r->tree; + eps = t->eps; + + i = r; + while ( 1 ) + { + i->y += eps; + if (!i->is_tree_root) + { + Node* i0 = i; + i = ARC_HEAD(i0->match); + if (i->is_blossom) ARC_TO_EDGE_PTR(i0->match)->slack -= eps; + else i->y -= eps; + FOR_ALL_EDGES(i, a, dir, I) + { + GET_OUTER_HEAD(a, dir, j); + + a->slack += eps; + if (j->flag == 0) a->slack -= j->tree->eps; + } + i = i0; + } + + MOVE_NODE_IN_TREE(i); + } + + t->pq0.Update(-eps); + + PriorityQueue pq00 = t->pq00; + t->pq00.Reset(); + for (q=pq00.GetAndResetFirst(); q; q=pq00.GetAndResetNext()) + { + a = (Edge*)q; + if (ProcessEdge00(a)) t->pq00.Add(a); + } + + for (e_ptr=&t->first[0], e=*e_ptr; e; e=*e_ptr) + { + if (e->head[0] == NULL) { *e_ptr = e->next[0]; tree_edges->Delete(e); continue; } + e_ptr = &e->next[0]; + + eps2 = e->head[0]->eps; + e->pq00.Update( - eps - eps2 ); + } + } + + for (r=nodes[node_num].tree_sibling_next; r; r=r->tree_sibling_next) r->tree->eps = 0; +} + +bool PerfectMatching::UpdateDuals() +{ + Node* r; + + double start_time = get_time(); + + //////////////////////////////////////////////////////////////////////////////////// + for (r=nodes[node_num].tree_sibling_next; r; r=r->tree_sibling_next) + { + Tree* t = r->tree; + PriorityQueue::Item* q; + REAL eps = PM_INFTY; + if ((q=t->pq0.GetMin())) eps = q->slack; + if ((q=t->pq_blossoms.GetMin()) && eps > q->slack) eps = q->slack; + while ((q=t->pq00.GetMin())) + { + if (ProcessEdge00((Edge*)q, false)) break; + t->pq00.Remove(q, pq_buf); + } + if (q && 2*eps > q->slack) eps = q->slack/2; + t->eps_delta = eps - t->eps; + } + + if (tree_num >= options.dual_LP_threshold*node_num) + { + if (options.dual_greedy_update_option == 0) ComputeEpsCC(); + else if (options.dual_greedy_update_option == 1) ComputeEpsSCC(); + else ComputeEpsSingle(); + } + else ComputeEpsGlobal(); + + REAL delta = 0; + for (r=nodes[node_num].tree_sibling_next; r; r=r->tree_sibling_next) + { + if (r->tree->eps_delta > 0) + { + delta += r->tree->eps_delta; + r->tree->eps += r->tree->eps_delta; + } + } + + stat.dual_time += get_time() - start_time; + + return (delta > PM_THRESHOLD); +} + + + +//----------// +// Expand // +//----------// + + +inline void PerfectMatching::ProcessSelfloop(Node* b, Edge* a) +{ + int dir; + Node* j; + Node* prev[2]; + for (dir=0; dir<2; dir++) + { + j = a->head[dir]; + GET_PENULTIMATE_BLOSSOM(j); + prev[dir] = j; + } + if (prev[0] != prev[1]) + { + ADD_EDGE(prev[0], a, 1); + ADD_EDGE(prev[1], a, 0); + a->slack -= 2*prev[0]->blossom_eps; + } + else + { + a->next[0] = prev[0]->blossom_selfloops; + prev[0]->blossom_selfloops = a; + } + +} + + + +void PerfectMatching::Expand(Node* b) +{ + assert(b->is_blossom); + assert(b->is_outer); + assert(b->flag == 1); + + double start_time = get_time(); + + Node* i; + Node* j; + Node* k; + Edge* a; + EdgeIterator I; + int dir; + ExpandTmpItem* tmp_item; + Tree* t = b->tree; + REAL eps = t->eps; + Edge* a_augment = NULL; + + GET_TREE_PARENT(b, i); + a = ARC_TO_EDGE_PTR(b->tree_parent); + dir = ARC_TO_EDGE_DIR(b->tree_parent); + + j = a->head0[1-dir]; + GET_PENULTIMATE_BLOSSOM(j); + MOVE_EDGE(b, j, a, dir); + + a = ARC_TO_EDGE_PTR(b->match); + dir = ARC_TO_EDGE_DIR(b->match); + k = a->head0[1-dir]; + GET_PENULTIMATE_BLOSSOM(k); + MOVE_EDGE(b, k, a, dir); + + i = ARC_HEAD(k->blossom_sibling); + while ( 1 ) + { + tmp_item = expand_tmp_list->New(); + tmp_item->i = i; tmp_item->blossom_parent = i->blossom_parent; tmp_item->blossom_grandparent = i->blossom_grandparent; + i->flag = 2; + + // blossom_selfloops + i->is_outer = 1; + while ((a=i->blossom_selfloops)) + { + i->blossom_selfloops = a->next[0]; + ProcessSelfloop(i, a); + } + i->is_outer = 0; + + if (i == k) break; + i->match = i->blossom_sibling; + j = ARC_HEAD(i->match); + tmp_item = expand_tmp_list->New(); + tmp_item->i = j; tmp_item->blossom_parent = j->blossom_parent; tmp_item->blossom_grandparent = j->blossom_grandparent; + j->flag = 2; + + // blossom_selfloops + j->is_outer = 1; + while ((a=j->blossom_selfloops)) + { + j->blossom_selfloops = a->next[0]; + ProcessSelfloop(j, a); + } + j->is_outer = 0; + + j->match = ARC_REV(i->match); + i = ARC_HEAD(j->blossom_sibling); + } + k->match = b->match; + i = ARC_TAIL(b->tree_parent); + Arc* aa = i->blossom_sibling; + i->flag = 1; i->tree = b->tree; i->y += b->tree->eps; + i->tree_parent = b->tree_parent; + if (i != k) + { + Node** i_ptr; + if (i->match == aa) + { + i = ARC_HEAD(i->match); + i_ptr = &j; + while ( 1 ) + { + aa = i->blossom_sibling; + i->flag = 0; i->tree = b->tree; i->y -= t->eps; + *i_ptr = i; + i_ptr = &i->first_tree_child; + i->tree_sibling_prev = i; + i->tree_sibling_next = NULL; + i = ARC_HEAD(aa); + i->flag = 1; i->tree = b->tree; i->y += t->eps; + i->tree_parent = ARC_REV(aa); + if (i == k) break; + i = ARC_HEAD(i->match); + } + *i_ptr = ARC_HEAD(k->match); + } + else + { + i = k; + j = ARC_HEAD(k->match); + do + { + i->tree_parent = i->blossom_sibling; + i->flag = 1; i->tree = b->tree; i->y += b->tree->eps; + i = ARC_HEAD(i->tree_parent); + i->flag = 0; i->tree = b->tree; i->y -= b->tree->eps; + i->first_tree_child = j; + j = i; + i->tree_sibling_prev = i; + i->tree_sibling_next = NULL; + i = ARC_HEAD(i->match); + } while ( i->flag != 1 ); + } + i = ARC_HEAD(k->match); + + j->tree_sibling_prev = i->tree_sibling_prev; + j->tree_sibling_next = i->tree_sibling_next; + if (i->tree_sibling_prev->tree_sibling_next) i->tree_sibling_prev->tree_sibling_next = j; + else ARC_HEAD(b->tree_parent)->first_tree_child = j; + if (i->tree_sibling_next) i->tree_sibling_next->tree_sibling_prev = j; + else ARC_HEAD(b->tree_parent)->first_tree_child->tree_sibling_prev = j; + + i->tree_sibling_prev = i; + i->tree_sibling_next = NULL; + } + + // go through inner arcs + i = k; + while ( 1 ) + { + // "-" node + if (i->is_blossom) + { + a = ARC_TO_EDGE_PTR(i->match); + REAL tmp = a->slack; a->slack = i->y; i->y = tmp; + t->pq_blossoms.Add(a); + } + FOR_ALL_EDGES(i, a, dir, I) + { + j = a->head[dir]; + if (j->flag != 0) a->slack -= eps; + } + i->is_processed = 1; + if (i->tree_parent == b->tree_parent) break; + i = ARC_HEAD(i->tree_parent); + // "+" node + FOR_ALL_EDGES(i, a, dir, I) + { + j = a->head[dir]; + if (j->flag == 2) + { + a->slack += eps; + t->pq0.Add(a); + } + else if (j->flag == 0 && i < j) + { + a->slack += 2*eps; + t->pq00.Add(a); + } + } + i->is_processed = 1; + i = ARC_HEAD(i->match); + } + + // go through boundary arcs + for (tmp_item=expand_tmp_list->ScanFirst(); tmp_item; tmp_item=expand_tmp_list->ScanNext()) + { + i = tmp_item->i; + j = tmp_item->blossom_parent; tmp_item->blossom_parent = i->blossom_parent; i->blossom_parent = j; + j = tmp_item->blossom_grandparent; tmp_item->blossom_grandparent = i->blossom_grandparent; i->blossom_grandparent = j; + } + for (dir=0; dir<2; dir++) + { + if (!b->first[dir]) continue; + b->first[dir]->prev[dir]->next[dir] = NULL; + + Edge* a_next; + for (a=b->first[dir]; a; a=a_next) + { + a_next = a->next[dir]; + i = a->head0[1-dir]; + GET_PENULTIMATE_BLOSSOM2(i); + ADD_EDGE(i, a, dir); + GET_OUTER_HEAD(a, dir, j); + + if (i->flag == 1) continue; + + if (j->flag == 0 && j->tree != t) j->tree->pq_current->pq01[1-j->tree->dir_current].Remove(a, pq_buf); + + if (i->flag == 2) + { + a->slack += eps; + if (j->flag == 0) j->tree->pq0.Add(a); + } + else + { + a->slack += 2*eps; + if (j->flag == 2) t->pq0.Add(a); + else if (j->flag == 0) + { + if (j->tree != t) + { + if (!j->tree->pq_current) AddTreeEdge(t, j->tree); + if (a->slack <= j->tree->eps + eps) a_augment = a; + } + j->tree->pq_current->pq00.Add(a); + } + else if (j->tree != t) + { + if (!j->tree->pq_current) AddTreeEdge(t, j->tree); + j->tree->pq_current->pq01[j->tree->dir_current].Add(a); + } + + } + } + } + for (tmp_item=expand_tmp_list->ScanFirst(); tmp_item; tmp_item=expand_tmp_list->ScanNext()) + { + i = tmp_item->i; + i->blossom_parent = tmp_item->blossom_parent; + i->blossom_grandparent = tmp_item->blossom_grandparent; + i->is_outer = 1; + } + expand_tmp_list->Reset(); + + b->tree_sibling_next = removed_first; + removed_first = b; + removed_num ++; + if (4*removed_num > node_num) FreeRemoved(); + + blossom_num --; + stat.expand_count ++; + + stat.expand_time += get_time() - start_time; + + if (a_augment) Augment(a_augment); +} + +void PerfectMatching::FreeRemoved() +{ + Node* i0; + Node* i; + for (i0=nodes; i0is_outer && !i->is_marked; i=i->blossom_parent) + { + i->is_marked = 1; + if (i->blossom_grandparent->is_removed) i->blossom_grandparent = i->blossom_parent; + } + } + for (i0=nodes; i0is_outer && i->is_marked; i=i->blossom_parent) + { + i->is_marked = 0; + } + } + + while ((i=removed_first)) + { + removed_first = i->tree_sibling_next; + blossoms->Delete(i); + removed_num --; + } + + assert(removed_num == 0); +} + + + + +//----------// +// Init // +//----------// + + + +void PerfectMatching::InitGreedy(bool allocate_trees) +{ + Node* i; + int dir; + Edge* a; + EdgeIterator I; + Tree* t = NULL; + Node* last_root = &nodes[node_num]; + REAL slack_min; + + for (i=nodes; iy = PM_INFTY; + for (a=edges; ahead[0]->y > a->slack) a->head[0]->y = a->slack; + if (a->head[1]->y > a->slack) a->head[1]->y = a->slack; + } + for (a=edges; ahead[0]; + if (!i->is_outer) + { + i->is_outer = 1; + i->y /= 2; + } + a->slack -= i->y; + i = a->head[1]; + if (!i->is_outer) + { + i->is_outer = 1; + i->y /= 2; + } + a->slack -= i->y; + } + + tree_num = node_num; + for (i=nodes; iflag == 2) continue; + slack_min = PM_INFTY; + FOR_ALL_EDGES(i, a, dir, I) if (slack_min > a->slack) slack_min = a->slack; + i->y += slack_min; + FOR_ALL_EDGES(i, a, dir, I) + { + if (a->slack <= slack_min && i->flag == 0 && a->head[dir]->flag == 0) + { + i->flag = 2; + a->head[dir]->flag = 2; + i->match = EDGE_DIR_TO_ARC(a, dir); + a->head[dir]->match = EDGE_DIR_TO_ARC(a, 1-dir); + tree_num -= 2; + } + a->slack -= slack_min; + } + } + if (allocate_trees) + { + if (tree_num > tree_num_max) + { + if (trees) free(trees); + tree_num_max = tree_num; + trees = (Tree*) malloc(tree_num_max*sizeof(Tree)); + } + t = trees; + } + for (i=nodes; iflag != 0) continue; + i->is_tree_root = 1; + i->first_tree_child = NULL; + i->tree_sibling_prev = last_root; + last_root->tree_sibling_next = i; + last_root = i; + if (allocate_trees) + { + i->tree = t; + t->root = i; + t->eps = 0; + t->first[0] = t->first[1] = NULL; + t->pq_current = NULL; + t->pq00.Reset(); + t->pq0.Reset(); + t->pq_blossoms.Reset(); + t ++; + } + } + last_root->tree_sibling_next = NULL; +} + +//////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////// + +PerfectMatching::Node* PerfectMatching::FindBlossomRootInit(Edge* a0) +{ + Node* i; + Node* j; + Node* _i[2]; + Node* r; + int branch; + + _i[0] = ARC_HEAD(a0); + _i[1] = ARC_TAIL(a0); + branch = 0; + while ( 1 ) + { + if (!_i[branch]->is_outer) + { + r = _i[branch]; + j = _i[1-branch]; + break; + } + _i[branch]->is_outer = 0; + if (_i[branch]->is_tree_root) + { + j = _i[branch]; + i = _i[1-branch]; + while (i->is_outer) + { + i->is_outer = 0; + i = ARC_HEAD(i->match); + i->is_outer = 0; + i = ARC_HEAD(i->tree_parent); + } + r = i; + break; + } + i = ARC_HEAD(_i[branch]->match); + i->is_outer = 0; + _i[branch] = ARC_HEAD(i->tree_parent); + branch = 1 - branch; + } + i = r; + while ( i != j ) + { + i = ARC_HEAD(i->match); + i->is_outer = 1; + i = ARC_HEAD(i->tree_parent); + i->is_outer = 1; + } + return r; +} + +void PerfectMatching::ShrinkInit(Edge* a0, Node* tree_root) +{ + int branch, flag; + Node* i; + Node* j; + Node* r; + Arc* a_prev; + Arc* aa; + + tree_root->flag = 2; + i = tree_root->first_tree_child; + if ( i ) + while ( 1 ) + { + ARC_HEAD(i->match)->flag = 2; + i->flag = 2; + + MOVE_NODE_IN_TREE(i); + } + + r = FindBlossomRootInit(a0); + + if ( !r->is_tree_root ) + { + j = ARC_HEAD(r->match); + j->match = aa = j->tree_parent; + i = ARC_HEAD(aa); + while ( !i->is_tree_root ) + { + j = ARC_HEAD(i->match); + i->match = ARC_REV(aa); + j->match = aa = j->tree_parent; + i = ARC_HEAD(aa); + } + i->match = ARC_REV(aa); + } + + tree_root->is_tree_root = 0; + + branch = 0; + flag = 0; + a_prev = EDGE_DIR_TO_ARC(a0, 0); + i = ARC_HEAD(a_prev); + while ( 1 ) + { + Arc* a_next = (flag == 0) ? i->match : i->tree_parent; + flag = 1 - flag; + i->flag = 0; + i->match = NULL; + if (branch == 0) + { + i->blossom_sibling = a_next; + if (i == r) + { + branch = 1; + flag = 0; + a_prev = ARC_REV(a0); + i = ARC_HEAD(a_prev); + if (i == r) break; + } + else + { + a_prev = i->blossom_sibling; + i = ARC_HEAD(a_prev); + } + } + else + { + i->blossom_sibling = ARC_REV(a_prev); + a_prev = a_next; + i = ARC_HEAD(a_prev); + if (i == r) break; + } + } + i->blossom_sibling = ARC_REV(a_prev); +} + +void PerfectMatching::ExpandInit(Node* k) +{ + Node* i = ARC_HEAD(k->blossom_sibling); + Node* j; + + while ( 1 ) + { + i->flag = 2; i->is_outer = 1; + if (i == k) break; + i->match = i->blossom_sibling; + j = ARC_HEAD(i->match); + j->flag = 2; j->is_outer = 1; + j->match = ARC_REV(i->match); + i = ARC_HEAD(j->blossom_sibling); + } +} + +void PerfectMatching::AugmentBranchInit(Node* i0, Node* r) +{ + Node* tree_root_prev = r->tree_sibling_prev; + Node* i; + Node* j; + Arc* aa; + + r->flag = 2; + i = r->first_tree_child; + if ( i ) + while ( 1 ) + { + ARC_HEAD(i->match)->flag = 2; + i->flag = 2; + + MOVE_NODE_IN_TREE(i); + } + i = i0; + if ( !i0->is_tree_root ) + { + j = ARC_HEAD(i0->match); + j->match = aa = j->tree_parent; + i = ARC_HEAD(aa); + while ( !i->is_tree_root ) + { + j = ARC_HEAD(i->match); + i->match = ARC_REV(aa); + j->match = aa = j->tree_parent; + i = ARC_HEAD(aa); + } + i->match = ARC_REV(aa); + } + r->is_tree_root = 0; + tree_root_prev->tree_sibling_next = r->tree_sibling_next; + if (r->tree_sibling_next) r->tree_sibling_next->tree_sibling_prev = tree_root_prev; + tree_num --; +} + +//////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////// + +// true_slack(a) = slack(a) + ... + +// i->flag=0, i->is_processed=1: true_slack -= eps +// i->flag=1, i->match->head->is_processed=1: true_slack += eps - slack(i->match) + +void PerfectMatching::InitGlobal() +{ + Node* i; + Node* j; + Node* r; + Node* r2; + Node* r3 = NULL; // initialize to prevent compiler warning + Edge* a; + EdgeIterator I; + int dir; + Tree TREE; + enum { NONE, AUGMENT, SHRINK } flag; + + InitGreedy(); + + for (i=nodes; ibest_edge = NULL; + + PriorityQueue pq; + + for (r=nodes[node_num].tree_sibling_next; r; ) + { + r2 = r->tree_sibling_next; + if (r2) r3 = r2->tree_sibling_next; + i = r; + + pq.Reset(); + + r->tree = &TREE; + + REAL eps = 0; + Arc* critical_arc = NULL; + REAL critical_eps = PM_INFTY; + flag = NONE; + Node* branch_root = i; + + while ( 1 ) + { + i->is_processed = 1; + i->y -= eps; + if (!i->is_tree_root) ARC_HEAD(i->match)->y += eps; + + FOR_ALL_EDGES(i, a, dir, I) + { + a->slack += eps; + j = a->head[dir]; + + if (j->tree == &TREE) + { + // same tree + if (j->flag == 0) + { + REAL slack = a->slack; + if (!j->is_processed) slack += eps; + if (2*critical_eps > slack || critical_arc == NULL) + { + flag = SHRINK; + critical_eps = slack/2; + critical_arc = EDGE_DIR_TO_ARC(a, dir); + if (critical_eps <= eps) break; + //pq.DecreaseUpperBound(critical_eps); + } + } + } + else if (j->flag == 0) + { + // different tree + if (critical_eps >= a->slack || critical_arc == NULL) + { + flag = AUGMENT; + critical_eps = a->slack; + critical_arc = EDGE_DIR_TO_ARC(a, dir); + if (critical_eps <= eps) break; + //pq.DecreaseUpperBound(critical_eps); + } + } + else + { + // free node + if (a->slack > eps) + { + if (a->slack < critical_eps) + { + if (j->best_edge == NULL) + { + j->best_edge = a; + pq.Add(a); + } + else + { + if (a->slack < j->best_edge->slack) + { + pq.Decrease(j->best_edge, a, pq_buf); + j->best_edge = a; + } + } + } + } + else + { + assert(j->flag == 2 && !j->is_blossom && !ARC_HEAD(j->match)->is_blossom); + if (j->best_edge) pq.Remove(j->best_edge, pq_buf); + j->flag = 1; + j->tree = i->tree; + j->tree_parent = EDGE_DIR_TO_ARC(a, 1-dir); + j = ARC_HEAD(j->match); + if (j->best_edge) pq.Remove(j->best_edge, pq_buf); + ADD_TREE_CHILD(i, j); + } + } + } + + if (dir < 2 && a) + { + Edge* atmp = a; + int dirtmp = dir; + CONTINUE_FOR_ALL_EDGES(i, atmp, dirtmp, I) atmp->slack += eps; + break; + } + + // move i + if (i->first_tree_child) i = i->first_tree_child; + else + { + while (i != branch_root && !i->tree_sibling_next) { i = ARC_HEAD(i->match); i = ARC_HEAD(i->tree_parent); } + if (i == branch_root) + { + PriorityQueue::Item* q = pq.GetMin(); + if (q == NULL || q->slack >= critical_eps) + { + eps = critical_eps; + break; + } + pq.Remove(q, pq_buf); + a = (Edge*)q; + dir = (a->head[0]->flag == 2) ? 0 : 1; + j = a->head[0]; + Arc* aa = EDGE_DIR_TO_ARC(a, dir); + eps = a->slack; + assert(eps < critical_eps); + + // continue growth + i = ARC_TAIL(aa); + j = ARC_HEAD(aa); + + assert(j->flag == 2 && !j->is_blossom && !ARC_HEAD(j->match)->is_blossom); + j->flag = 1; + j->tree = i->tree; + j->tree_parent = ARC_REV(aa); + j = ARC_HEAD(j->match); + if (j->best_edge) pq.Remove(j->best_edge, pq_buf); + ADD_TREE_CHILD(i, j); + i = branch_root = j; + continue; + } + i = i->tree_sibling_next; + } + } + + // update slacks + i = r; + while ( 1 ) + { + if (i->is_processed) + { + i->y += eps; + if (!i->is_tree_root) + { + j = ARC_HEAD(i->match); + j->y -= eps; + REAL delta = eps - ARC_TO_EDGE_PTR(i->match)->slack; + FOR_ALL_EDGES(j, a, dir, I) a->slack += delta; + j->best_edge = NULL; + } + FOR_ALL_EDGES(i, a, dir, I) + { + if (!PriorityQueue::isReset(a)) + { + assert(a->head[dir]->flag == 2 && a->head[dir]->best_edge == a); + a->head[dir]->best_edge = NULL; + PriorityQueue::ResetItem(a); + } + a->slack -= eps; + } + + i->is_processed = 0; + } + else + { + if (!i->is_tree_root) ARC_HEAD(i->match)->best_edge = NULL; + } + i->best_edge = NULL; + + MOVE_NODE_IN_TREE(i); + } + + i = ARC_TAIL(critical_arc); + j = ARC_HEAD(critical_arc); + if (flag == SHRINK) + { + // shrink + ShrinkInit(ARC_TO_EDGE_PTR(critical_arc), r); + } + else + { + // augment + AugmentBranchInit(i, r); + if (j->is_outer) + { + AugmentBranchInit(j, j); + } + else + { + ExpandInit(j); + tree_num --; + } + i->match = critical_arc; + j->match = ARC_REV(critical_arc); + } + + r = r2; + if (r && !r->is_tree_root) r = r3; + } + + if (tree_num > tree_num_max) + { + if (trees) free(trees); + tree_num_max = tree_num; + trees = (Tree*) malloc(tree_num_max*sizeof(Tree)); + } + Tree* t = trees; + for (r=nodes; ris_outer) + { + ExpandInit(r); + r->is_tree_root = 1; + r->flag = 0; + r->first_tree_child = NULL; + if (t == trees) { nodes[node_num].tree_sibling_next = r; r->tree_sibling_prev = &nodes[node_num]; } + else { (t-1)->root->tree_sibling_next = r; r->tree_sibling_prev = (t-1)->root; } + r->tree = t; + t->root = r; + t->eps = 0; + t->first[0] = t->first[1] = NULL; + t->pq_current = NULL; + t->pq00.Reset(); + t->pq0.Reset(); + t->pq_blossoms.Reset(); + t ++; + } + } + assert(t == trees+tree_num); + if (t == trees) nodes[node_num].tree_sibling_next = NULL; + else (t-1)->root->tree_sibling_next = NULL; +} + + + +//----------// +// Interface // +//----------// + + +PerfectMatching::PerfectMatching(int nodeNum, int edgeNumMax) + : trees(NULL), + node_num(nodeNum), + edge_num(0), + edge_num_max(edgeNumMax), + tree_num_max(0), + removed_first(NULL), + blossom_num(0), + removed_num(0), + first_solve(true) +{ + if (node_num & 1) { printf("# of nodes is odd: perfect matching cannot exist\n"); exit(1); } + nodes = (Node*) malloc((node_num+1)*sizeof(Node)); + edges_orig = (char*) malloc(edge_num_max*sizeof(Edge)+1); + edges = (Edge*) ( ( ((POINTER_TYPE)edges_orig) & 1 ) ? (edges_orig + 1) : edges_orig ); + memset(nodes, 0, (node_num+1)*sizeof(Node)); + + blossoms = new DBlock(256); + tree_edges = new DBlock(256); + expand_tmp_list = new Block(256); + pq_buf = PriorityQueue::AllocateBuf(); +} + + +void PerfectMatching::Save(char* filename, int format) +{ + if (!first_solve) { printf("Save() cannot be called after Solve()!\n"); exit(1); } + int e; + FILE* fp = fopen(filename, "w"); + if (!fp) { printf("Can't open %s\n", filename); exit(1); } + if (format == 0) + { + fprintf(fp, "p edge %d %d\n", node_num, edge_num); + for (e=0; e::DeallocateBuf(pq_buf); +} + + +PerfectMatching::EdgeId PerfectMatching::AddEdge(NodeId _i, NodeId _j, REAL cost) +{ + if (_i<0 || _i>=node_num || _j<0 || _j>node_num || _i==_j) + { + printf("wrong node id's! (%d,%d)\n", _i, _j); exit(1); + } + if (edge_num >= edge_num_max) ReallocateEdges(); + Node* i = nodes + _i; + Node* j = nodes + _j; + Edge* a = edges + edge_num; + + ADD_EDGE(i, a, 0); + ADD_EDGE(j, a, 1); + a->head0[0] = j; + a->head0[1] = i; + + a->slack = cost*COST_FACTOR; + PriorityQueue::ResetItem(a); + + return edge_num ++; +} + +int PerfectMatching::GetSolution(EdgeId e) +{ + assert(e>=0 && ehead0[1]->match == EDGE_DIR_TO_ARC(a, 0)) ? 1 : 0; +} + +PerfectMatching::NodeId PerfectMatching::GetMatch(NodeId i) +{ + assert(i>=0 && ihead0[1]; !i->is_outer; i=i->blossom_parent, delta--) {} + for (j=a->head0[0]; !j->is_outer; j=j->blossom_parent, delta++) {} + if ( i == j ) + { + i = a->head0[1]; + j = a->head0[0]; + while ( delta < 0 ) { i = i->blossom_parent; delta ++; } + while ( delta > 0 ) { j = j->blossom_parent; delta --; } + while ( i->blossom_parent != j->blossom_parent ) + { + i = i->blossom_parent; + j = j->blossom_parent; + } + } + tail = i; + head = j; + assert((i->is_outer && j->is_outer) || (i->blossom_parent==j->blossom_parent && !i->is_outer && !j->is_outer)); +} + +void PerfectMatching::ReallocateEdges() +{ + printf("Warning: reallocating edges. Increasing edge_num_max in the constructor may improve memory efficiency!\n"); + edge_num_max = edge_num_max*3/2 + 16; + char* edges_orig_old = edges_orig; + Edge* edges_old = edges; + edges_orig = (char*) realloc(edges_orig_old, edge_num_max*sizeof(Edge)+1); + edges = (Edge*) ( ( ((POINTER_TYPE)edges_orig_old) & 1 ) ? (edges_orig + 1) : edges_orig ); + if ( ((POINTER_TYPE)edges) & 1 ) + { + char* edges_orig_old2 = edges_orig; + Edge* edges_old2 = edges; + + edges_orig = (char*) malloc(edge_num_max*sizeof(Edge)+1); + edges = (Edge*) ( ( ((POINTER_TYPE)edges_orig_old) & 1 ) ? (edges_orig + 1) : edges_orig ); + memcpy(edges, edges_old2, edge_num*sizeof(Edge)); + free(edges_orig_old2); + } + +#define UPDATE_EDGE_PTR(ptr) ptr = (Edge*)((char*)(ptr) + ((char*)edges - (char*)edges_old)) +#define UPDATE_ARC_PTR(ptr) ptr = (Arc*)((char*)(ptr) + ((char*)edges - (char*)edges_old)) + + Node* i; + Edge* a; + for (a=edges; anext[0]) UPDATE_EDGE_PTR(a->next[0]); + if (a->next[1]) UPDATE_EDGE_PTR(a->next[1]); + if (a->prev[0]) UPDATE_EDGE_PTR(a->prev[0]); + if (a->prev[1]) UPDATE_EDGE_PTR(a->prev[1]); + } + if (first_solve) + { + for (i=nodes; ifirst[0]) UPDATE_EDGE_PTR(i->first[0]); + if (i->first[1]) UPDATE_EDGE_PTR(i->first[1]); + } + } + else + { + Node* i0; + for (i0=nodes; i0is_outer) + { + UPDATE_ARC_PTR(i->match); + if (i->first[0]) UPDATE_EDGE_PTR(i->first[0]); + if (i->first[1]) UPDATE_EDGE_PTR(i->first[1]); + break; + } + UPDATE_ARC_PTR(i->blossom_sibling); + if (i->first[0]) UPDATE_EDGE_PTR(i->first[0]); + if (i->first[1]) UPDATE_EDGE_PTR(i->first[1]); + + i = i->blossom_parent; + if (i->is_outer) { if ( i->is_marked) break; i->is_marked = 1; } + else { if (!i->is_marked) break; i->is_marked = 0; } + } + } + for (i0=nodes; i0is_outer) break; + + i = i->blossom_parent; + if (i->is_outer) { if (!i->is_marked) break; i->is_marked = 0; } + else { if ( i->is_marked) break; i->is_marked = 1; } + } + } + } +} + +int PerfectMatching::GetBlossomNum() +{ + return blossom_num; +} + +void PerfectMatching::GetDualSolution(int* blossom_parents, REAL* twice_y) +{ + int _i0, id = node_num; + int* child_ptr; + Node* i0; + Node* i; + int* tmp_array = new int[blossom_num]; + + int* tmp_array_ptr = tmp_array; + for (_i0=0, i0=nodes; _i0y; + if (i0->is_outer) + { + blossom_parents[_i0] = -1; + continue; + } + child_ptr = &blossom_parents[_i0]; + i = i0->blossom_parent; + while ( 1 ) + { + if (i->is_marked) + { + *child_ptr = i->lca_preorder; + break; + } + i->is_marked = 1; + *tmp_array_ptr ++ = i->lca_preorder; + *child_ptr = i->lca_preorder = id ++; + child_ptr = &blossom_parents[i->lca_preorder]; + twice_y[i->lca_preorder] = i->y; + if (i->is_outer) + { + *child_ptr = -1; + break; + } + i = i->blossom_parent; + } + } + + assert(id == node_num+blossom_num && tmp_array_ptr == tmp_array + blossom_num); + + tmp_array_ptr = tmp_array; + for (_i0=0, i0=nodes; _i0is_outer) continue; + i = i0->blossom_parent; + while ( 1 ) + { + if (!i->is_marked) break; + i->is_marked = 0; + i->lca_preorder = *tmp_array_ptr ++; + if (i->is_outer) break; + i = i->blossom_parent; + } + } + + delete [] tmp_array; +} + + + + +//----------// +// Main // +//----------// + + + +void PerfectMatching::Finish() +{ + +#define IS_VALID_MATCH(i) ((Edge*)(i->match) >= edges && (Edge*)(i->match) < edges + edge_num) + + Node* i0; + Node* i; + Node* j; + Node* k; + Node* b; + Node* b_prev; + Node* b_prev_prev; + + for (i0=nodes; i0blossom_grandparent = b_prev; + b_prev = b; + b = b->blossom_parent; + } while (!IS_VALID_MATCH(b)); + + b_prev_prev = b_prev->blossom_grandparent; + while ( 1 ) + { + for (k=ARC_TAIL0(b->match); k->blossom_parent!=b; k=k->blossom_parent) {} + k->match = b->match; + i = ARC_HEAD(k->blossom_sibling); + while ( i != k ) + { + i->match = i->blossom_sibling; + j = ARC_HEAD(i->match); + j->match = ARC_REV(i->match); + i = ARC_HEAD(j->blossom_sibling); + } + + b = b_prev; + if (!b->is_blossom) break; + b_prev = b_prev_prev; + b_prev_prev = b_prev->blossom_grandparent; + } + } +} + + +void PerfectMatching::AddTreeEdge(Tree* t0, Tree* t1) +{ + TreeEdge* e = tree_edges->New(); + e->head[0] = t1; + e->head[1] = t0; + e->next[0] = t0->first[0]; + t0->first[0] = e; + e->next[1] = t1->first[1]; + t1->first[1] = e; + + e->pq00.Reset(); + e->pq01[0].Reset(); + e->pq01[1].Reset(); + + t1->pq_current = e; + t1->dir_current = 0; +} + +bool PerfectMatching::ProcessEdge00(Edge* a, bool update_boundary_edge) +{ + int dir; + Node* j; + Node* prev[2]; + Node* last[2]; + for (dir=0; dir<2; dir++) + { + if (a->head[dir]->is_outer) { prev[dir] = NULL; last[dir] = a->head[dir]; } + else + { + j = a->head[dir]; + GET_PENULTIMATE_BLOSSOM(j); + prev[dir] = j; + last[dir] = prev[dir]->blossom_parent; + //assert(last[dir]->is_outer); + } + } + + if (last[0] != last[1]) + { + for (dir=0; dir<2; dir++) + { + j = a->head[dir]; + if (j != last[dir]) { int dir_rev = 1 - dir; MOVE_EDGE(j, last[dir], a, dir_rev); } + } + if (update_boundary_edge) a->slack -= 2*a->head[0]->tree->eps; + return true; + } + + if (prev[0] != prev[1]) + { + for (dir=0; dir<2; dir++) + { + j = a->head[dir]; + if (j != prev[dir]) { int dir_rev = 1 - dir; MOVE_EDGE(j, prev[dir], a, dir_rev); } + } + a->slack -= 2*prev[0]->blossom_eps; + return false; + } + + for (dir=0; dir<2; dir++) + { + j = a->head[1-dir]; + REMOVE_EDGE(j, a, dir); + } + a->next[0] = prev[0]->blossom_selfloops; + prev[0]->blossom_selfloops = a; + return false; +} + + +inline void PerfectMatching::AugmentBranch(Node* i0) +{ + int dir; + Tree* t = i0->tree; + Node* r = t->root; + Node* tree_root_prev = r->tree_sibling_prev; + Node* i; + Node* j; + Edge* a; + EdgeIterator I; + Arc* aa; + REAL eps = t->eps; + PriorityQueue::Item* q; + TreeEdge* e; + TreeEdgeIterator T; + Tree* t2; + + t = r->tree; + t->pq_current = t; + + FOR_ALL_TREE_EDGES_X(t, e, dir, T) + { + t2 = e->head[dir]; + e->head[1-dir] = NULL; // mark it for deletion + + t2->pq_current = e; + t2->dir_current = dir; + } + + i = r->first_tree_child; + if ( i ) + while ( 1 ) + { + Node* i0 = i; + i = ARC_HEAD(i->match); + if (i->is_processed) + { + if (i->is_blossom) + { + a = ARC_TO_EDGE_PTR(i->match); + REAL tmp = a->slack; a->slack = i->y; i->y = tmp; + PriorityQueue::ResetItem(a); + } + FOR_ALL_EDGES(i, a, dir, I) + { + GET_OUTER_HEAD(a, dir, j); + + if (j->flag == 0 && j->is_processed) + { + if (j->tree != t) + { + a->slack += eps; + if (PriorityQueue::isReset(a)) j->tree->pq0.Add(a); + } + } + else a->slack += eps; + } + } + + i = i0; + MOVE_NODE_IN_TREE(i); + } + + /////////////////////////////////////////////////////////////////// + + FOR_ALL_TREE_EDGES(t, e, dir) + { + t2 = e->head[dir]; + t2->pq_current = NULL; + + e->pq01[1-dir].Merge(t2->pq0); + for (q=e->pq00.GetFirst(); q; q=e->pq00.GetNext(q)) + { + q->slack -= eps; + int dir2; + for (dir2=0; dir2<2; dir2++) GET_OUTER_HEAD((Edge*)q, dir2, j); + } + e->pq00.Merge(t2->pq0); + for (q=e->pq01[dir].GetAndResetFirst(); q; q=e->pq01[dir].GetAndResetNext()) + { + q->slack -= eps; + int dir2; + for (dir2=0; dir2<2; dir2++) GET_OUTER_HEAD((Edge*)q, dir2, j); + } + } + for (q=t->pq0.GetAndResetFirst(); q; q=t->pq0.GetAndResetNext()) + { + q->slack -= eps; + int dir2; + for (dir2=0; dir2<2; dir2++) GET_OUTER_HEAD((Edge*)q, dir2, j); + } + for (q=t->pq00.GetAndResetFirst(); q; q=t->pq00.GetAndResetNext()) + { + ProcessEdge00((Edge*)q); + } + + /////////////////////////////////////////////////////////////////// + + r->flag = 2; + r->is_processed = 0; + i = r->first_tree_child; + r->y += eps; + if ( i ) + while ( 1 ) + { + j = ARC_HEAD(i->match); + j->flag = 2; + i->flag = 2; + j->is_processed = 0; + i->is_processed = 0; + j->y -= eps; + i->y += eps; + + MOVE_NODE_IN_TREE(i); + } + + /////////////////////////////////////////////////////////////////// + + i = i0; + if ( !i0->is_tree_root ) + { + j = ARC_HEAD(i0->match); + GET_TREE_PARENT(j, i); + j->match = aa = j->tree_parent; + while ( !i->is_tree_root ) + { + j = ARC_HEAD(i->match); + i->match = ARC_REV(aa); + GET_TREE_PARENT(j, i); + j->match = aa = j->tree_parent; + } + i->match = ARC_REV(aa); + } + r->is_tree_root = 0; + tree_root_prev->tree_sibling_next = r->tree_sibling_next; + if (r->tree_sibling_next) r->tree_sibling_next->tree_sibling_prev = tree_root_prev; + tree_num --; +} + + +void PerfectMatching::Augment(Edge* a) +{ + Node* j; + int dir; + + for (dir=0; dir<2; dir++) + { + GET_OUTER_HEAD(a, dir, j); + AugmentBranch(j); + j->match = EDGE_DIR_TO_ARC(a, 1-dir); + } + if (options.verbose) + { + int k = 1; + while (k < tree_num) k *= 2; + if (k == tree_num || tree_num<=8 || (tree_num<=64 && (tree_num%8)==0)) { printf("%d.", tree_num); fflush(stdout); } + } +} + +inline void PerfectMatching::GrowNode(Node* i) +{ + //assert(i->is_outer); + //assert(i->flag == 0); + + Edge* a; + EdgeIterator I; + int dir; + Node* j; + Tree* t = i->tree; + REAL eps = t->eps; + Edge* a_augment = NULL; + + FOR_ALL_EDGES(i, a, dir, I) + { + GET_OUTER_HEAD(a, dir, j); + + if (j->flag == 2) + { + a->slack += eps; + if (a->slack > 0) + { + t->pq0.Add(a); + } + else + { + j->flag = 1; + j->tree = i->tree; + j->tree_parent = EDGE_DIR_TO_ARC(a, 1-dir); + j->y += eps; + j = ARC_HEAD(j->match); + j->y -= eps; + ADD_TREE_CHILD(i, j); + } + } + else + { + if (j->flag == 0 && j->is_processed) + { + if (!PriorityQueue::isReset(a)) j->tree->pq0.Remove(a, pq_buf); + if (a->slack <= j->tree->eps && j->tree != t) a_augment = a; + a->slack += eps; + if (!j->tree->pq_current) AddTreeEdge(t, j->tree); + j->tree->pq_current->pq00.Add(a); + } + else + { + a->slack += eps; + if (j->flag == 1 && j->tree != t) + { + if (!j->tree->pq_current) AddTreeEdge(t, j->tree); + j->tree->pq_current->pq01[j->tree->dir_current].Add(a); + } + } + } + } + + //assert(!i->is_processed); + i->is_processed = 1; + + if (!i->is_tree_root) + { + j = ARC_HEAD(i->match); + //assert(!j->is_processed); + j->is_processed = 1; + if (j->is_blossom) + { + a = ARC_TO_EDGE_PTR(i->match); + REAL tmp = a->slack; a->slack = j->y; j->y = tmp; + t->pq_blossoms.Add(a); + } + } + + if (a_augment) Augment(a_augment); + + stat.grow_count ++; +} + + + +void PerfectMatching::GrowTree(Node* r, bool new_subtree) +{ + //assert(r->flag == 0); + + Node* i = r; + Node* j; + Node* stop = r->tree_sibling_next; + if (new_subtree && r->first_tree_child) stop = r->first_tree_child; + Edge* a; + EdgeIterator I; + int dir; + Tree* t = r->tree; + REAL eps = t->eps; + int tree_num0 = tree_num; + + while ( 1 ) + { + if (!i->is_tree_root) + { + // process "-" node + i = ARC_HEAD(i->match); + FOR_ALL_EDGES(i, a, dir, I) + { + GET_OUTER_HEAD(a, dir, j); + + if (j->flag == 2) a->slack -= eps; + else + { + if (j->flag == 0 && j->is_processed) + { + if (!PriorityQueue::isReset(a)) j->tree->pq0.Remove(a, pq_buf); + a->slack -= eps; + if (j->tree != t) + { + if (!j->tree->pq_current) AddTreeEdge(t, j->tree); + j->tree->pq_current->pq01[1-j->tree->dir_current].Add(a); + } + } + else a->slack -= eps; + } + } + i = ARC_HEAD(i->match); + } + // process "+" node + GrowNode(i); + if (tree_num != tree_num0) break; + + if (i->first_tree_child) i = i->first_tree_child; + else + { + while (i != r && !i->tree_sibling_next) { i = ARC_HEAD(i->match); GET_TREE_PARENT(i, i); } + i = i->tree_sibling_next; + } + if (i == stop) break; + } +} + +void PerfectMatching::Solve(bool finish) +{ + Node* i; + Node* j; + Node* r; + Node* r2; + Node* r3 = NULL; // initialize to prevent compiler warning + PriorityQueue::Item* q; + Edge* a; + Tree* t; + Tree* t2; + TreeEdge* e; + TreeEdgeIterator T; + int dir; + REAL eps; + + double start_time = get_time(); + + if (IS_INT) + { + if (options.dual_greedy_update_option == 2) + { + printf("Fixed eps approach can only be used with floating point REAL!\n"); + printf("Change REAL to double in PerfectMatching.h and recompile\n"); + exit(1); + } + if (options.dual_LP_threshold > 0) + { + printf("LP approach can only be used with floating point REAL!\n"); + printf("Change REAL to double in PerfectMatching.h and recompile\n"); + exit(1); + } + } + if (options.verbose) { printf("perfect matching with %d nodes and %d edges\n", node_num, edge_num); fflush(stdout); } + + if (first_solve) + { + if (options.verbose) { printf(" starting init..."); fflush(stdout); } + if (options.fractional_jumpstart) InitGlobal(); + else InitGreedy(); + if (options.verbose) printf("done [%.3f secs]. ", get_time() - start_time); + first_solve = false; + } + else if (options.verbose) printf(" solving updated problem. "); + + if (options.verbose) { printf("%d trees\n .", tree_num); fflush(stdout); } + + memset(&stat, 0, sizeof(Stat)); + + /////////////////////////////////////////////////////// + // first pass - initialize auxiliary graph // + /////////////////////////////////////////////////////// + + for (r=nodes[node_num].tree_sibling_next; r; r=r->tree_sibling_next) + { + //assert(!r->is_processed); + t = r->tree; + //assert(!t->first[0] && !t->first[1]); + + EdgeIterator I; + FOR_ALL_EDGES(r, a, dir, I) + { + j = a->head[dir]; + if (j->flag == 2) t->pq0.Add(a); + else if (j->is_processed) + { + //assert(j->flag == 0); + if (!j->tree->pq_current) AddTreeEdge(t, j->tree); + j->tree->pq_current->pq00.Add(a); + } + } + r->is_processed = 1; + FOR_ALL_TREE_EDGES(t, e, dir) e->head[dir]->pq_current = NULL; + } + + /////////////////////////////////////////////////////// + // main loop // + /////////////////////////////////////////////////////// + + while ( 1 ) + { + int tree_num0 = tree_num; + Stat stat0 = stat; + REAL delta = 0; + + for (r=nodes[node_num].tree_sibling_next; r; ) + { + r2 = r->tree_sibling_next; + if (r2) r3 = r2->tree_sibling_next; + t = r->tree; + + int tree_num1 = tree_num; + + ////////////////////////////////////////////////////////////////////// + // step 1 - traversing auxiliary graph, setting pq_current pointers // + ////////////////////////////////////////////////////////////////////// + t->pq_current = t; + if (options.update_duals_before) + { + eps = PM_INFTY; + Edge* a_augment = NULL; + REAL eps_augment = PM_INFTY; + if ((q=t->pq0.GetMin())) eps = q->slack; + if ((q=t->pq_blossoms.GetMin()) && eps > q->slack) eps = q->slack; + while ((q=t->pq00.GetMin())) + { + if (ProcessEdge00((Edge*)q, false)) break; + t->pq00.Remove(q, pq_buf); + } + if (q && 2*eps > q->slack) eps = q->slack/2; + FOR_ALL_TREE_EDGES_X(t, e, dir, T) + { + t2 = e->head[dir]; + t2->pq_current = e; + t2->dir_current = dir; + if ((q=e->pq00.GetMin()) && (!a_augment || eps_augment > q->slack-t2->eps)) { a_augment = (Edge*)q; eps_augment = q->slack-t2->eps; } + if ((q=e->pq01[dir].GetMin()) && eps > q->slack+t2->eps) eps = q->slack+t2->eps; + } + if (eps > eps_augment) eps = eps_augment; + if (eps > t->eps) + { + delta += eps - t->eps; + t->eps = eps; + } + if (a_augment && eps_augment <= t->eps) Augment(a_augment); + } + else + { + FOR_ALL_TREE_EDGES_X(t, e, dir, T) + { + t2 = e->head[dir]; + t2->pq_current = e; + t2->dir_current = dir; + + if ((q=e->pq00.GetMin()) && (q->slack - t->eps <= t2->eps)) + { + Augment((Edge*)q); + break; + } + } + } + + ///////////////////////////////// + // step 2 - growing tree // + ///////////////////////////////// + eps = t->eps; + REAL twice_eps = 2*eps; + + while ( tree_num1 == tree_num ) + { + if ((q=t->pq0.GetMin()) && q->slack <= t->eps) + { + a = (Edge*)q; + dir = (a->head[1]->flag == 2 && a->head[1]->is_outer) ? 1 : 0; + GET_OUTER_HEAD(a, 1-dir, i); + j = a->head[dir]; + //assert(i->flag==0 && j->flag==2 && i->is_outer && j->is_outer && i->tree==t); + + j->flag = 1; + j->tree = i->tree; + j->tree_parent = EDGE_DIR_TO_ARC(a, 1-dir); + j->y += eps; + j = ARC_HEAD(j->match); + j->y -= eps; + ADD_TREE_CHILD(i, j); + + GrowTree(j, true); + } + else if ((q=t->pq00.GetMin()) && q->slack <= twice_eps) + { + t->pq00.Remove(q, pq_buf); + a = (Edge*)q; + if (ProcessEdge00(a)) Shrink(a); + } + else if ((q=t->pq_blossoms.GetMin()) && q->slack <= eps) + { + t->pq_blossoms.Remove(q, pq_buf); + a = (Edge*)q; + j = (a->head[0]->flag == 1) ? a->head[0] : a->head[1]; + REAL tmp = a->slack; a->slack = j->y; j->y = tmp; + Expand(j); + } + else break; + } + + /////////////////////////////////////////////////////////////////////// + // step 3 - traversing auxiliary graph, clearing pq_current pointers // + /////////////////////////////////////////////////////////////////////// + if ( tree_num1 == tree_num ) + { + t->pq_current = NULL; + if (options.update_duals_after) + { + eps = PM_INFTY; + Edge* a_augment = NULL; + REAL eps_augment = PM_INFTY; + if ((q=t->pq0.GetMin())) eps = q->slack; + if ((q=t->pq_blossoms.GetMin()) && eps > q->slack) eps = q->slack; + while ((q=t->pq00.GetMin())) + { + if (ProcessEdge00((Edge*)q, false)) break; + t->pq00.Remove(q, pq_buf); + } + if (q && 2*eps > q->slack) eps = q->slack/2; + FOR_ALL_TREE_EDGES(t, e, dir) + { + t2 = e->head[dir]; + e->head[dir]->pq_current = NULL; + if ((q=e->pq00.GetMin()) && (!a_augment || eps_augment > q->slack-t2->eps)) { a_augment = (Edge*)q; eps_augment = q->slack-t2->eps; } + if ((q=e->pq01[dir].GetMin()) && eps > q->slack+t2->eps) eps = q->slack+t2->eps; + } + if (eps > eps_augment) eps = eps_augment; + bool progress = false; + if (eps > t->eps) + { + delta += eps - t->eps; + t->eps = eps; + progress = true; + } + if (a_augment && eps_augment <= t->eps) Augment(a_augment); + else if (progress && tree_num >= options.single_tree_threshold*node_num) + { + // continue with the same tree + r = t->root; + continue; + } + } + else + { + FOR_ALL_TREE_EDGES(t, e, dir) e->head[dir]->pq_current = NULL; + } + } + + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + + r = r2; + if (r && !r->is_tree_root) r = r3; + } + + if (tree_num == 0) break; + + if ( tree_num == tree_num0 ) + //&& stat.grow_count == stat0.grow_count + //&& stat.shrink_count == stat0.shrink_count + //&& stat.expand_count == stat0.expand_count ) + { + if (!UpdateDuals()) + { + if (!IS_INT && delta <= PM_THRESHOLD) // for numerical stability + { + //CommitEps(); + int dual_greedy_update_option = options.dual_greedy_update_option; + options.dual_greedy_update_option = 2; + UpdateDuals(); + options.dual_greedy_update_option = dual_greedy_update_option; + } + } + } + } + + if (finish) Finish(); + + if (options.verbose) + { + printf("\ndone [%.3f secs]. %d grows, %d expands, %d shrinks\n", get_time()-start_time, stat.grow_count, stat.expand_count, stat.shrink_count); + printf(" expands: [%.3f secs], shrinks: [%.3f secs], dual updates: [%.3f secs]\n", stat.expand_time, stat.shrink_time, stat.dual_time); + fflush(stdout); + } +} + + + + +//----------// +// Repair // +//----------// + + +struct PerfectMatching::LCATreeX : LCATree +{ + LCATreeX(int size) : LCATree(size) { rev_mapping = new Node*[size]; } + ~LCATreeX() { delete [] rev_mapping; } + Node** rev_mapping; +}; + +void PerfectMatching::StartUpdate() +{ + Node* i0; + Node* i; + Node* j; + Node* b; + + while ((i=removed_first)) + { + removed_first = i->tree_sibling_next; + blossoms->Delete(i); + removed_num --; + } + + Edge* a; + Edge* selfloop_first = NULL; + Edge* selfloop_last = NULL; + + for (i0=nodes; i0is_processed = 0; + if (i0->is_outer) continue; + + i0->is_tree_root = 0; + i0->blossom_ptr = NULL; + i = i0; + while ( 1 ) + { + j = i->blossom_parent; + j->is_processed = 0; + if (j->is_outer) { j->first_tree_child = i; break; } + if (j->is_marked) break; + if ((a=j->blossom_selfloops)) + { + if (selfloop_last) selfloop_last->next[1] = a; + else selfloop_first = a; + selfloop_last = a; + a->next[1] = NULL; + } + j->blossom_ptr = i; + i = j; + } + b = (i->blossom_parent->is_outer) ? i->blossom_parent : i->blossom_parent->blossom_grandparent; +#ifdef LCA_REPAIRS + if (!b->is_marked) + { + b->lca_size = 1; + b->is_marked = 1; + } +#endif + while ( 1 ) + { +#ifdef LCA_REPAIRS + b->lca_size ++; +#endif + ARC_TO_EDGE_PTR(i->blossom_sibling)->y_saved = i->y; + i->y += i->blossom_parent->y; + if (!i->is_blossom) break; + i->is_marked = 1; + j = i; + i = i->blossom_ptr; + j->blossom_grandparent = b; + } + i->blossom_grandparent = b; + } + +#ifdef LCA_REPAIRS + for (i0=nodes; i0is_outer) continue; + b = i0->blossom_grandparent; + if (!b->is_marked) continue; + b->is_marked = 0; + LCATreeX* lca = new LCATreeX(b->lca_size); + b->blossom_ptr = b->first_tree_child; + i = b; + while ( 1 ) + { + if (i->blossom_ptr) i = i->blossom_ptr; + else + { + while ( 1 ) + { + if (i->is_outer) break; + i->lca_preorder = lca->Add(i, i->blossom_parent); + lca->rev_mapping[i->lca_preorder] = i; + i = ARC_HEAD(i->blossom_sibling); + if (i != i->blossom_parent->blossom_ptr) break; + i = i->blossom_parent; + } + if (i->is_outer) + { + lca->AddRoot(i); + break; + } + } + } + b->lca = lca; + } +#endif + + while ((a=selfloop_first)) + { + selfloop_first = a->next[1]; + do + { + Edge* a_next = a->next[0]; + +#ifdef LCA_REPAIRS + int _i = a->head0[1]->lca_preorder; + int _j = a->head0[0]->lca_preorder; + Node* b = a->head0[1]->blossom_grandparent; + b->lca->GetPenultimateNodes(_i, _j); + i = b->lca->rev_mapping[_i]; + j = b->lca->rev_mapping[_j]; +#else + GetRealEndpoints(a, i, j); +#endif + ADD_EDGE(i, a, 0); + ADD_EDGE(j, a, 1); + a->slack -= 2*i->blossom_eps; + a = a_next; + } while ( a ); + } + + /* + for (i0=nodes; i0is_outer) continue; + b = i0->blossom_grandparent; + if (b->lca) + { + delete b->lca; + b->lca = NULL; + } + } + */ + + nodes[node_num].first_tree_child = NULL; +} + +void PerfectMatching::FinishUpdate() +{ + Node* i0; + Node* i; + Node* j; + Edge* a; + EdgeIterator I; + int dir; + Tree* t; + + for (i0=nodes; i0is_outer) continue; + +#ifdef LCA_REPAIRS + if (i0->blossom_grandparent->lca) + { + delete i0->blossom_grandparent->lca; + i0->blossom_grandparent->lca = NULL; + } +#endif + + ////////////////////////////////////////////////////////////// + if (!i0->blossom_grandparent->is_removed) + { + i = i0; + do + { + i->y = ARC_TO_EDGE_PTR(i->blossom_sibling)->y_saved; + i->is_marked = 0; + i->blossom_selfloops = NULL; + i = i->blossom_parent; + } while (i->is_marked); + continue; + } + ////////////////////////////////////////////////////////////// + + i = i0->blossom_parent; + while ( 1 ) + { + if (i->is_removed && !i->is_outer) break; + REAL y_parent = (i->is_outer) ? 0 : i->blossom_parent->y; + for (dir=0; dir<2; dir++) + { + if (!i->first[dir]) continue; + i->first[dir]->prev[dir]->next[dir] = NULL; + Edge* a_next; + for (a=i->first[dir]; a; a=a_next) + { + a_next = a->next[dir]; + j = a->head0[1-dir]; + ADD_EDGE(j, a, dir); + a->slack += j->blossom_parent->y - y_parent; + } + i->first[dir] = NULL; + } + if (i->is_removed) break; + + j = i->blossom_parent; + i->is_removed = 1; + i->tree_sibling_next = removed_first; + removed_first = i; + i = j; + } + i0->y = ARC_TO_EDGE_PTR(i0->blossom_sibling)->y_saved; + i0->is_outer = 1; + i0->flag = 2; + i0->is_tree_root = 1; + } + + Node* blossom_list = nodes[node_num].first_tree_child; + + + + for (i=nodes; iis_tree_root) continue; + i->first_tree_child = nodes[node_num].first_tree_child; + nodes[node_num].first_tree_child = i; + REAL slack_min = PM_INFTY; + FOR_ALL_EDGES(i, a, dir, I) + { + if (slack_min > a->slack) slack_min = a->slack; + } + i->y += slack_min; + FOR_ALL_EDGES(i, a, dir, I) a->slack -= slack_min; + } + + tree_num = 0; + for (i=nodes[node_num].first_tree_child; i!=blossom_list; i=i->first_tree_child) + { + tree_num ++; + if (!i->is_tree_root) continue; + FOR_ALL_EDGES(i, a, dir, I) + { + j = a->head[dir]; + if (a->slack <= 0 && j->is_tree_root) + { + i->is_tree_root = j->is_tree_root = 0; + i->match = EDGE_DIR_TO_ARC(a, dir); + j->match = EDGE_DIR_TO_ARC(a, 1-dir); + tree_num -= 2; + break; + } + } + } + for ( ; i; i=i->first_tree_child) + { + if (i->is_removed) { i->is_tree_root = 0; continue; } + tree_num ++; + } + + if (tree_num > tree_num_max) + { + if (trees) free(trees); + tree_num_max = tree_num; + trees = (Tree*) malloc(tree_num_max*sizeof(Tree)); + } + t = trees; + + Node* last_root = &nodes[node_num]; + Node* i_next; + for (i=nodes; i; i=i_next) + { + if (!i->is_blossom) i_next = (ifirst_tree_child; + if (!i->is_tree_root) continue; + + i->flag = 0; + i->first_tree_child = NULL; + i->tree_sibling_prev = last_root; + last_root->tree_sibling_next = i; + last_root = i; + i->tree = t; + t->root = i; + t->eps = 0; + t->first[0] = t->first[1] = NULL; + t->pq_current = NULL; + t->pq00.Reset(); + t->pq0.Reset(); + t->pq_blossoms.Reset(); + t ++; + } + + assert(t == trees + tree_num); + last_root->tree_sibling_next = NULL; + + while ((i=removed_first)) + { + removed_first = i->tree_sibling_next; + blossoms->Delete(i); + blossom_num --; + } +} + +PerfectMatching::REAL PerfectMatching::GetTwiceSum(NodeId i) +{ + assert(i>=0 && ihead0[dir]; + if (i->is_outer) + { + if (!i->is_tree_root) + { + i->is_tree_root = 1; + i = ARC_HEAD(i->match); + assert(!i->is_tree_root && i->is_outer); + i->is_tree_root = 1; + if (i->is_blossom) + { + i->first_tree_child = nodes[node_num].first_tree_child; + nodes[node_num].first_tree_child = i; + } + } + return; + } + if (i->blossom_grandparent->is_removed) return; + } + + Node* b = i->blossom_grandparent; + assert(b->is_outer); + + if (!b->is_tree_root) + { + b->is_tree_root = 1; + i = ARC_HEAD(b->match); + assert(!i->is_tree_root && i->is_outer); + i->is_tree_root = 1; + if (i->is_blossom) + { + i->first_tree_child = nodes[node_num].first_tree_child; + nodes[node_num].first_tree_child = i; + } + } + + b->is_removed = 1; + b->tree_sibling_next = removed_first; + removed_first = b; +} + +PerfectMatching::EdgeId PerfectMatching::AddNewEdge(NodeId _i, NodeId _j, REAL cost, bool do_not_add_if_positive_slack) +{ + assert(_i>=0 && _i=0 && _j= edge_num_max) ReallocateEdges(); + Node* i = nodes + _i; + Node* j = nodes + _j; + Edge* a = edges + edge_num; + + a->slack = cost*COST_FACTOR; + a->head0[0] = j; + a->head0[1] = i; + Node* bi = (i->is_outer) ? i : i->blossom_grandparent; + Node* bj = (j->is_outer) ? j : j->blossom_grandparent; + if (bi == bj) + { +#ifdef LCA_REPAIRS + int _i = i->lca_preorder; + int _j = j->lca_preorder; + bi->lca->GetPenultimateNodes(_i, _j); + i = bi->lca->rev_mapping[_i]; + j = bi->lca->rev_mapping[_j]; +#else + GetRealEndpoints(a, i, j); +#endif + a->slack += i->blossom_parent->y + j->blossom_parent->y; + } + else + { + i = bi; + j = bj; + } + a->slack -= a->head0[0]->y + a->head0[1]->y; + + if (a->slack >= 0 && do_not_add_if_positive_slack) return -1; + + ADD_EDGE(i, a, 0); + ADD_EDGE(j, a, 1); + PriorityQueue::ResetItem(a); + + if (a->slack < 0) + { + ProcessNegativeEdge(a); + } + + return edge_num ++; +} + +void PerfectMatching::UpdateCost(EdgeId e, REAL delta_cost) +{ + assert(e>=0 && eslack += delta_cost*COST_FACTOR; + if (a->slack == 0) return; + if (a->slack > 0) + { + Node* i = a->head[1]; + Node* j = a->head[0]; + if (i->is_outer) + { + if (ARC_TO_EDGE_PTR(i->match) != a && ARC_TO_EDGE_PTR(j->match) != a) return; + } + else + { + if (ARC_TO_EDGE_PTR(i->blossom_sibling) != a && ARC_TO_EDGE_PTR(j->blossom_sibling) != a) return; + } + } + ProcessNegativeEdge(a); +} + + + + +//----------// +// Shrink // +//----------// + + + +PerfectMatching::Node* PerfectMatching::FindBlossomRoot(Edge* a0) +{ + Node* i; + Node* j; + Node* _i[2]; + Node* r; + int branch; + + _i[0] = ARC_HEAD(a0); + _i[1] = ARC_TAIL(a0); + branch = 0; + while ( 1 ) + { + if (_i[branch]->is_marked) + { + r = _i[branch]; + j = _i[1-branch]; + break; + } + _i[branch]->is_marked = 1; + if (_i[branch]->is_tree_root) + { + j = _i[branch]; + i = _i[1-branch]; + while (!i->is_marked) + { + i->is_marked = 1; + i = ARC_HEAD(i->match); + GET_TREE_PARENT(i, i); + } + r = i; + break; + } + i = ARC_HEAD(_i[branch]->match); + GET_TREE_PARENT(i, _i[branch]); + branch = 1 - branch; + } + i = r; + while ( i != j ) + { + i = ARC_HEAD(i->match); + i = ARC_HEAD(i->tree_parent); + i->is_marked = 0; + } + // clear is_marked and is_outer + i = ARC_HEAD(a0); + while (i != r) + { + i->is_marked = 0; + i->is_outer = 0; + i = ARC_HEAD(i->match); + i->is_outer = 0; + i = ARC_HEAD(i->tree_parent); + } + i = ARC_TAIL(a0); + while (i != r) + { + i->is_marked = 0; + i->is_outer = 0; + i = ARC_HEAD(i->match); + i->is_outer = 0; + i = ARC_HEAD(i->tree_parent); + } + r->is_marked = 0; + r->is_outer = 0; + + return r; +} + + +void PerfectMatching::Shrink(Edge* a0) +{ + //assert(a0->head[0]->is_outer && a0->head[1]->is_outer); + //assert(a0->head[0]->flag == 0 && a0->head[1]->flag == 0); + + double start_time = get_time(); + + int branch, dir; + Node* r; + Node* i; + Node* j; + Edge* a; + Edge** a_inner_ptr; + Arc* a_prev; + Node* b = blossoms->New(); + Edge* a_augment = NULL; + Edge* b_match; + + b->first[0] = b->first[1] = NULL; + + // set is_outer=0 for all nodes in the blossom + r = FindBlossomRoot(a0); + Tree* t = r->tree; + REAL eps = t->eps; + + b->first_tree_child = NULL; + i = ARC_HEAD(a0); + branch = 0; + while ( 1 ) + { + if (i == r && branch) break; + i->is_marked = 1; + if (i == r) + { + branch = 1; + i = ARC_TAIL(a0); + continue; + } + + // remove i from the list of children + REMOVE_FROM_TREE(i); + + // move children of i to the list of children of b + if (i->first_tree_child) + { + j = i->first_tree_child; + if (!b->first_tree_child) b->first_tree_child = j; + else + { + Node* j_last = j->tree_sibling_prev; + j->tree_sibling_prev = b->first_tree_child->tree_sibling_prev; + b->first_tree_child->tree_sibling_prev->tree_sibling_next = j; + b->first_tree_child->tree_sibling_prev = j_last; + } + } + + // go to parent + i = ARC_HEAD(i->match); + i->is_marked = 1; + if (i->is_blossom) + { + a = ARC_TO_EDGE_PTR(i->match); + t->pq_blossoms.Remove(a, pq_buf); + REAL tmp = a->slack; a->slack = i->y; i->y = tmp; + } + i = ARC_HEAD(i->tree_parent); + } + + // move children of r to the list of children of b + if (i->first_tree_child) + { + j = i->first_tree_child; + if (!b->first_tree_child) b->first_tree_child = j; + else + { + Node* j_last = j->tree_sibling_prev; + j->tree_sibling_prev = b->first_tree_child->tree_sibling_prev; + b->first_tree_child->tree_sibling_prev->tree_sibling_next = j; + b->first_tree_child->tree_sibling_prev = j_last; + } + } + + // init b + b->is_removed = 0; + b->is_outer = 1; + b->flag = 0; + b->is_blossom = 1; + b->is_tree_root = r->is_tree_root; + b->is_processed = 1; + b->tree = t; + b->y = -eps; + b->is_marked = 0; + + // replace r with b in the tree + b->tree_sibling_prev = r->tree_sibling_prev; + b->tree_sibling_next = r->tree_sibling_next; + Node* b_parent = NULL; + if (!b->is_tree_root) + { + b_parent = ARC_HEAD(r->match); GET_TREE_PARENT(b_parent, b_parent); + } + if (b->tree_sibling_prev->tree_sibling_next) b->tree_sibling_prev->tree_sibling_next = b; + else b_parent->first_tree_child = b; + if (b->tree_sibling_next) b->tree_sibling_next->tree_sibling_prev = b; + else if (b_parent) b_parent->first_tree_child->tree_sibling_prev = b; + + if (b->is_tree_root) + { + b->tree->root = b; + b_match = NULL; + } + else + { + b->match = r->match; + b_match = ARC_TO_EDGE_PTR(b->match); + } + REAL b_match_slack = 0; // initialize to prevent compiler warning + if (b_match && ARC_HEAD(b->match)->is_blossom) + { + b_match_slack = b_match->slack; + b_match->slack = ARC_HEAD(b->match)->y; + } + + // second pass over nodes in the blossom + branch = 0; + a_prev = EDGE_DIR_TO_ARC(a0, 0); + i = ARC_HEAD(a_prev); + while ( 1 ) + { + // update Arc::next and Arc::head pointers + if (i->flag == 0) i->y += eps; + else i->y -= eps; + i->is_processed = 0; + + if (i->flag == 1) + { + Edge* a_prev; + for (dir=0; dir<2; dir++) + if (i->first[dir]) + { + for (a_inner_ptr=&i->first[dir], a=*a_inner_ptr, a_prev=a->prev[dir], a_prev->next[dir]=NULL; a; a=*a_inner_ptr) + { + Node* j0 = a->head[dir]; + for (j=j0; !j->is_outer && !j->is_marked; j = j->blossom_parent) {} + if (j != j0) { /*assert(j->flag == 0);*/ int dir_rev = 1 - dir; MOVE_EDGE(j0, j, a, dir_rev); } + if (j->is_marked) // "inner" arc + { + a_inner_ptr = &a->next[dir]; + a->prev[dir] = a_prev; + a_prev = a; + + if (j->flag == 1) a->slack += eps; + } + else // "boundary" arc + { + *a_inner_ptr = a->next[dir]; + ADD_EDGE(b, a, dir); + + if (j->flag == 0 && j->tree != t) + { + j->tree->pq_current->pq01[1-j->tree->dir_current].Remove(a, pq_buf); + if (a->slack + eps <= j->tree->eps) a_augment = a; + } + a->slack += 2*eps; + if (j->flag == 2) t->pq0.Add(a); + else if (j->flag == 0) + { + if (!j->tree->pq_current) AddTreeEdge(t, j->tree); + j->tree->pq_current->pq00.Add(a); + } + else if (j->tree != t) + { + if (!j->tree->pq_current) AddTreeEdge(t, j->tree); + j->tree->pq_current->pq01[j->tree->dir_current].Add(a); + } + } + } + if (i->first[dir]) + { + a_prev->next[dir] = i->first[dir]; + i->first[dir]->prev[dir] = a_prev; + } + } + } + + Arc* a_next = (i->flag == 0) ? i->match : i->tree_parent; + i->blossom_parent = b; + i->match = NULL; + i->blossom_grandparent = b; + i->blossom_selfloops = NULL; + if (branch == 0) + { + i->blossom_sibling = a_next; + if (i == r) + { + branch = 1; + a_prev = ARC_REV(a0); + i = ARC_HEAD(a_prev); + if (i == r) break; + } + else + { + a_prev = i->blossom_sibling; + i = ARC_HEAD(a_prev); + } + } + else + { + i->blossom_sibling = ARC_REV(a_prev); + a_prev = a_next; + i = ARC_HEAD(a_prev); + if (i == r) break; + } + } + i->blossom_sibling = ARC_REV(a_prev); + r->is_tree_root = 0; + + for (i=ARC_HEAD(r->blossom_sibling); ; i = ARC_HEAD(i->blossom_sibling)) + { + i->is_marked = 0; + i->blossom_eps = eps; + if (i == r) break; + } + + if (b_match) + { + if (ARC_HEAD(b->match)->is_blossom) + { + b_match->slack = b_match_slack; + } + dir = ARC_TO_EDGE_DIR(b->match); + //assert(b_match->head[1-dir] == r); + MOVE_EDGE(r, b, b_match, dir); + } + + stat.shrink_count ++; + blossom_num ++; + stat.shrink_time += get_time() - start_time; + + if (a_augment) Augment(a_augment); +} + diff --git a/src/blossom5/PerfectMatching.h b/src/blossom5/PerfectMatching.h new file mode 100644 index 0000000..459f475 --- /dev/null +++ b/src/blossom5/PerfectMatching.h @@ -0,0 +1,232 @@ +/* + PerfectMatching.h - interface to min cost perfect matching code + + Copyright 2008 Vladimir Kolmogorov (vnk@adastral.ucl.ac.uk) + + This software can be used for research and evaluation purposes only. Commercial use is prohibited. + Public redistribution of the code or its derivatives is prohibited. + If you use this software for research purposes, you should cite the following paper in any resulting publication: + Vladimir Kolmogorov. "Blossom V: A new implementation of a minimum cost perfect matching algorithm." + In Mathematical Programming Computation (MPC), July 2009, 1(1):43-67. + + For commercial use of the software not covered by this agreement, please contact the author. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef HALSKDJDFHALSJASFDFASJGLA +#define HALSKDJDFHALSJASFDFASJGLA + +#include +#include +#include "blossom5/block.h" + + +// if defined, edge costs are of type 'double', otherwise 'int' +//#define PERFECT_MATCHING_DOUBLE + +// Note: with floating point numbers polynomial complexity is not guaranteed; +// the code may even get stuck due to rounding errors. If the code terminates, +// the solution may not be optimal. It may be worth calling CheckPerfectMatchingOptimality() +// to see whether complementary slackness conditions are satisfied. +// +// Using single precision floating point numbers (float) is really not recommended. + + +class PerfectMatching +{ +public: + +#ifdef PERFECT_MATCHING_DOUBLE + typedef double REAL; + #define PM_INFTY ((REAL)1e100) +#else + typedef int REAL; + #define PM_INFTY (INT_MAX/2) +#endif + + typedef int NodeId; + typedef int EdgeId; + + PerfectMatching(int nodeNum, int edgeNumMax); + ~PerfectMatching(); + + // first call returns 0, second 1, and so on. + EdgeId AddEdge(NodeId i, NodeId j, REAL cost); + + // Computes a perfect matching of minimum cost. + // NOTE: a perfect matching of finite cost must exist (otherwise the behaviour is not specified). + // If finish is false, then the final matching is not computed (so GetSolution() cannot be called afterwards). + void Solve(bool finish=true); + + /////////////////////////////////////////////////////////////// + // Read primal solution (can be called after Solve()). + int GetSolution(EdgeId e); // returns 1 if e is in the matching, 0 otherwise + NodeId GetMatch(NodeId i); // alternative way to get the result + + /////////////////////////////////////////////////////////////// + // Read dual solution (can be called after Solve()). + // 'blossom_parents' and 'twice_y' must be arrays of size node_num+GetBlossomNum(). + // The function sets blossom_parent[i] to the parent of i (or to -1 for exterior nodes). + void GetDualSolution(int* blossom_parents, REAL* twice_y); + int GetBlossomNum(); + + /////////////////////////////////////////////////////////////// + // Dynamic graph updates. After calling Solve() you may call // + // StartUpdate(), ..., FinishUpdate() and then Solve() again // + /////////////////////////////////////////////////////////////// + void StartUpdate(); + void FinishUpdate(); + + // 3 functions below can be called only between StartUpdate() and FinishUpdate(). + REAL GetTwiceSum(NodeId i); // if 2*cost(i,j)>=GetTwiceSum(i)+GetTwiceSum(j) then adding new edge (i,j) is not necessary - optimal solution will not change + EdgeId AddNewEdge(NodeId i, NodeId j, REAL cost, bool do_not_add_if_positive_slack=true); // if do_not_add_if_positive_slack is true and the slack of the edge turns out to be non-negative, then the edge will not be added and -1 will be returned + void UpdateCost(EdgeId e, REAL delta_cost); + + + // NOTE: with default options the dual vector is guaranteed to be half-integral + // (if all input weights are integral). However, with some options there is + // no such guarantee, in particular, if dual_greedy_update_option=2 or dual_LP_threshold>0. + // These options can be used only if the code is compiled with REAL=double. + struct Options + { + Options() : fractional_jumpstart(true), + dual_greedy_update_option(0), + dual_LP_threshold(0.00), + update_duals_before(false), + update_duals_after(false), + single_tree_threshold(1.00), + verbose(true) + {} + + bool fractional_jumpstart; // false: greedy, true: compute fractional matching + + int dual_greedy_update_option; // 0: compute connected components (as in Blossom IV) + // 1: compute strongly connected components (discussed by Cook-Rohe, but not implemented) + // 2: single eps for all trees (fixed eps approach) + + double dual_LP_threshold; // if tree_num => dual_updates_threshold*node_num: greedy updates + // if tree_num < dual_updates_threshold*node_num: global updates (solve LP) + + bool update_duals_before; // before tree growth + bool update_duals_after; // after tree growth + + double single_tree_threshold; // if (tree_num => single_tree_threshold*node_num && update_duals_after): try to grow a single tree as long as possible + + bool verbose; + } options; + + + // save problem to a file. format=0 corresponds to DIMACS format, + // format=1 corresponds to the format used by blossom4. + // CANNOT BE CALLED AFTER Solve()!!! + void Save(char* filename, int format=0); + + ////////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////// +private: + struct Node; + struct Arc; // no such struct, only Arc* is used (the pointer can be odd or even) + struct Edge; // pointer Edge* is always even + struct Tree; + struct TreeEdge; + struct PQPointers; + struct EdgeIterator; + struct TreeEdgeIterator; + struct LCATreeX; + + Node* nodes; + Edge* edges; + char* edges_orig; + DBlock* blossoms; + Tree* trees; + DBlock* tree_edges; + struct ExpandTmpItem + { + Node* i; + Node* blossom_parent; + Node* blossom_grandparent; + }; + Block* expand_tmp_list; // used inside Expand() + + int node_num; + int edge_num, edge_num_max; + int tree_num, tree_num_max; + + Node* removed_first; + int blossom_num; + int removed_num; + + void* pq_buf; + + bool first_solve; + + // stat + struct Stat + { + int shrink_count; + int expand_count; + int grow_count; + double shrink_time; + double expand_time; + double dual_time; + } stat; + + //////////////////////////////////////////////////////////////////// + + void InitGreedy(bool allocate_trees=true); + + void InitGlobal(); // compute fractional matching + Node* FindBlossomRootInit(Edge* a0); + void ShrinkInit(Edge* a0, Node* tree_root); + void ExpandInit(Node* b); + void AugmentBranchInit(Node* i0, Node* tree_root); + + void Finish(); // sets matching for inner nodes + + void ProcessNegativeEdge(Edge* a); + + void GetRealEndpoints(Edge* a, Node*& tail, Node*& head); + Node* FindBlossomRoot(Edge* a0); + void Shrink(Edge* a0); + void Expand(Node* b); + void Augment(Edge* a0); + void AugmentBranch(Node* i0); + void GrowNode(Node* i); + void GrowTree(Node* root, bool new_subtree); + bool ProcessEdge00(Edge* a, bool update_boundary_edge=true); // returns true if boundary edge, false otherwise + void ProcessSelfloop(Node* b, Edge* a); + + void AddTreeEdge(Tree* t0, Tree* t1); + + void ComputeEpsSingle(); // called from UpdateDuals() + void ComputeEpsCC(); // called from UpdateDuals() + void ComputeEpsSCC(); // called from UpdateDuals() + void ComputeEpsGlobal(); // called from UpdateDuals() + bool UpdateDuals(); + + void FreeRemoved(); + void CommitEps(); + + void ReallocateEdges(); + + void PrintAll(); +}; + + +#include "blossom5/CheckPerfectMatching.h" + +#endif diff --git a/src/blossom5/README.TXT b/src/blossom5/README.TXT new file mode 100644 index 0000000..5e3492d --- /dev/null +++ b/src/blossom5/README.TXT @@ -0,0 +1,78 @@ +BLOSSOM V - implementation of Edmonds' algorithm for computing a minimum cost perfect matching in a graph +Version 2.02 +http://www.cs.ucl.ac.uk/staff/V.Kolmogorov/software.html + +Details of the implementation are described in + + Vladimir Kolmogorov. "Blossom V: A new implementation of a minimum cost perfect matching algorithm." + In Mathematical Programming Computation (MPC), July 2009, 1(1):43-67. + +Please send comments to vnk@adastral.ucl.ac.uk. +If you use this software for research purposes, you should cite the aforementioned paper in any resulting publication. + +################################################################## + +License & disclaimer: + + Copyright 2008-2009 Vladimir Kolmogorov (vnk@adastral.ucl.ac.uk) + + This software can be used for research and evaluation purposes only. Commercial use is prohibited. + Public redistribution of the code or its derivatives is prohibited. + If you use this software for research purposes, you should cite the following paper in any resulting publication: + Vladimir Kolmogorov. "Blossom V: A new implementation of a minimum cost perfect matching algorithm." + In Mathematical Programming Computation (MPC), July 2009, 1(1):43-67. + + For commercial use of the software not covered by this agreement, please contact the author. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +################################################################## + +COMPILATION: + +In unix, type "make". The code should also compile in Windows with Microsoft Visual C++ compiler. +Tested on 32-bit machines. + +################################################################## + +USAGE: + +See PerfectMatching.h for interface functions. Alternatively, +compile the code and run ./blossom5 [options] (see USAGE.TXT for details). + +The code also allows solving complete geometric instances; see GEOM/GeomPerfectMatching.h +for interface functions. + +################################################################## + +PARAMETERS: + +For many types of problems, default parameters should be ok. +But for certain problems (such as structured geometric instances) +you may consider setting +dual_LP_threshold=0.005 (for example). This corresponds to calling +./blossom5 -m0.005 +Type PerfectMatching::REAL in PerfectMatcing.h should then be set to double. + +################################################################## + +EXTERNAL PACKAGE: + +When solving complete geometric instances you need to provide the initial subset of edges. +It may be desirable to use Delaunay triangulation for this purpose. +Then you need to download the "Triangle" package of J. R. Shewchuk from + http://www.cs.cmu.edu/~quake/triangle.html +and extract it to the directory "triange". +Alternatively, you can use nearest neighbours initialization (this does not require external packages). + diff --git a/src/blossom5/USAGE.TXT b/src/blossom5/USAGE.TXT new file mode 100644 index 0000000..afe93cd --- /dev/null +++ b/src/blossom5/USAGE.TXT @@ -0,0 +1,31 @@ +USAGE: ./blossom5 [options] + +At least one of the two flags below must be provided. +If both are provided, then edges in are added to the initial subset of edges for the geometric problem. + + -e read problem (list of edges) from file in DIMACS or blossom4 format + (see GRAPH1.TXT and GRAPH2.TXT for examples) + -g read geometric problem (list of 2D points) from file in TSPLIB format + +perfect matching parameters: + + -j do not use fractional jumpstart + -m# update duals by solving LP if the number of trees is smaller than # times node_num. + (# should belong to [0,1], default is 0.) + -d1 use SCC dual updates instead of CC + -d2 use dual updates with fixed delta instead of CC + -b update duals before processing a tree + -a update duals after processing a tree + +geometric matching parameters: + + -D do NOT add Delaunay triangulation to the initial subset of edges + -K# for each point, add # nearest neighbors to the initial subset of edges + -I do NOT add edges greedily to the initial subset of edges to make sure that a perfect matching exists + -T# use at most # iterations (or run until convergence, if #=0 - default) + +other options: + + -w save result to file + -c check complementary slackness conditions for non-geometric problem + -V no verbose diff --git a/src/blossom5/block.h b/src/blossom5/block.h new file mode 100644 index 0000000..7b6e696 --- /dev/null +++ b/src/blossom5/block.h @@ -0,0 +1,268 @@ +/* block.h */ +/* + Template classes Block and DBlock + Implement adding and deleting items of the same type in blocks. + + If there there are many items then using Block or DBlock + is more efficient than using 'new' and 'delete' both in terms + of memory and time since + (1) On some systems there is some minimum amount of memory + that 'new' can allocate (e.g., 64), so if items are + small that a lot of memory is wasted. + (2) 'new' and 'delete' are designed for items of varying size. + If all items has the same size, then an algorithm for + adding and deleting can be made more efficient. + (3) All Block and DBlock functions are inline, so there are + no extra function calls. + + Differences between Block and DBlock: + (1) DBlock allows both adding and deleting items, + whereas Block allows only adding items. + (2) Block has an additional operation of scanning + items added so far (in the order in which they were added). + (3) Block allows to allocate several consecutive + items at a time, whereas DBlock can add only a single item. + + Note that no constructors or destructors are called for items. + + Example usage for items of type 'MyType': + + /////////////////////////////////////////////////// + #include "blossom5/block.h" + #define BLOCK_SIZE 1024 + typedef struct { int a, b; } MyType; + MyType *ptr, *array[10000]; + + ... + + Block *block = new Block(BLOCK_SIZE); + + // adding items + for (int i=0; i New(); + ptr -> a = ptr -> b = rand(); + } + + // reading items + for (ptr=block->ScanFirst(); ptr; ptr=block->ScanNext()) + { + printf("%d %d\n", ptr->a, ptr->b); + } + + delete block; + + ... + + DBlock *dblock = new DBlock(BLOCK_SIZE); + + // adding items + for (int i=0; i New(); + } + + // deleting items + for (int i=0; i Delete(array[i]); + } + + // adding items + for (int i=0; i New(); + } + + delete dblock; + + /////////////////////////////////////////////////// + + Note that DBlock deletes items by marking them as + empty (i.e., by adding them to the list of free items), + so that this memory could be used for subsequently + added items. Thus, at each moment the memory allocated + is determined by the maximum number of items allocated + simultaneously at earlier moments. All memory is + deallocated only when the destructor is called. +*/ + +#ifndef __BLOCK_H__ +#define __BLOCK_H__ + +#include + +/***********************************************************************/ +/***********************************************************************/ +/***********************************************************************/ + +template class Block +{ +public: + /* Constructor. Arguments are the block size and + (optionally) the pointer to the function which + will be called if allocation failed; the message + passed to this function is "Not enough memory!" */ + Block(int size, void (*err_function)(const char *) = NULL) { first = last = NULL; block_size = size; error_function = err_function; } + + /* Destructor. Deallocates all items added so far */ + ~Block() { while (first) { block *next = first -> next; delete[] ((char*)first); first = next; } } + + /* Allocates 'num' consecutive items; returns pointer + to the first item. 'num' cannot be greater than the + block size since items must fit in one block */ + Type *New(int num = 1) + { + Type *t; + + if (!last || last->current + num > last->last) + { + if (last && last->next) last = last -> next; + else + { + block *next = (block *) new char [sizeof(block) + (block_size-1)*sizeof(Type)]; + if (!next) { if (error_function) (*error_function)("Not enough memory!"); exit(1); } + if (last) last -> next = next; + else first = next; + last = next; + last -> current = & ( last -> data[0] ); + last -> last = last -> current + block_size; + last -> next = NULL; + } + } + + t = last -> current; + last -> current += num; + return t; + } + + /* Returns the first item (or NULL, if no items were added) */ + Type *ScanFirst() + { + for (scan_current_block=first; scan_current_block; scan_current_block = scan_current_block->next) + { + scan_current_data = & ( scan_current_block -> data[0] ); + if (scan_current_data < scan_current_block -> current) return scan_current_data ++; + } + return NULL; + } + + /* Returns the next item (or NULL, if all items have been read) + Can be called only if previous ScanFirst() or ScanNext() + call returned not NULL. */ + Type *ScanNext() + { + while (scan_current_data >= scan_current_block -> current) + { + scan_current_block = scan_current_block -> next; + if (!scan_current_block) return NULL; + scan_current_data = & ( scan_current_block -> data[0] ); + } + return scan_current_data ++; + } + + /* Marks all elements as empty */ + void Reset() + { + block *b; + if (!first) return; + for (b=first; ; b=b->next) + { + b -> current = & ( b -> data[0] ); + if (b == last) break; + } + last = first; + } + +/***********************************************************************/ + +private: + + typedef struct block_st + { + Type *current, *last; + struct block_st *next; + Type data[1]; + } block; + + int block_size; + block *first; + block *last; + + block *scan_current_block; + Type *scan_current_data; + + void (*error_function)(const char *); +}; + +/***********************************************************************/ +/***********************************************************************/ +/***********************************************************************/ + +template class DBlock +{ +public: + /* Constructor. Arguments are the block size and + (optionally) the pointer to the function which + will be called if allocation failed; the message + passed to this function is "Not enough memory!" */ + DBlock(int size, void (*err_function)(const char *) = NULL) { first = NULL; first_free = NULL; block_size = size; error_function = err_function; } + + /* Destructor. Deallocates all items added so far */ + ~DBlock() { while (first) { block *next = first -> next; delete[] ((char*)first); first = next; } } + + /* Allocates one item */ + Type *New() + { + block_item *item; + + if (!first_free) + { + block *next = first; + first = (block *) new char [sizeof(block) + (block_size-1)*sizeof(block_item)]; + if (!first) { if (error_function) (*error_function)("Not enough memory!"); exit(1); } + first_free = & (first -> data[0] ); + for (item=first_free; item next_free = item + 1; + item -> next_free = NULL; + first -> next = next; + } + + item = first_free; + first_free = item -> next_free; + return (Type *) item; + } + + /* Deletes an item allocated previously */ + void Delete(Type *t) + { + ((block_item *) t) -> next_free = first_free; + first_free = (block_item *) t; + } + +/***********************************************************************/ + +private: + + typedef union block_item_st + { + Type t; + block_item_st *next_free; + } block_item; + + typedef struct block_st + { + struct block_st *next; + block_item data[1]; + } block; + + int block_size; + block *first; + block_item *first_free; + + void (*error_function)(const char *); +}; + + +#endif + diff --git a/src/blossom5/example.cpp b/src/blossom5/example.cpp new file mode 100644 index 0000000..16c962e --- /dev/null +++ b/src/blossom5/example.cpp @@ -0,0 +1,285 @@ +#include +#include "PerfectMatching.h" +#include "GEOM/GeomPerfectMatching.h" + +void LoadFile(int& node_num, int& edge_num, int*& edges, int*& weights, char* filename) +{ + int e = 0; + char LINE[1000]; + FILE* fp = fopen(filename, "r"); + if (!fp) { printf("Can't open %s\n", filename); exit(1); } + + int format = -1; // 0: DIMACS format. node id's start from 1 + // 1: simpler format (without "p" and "e"). node id's start from 0 + + edge_num = -1; + while (fgets(LINE, sizeof(LINE)-1, fp)) + { + if (LINE[0] == 'c') continue; + if (format < 0) + { + if (LINE[0] == 'p') + { + format = 0; + if (sscanf(LINE, "p edge %d %d\n", &node_num, &edge_num) != 2) { printf("%s: wrong format #1\n", filename); exit(1); } + } + else + { + format = 1; + if (sscanf(LINE, "%d %d\n", &node_num, &edge_num) != 2) { printf("%s: wrong format #1\n", filename); exit(1); } + } + + ////////////////////////////////////////////////////////////////////////////////// + if (node_num <= 0 || edge_num < 0) { printf("# of nodes and edges should be positive\n"); exit(1); } + if (node_num & 1) { printf("# of nodes is odd: perfect matching cannot exist\n"); exit(1); } + edges = new int[2*edge_num]; + weights = new int[edge_num]; + ////////////////////////////////////////////////////////////////////////////////// + } + else + { + int i, j; + char* ptr = LINE; + if (format == 0) { if (LINE[0] != 'e') continue; ptr = &LINE[1]; } + else ptr = &LINE[0]; + + int len; + if (sscanf(ptr, "%d %d %d\n", &i, &j, &len) != 3) continue; + if (format == 0) { i --; j --; } + edges[2*e] = i; + edges[2*e+1] = j; + weights[e] = len; + e ++; + } + } + + if (e != edge_num) { printf("%s: wrong format #3\n", filename); exit(1); } + fclose(fp); +} + +void SaveMatching(int node_num, PerfectMatching* pm, char* filename) +{ + FILE* fp = fopen(filename, "w"); + if (!fp) { printf("Can't open %s\n", filename); exit(1); } + fprintf(fp, "%d %d\n", node_num, node_num/2); + int i, j; + for (i=0; iGetMatch(i); + if (i < j) fprintf(fp, "%d %d\n", i, j); + } + fclose(fp); +} + +void LoadGeomFile(int& node_num, int*& x_array, int*& y_array, char* filename) +{ + int i = 0, i_tmp, x, y, DIM = 0; + char LINE[1000]; + + x_array = y_array = NULL; + + FILE* fp = fopen(filename, "r"); + if (!fp) { printf("Can't open %s\n", filename); exit(1); } + + while (fgets(LINE, sizeof(LINE)-1, fp)) + { + if (sscanf(LINE, "DIMENSION : %d", &node_num) == 1) + { + if (node_num < 1) { printf("too few nodes\n"); exit(1); } + if (node_num & 1) { printf("# of points is odd: perfect matching cannot exist\n"); exit(1); } + if (x_array) { printf("wrong format\n"); exit(1); } + x_array = new int[node_num]; + y_array = new int[node_num]; + continue; + } + if (sscanf(LINE, "EDGE_WEIGHT_TYPE : EUC_%dD", &DIM) == 1) + { + if (DIM != 2) { printf("only EUC_2D is supported"); exit(1); } + continue; + } + if (sscanf(LINE, "%d %d %d", &i_tmp, &x, &y) == 3) + { + i_tmp --; + if (i_tmp != i ++ || i > node_num) { printf("wrong number of points\n"); exit(1); } + x_array[i_tmp] = x; + y_array[i_tmp] = y; + continue; + } + printf("%s", LINE); + } + fclose(fp); + if (i != node_num || !x_array || DIM != 2) { printf("wrong format\n"); exit(1); } +} + + +void SaveMatching(int node_num, GeomPerfectMatching* gpm, char* filename) +{ + FILE* fp = fopen(filename, "w"); + if (!fp) { printf("Can't open %s\n", filename); exit(1); } + fprintf(fp, "%d %d\n", node_num, node_num/2); + int i, j; + for (i=0; iGetMatch(i); + if (i < j) + { + GeomPerfectMatching::REAL len = gpm->Dist(i, j); + if ( ((GeomPerfectMatching::REAL)1 / 2) == 0 ) fprintf(fp, "%d %d %d\n", i, j, len); + else fprintf(fp, "%d %d %f\n", i, j, (double)len); + } + } + fclose(fp); +} + + +void ShowUsage() +{ + printf("Usage: see USAGE.TXT\n"); + exit(1); +} + + +int main(int argc, char* argv[]) +{ + struct PerfectMatching::Options options; + struct GeomPerfectMatching::GPMOptions gpm_options; + char* filename = NULL; + char* geom_filename = NULL; + char* save_filename = NULL; + bool check_perfect_matching = false; + int i, e, node_num, edge_num; + int* edges; + int* weights; + + for (i=1; i1) ShowUsage(); + break; + case 'd': + options.dual_greedy_update_option = atoi(&argv[i][2]); + if (options.dual_greedy_update_option<1 || options.dual_greedy_update_option>2) ShowUsage(); + break; + case 'b': + if (argv[i][2]) ShowUsage(); + options.update_duals_before = true; + break; + case 'a': + if (argv[i][2]) ShowUsage(); + options.update_duals_after = true; + break; + case 'D': + if (argv[i][2]) ShowUsage(); + gpm_options.init_Delaunay = false; + break; + case 'K': + gpm_options.init_KNN = atoi(&argv[i][2]); + if (gpm_options.init_KNN<0) ShowUsage(); + break; + case 'I': + if (argv[i][2]) ShowUsage(); + gpm_options.init_greedy = false; + break; + case 'T': + gpm_options.iter_max = atoi(&argv[i][2]); + if (gpm_options.iter_max<0) ShowUsage(); + break; + case 'w': + if (save_filename || argv[i][2] || ++i == argc) ShowUsage(); + save_filename = argv[i]; + break; + case 'c': + if (argv[i][2]) ShowUsage(); + check_perfect_matching = true; + break; + case 'V': + if (argv[i][2]) ShowUsage(); + options.verbose = false; + break; + default: + printf("Unknown option: %s\n", argv[i]); + ShowUsage(); + break; + } + + } + + if (!filename && !geom_filename) ShowUsage(); + + if (filename) LoadFile(node_num, edge_num, edges, weights, filename); + + if (!geom_filename) + { + PerfectMatching *pm = new PerfectMatching(node_num, edge_num); + for (e=0; eAddEdge(edges[2*e], edges[2*e+1], weights[e]); + pm->options = options; + pm->Solve(); + if (check_perfect_matching) + { + int res = CheckPerfectMatchingOptimality(node_num, edge_num, edges, weights, pm); + printf("check optimality: res=%d (%s)\n", res, (res==0) ? "ok" : ((res==1) ? "error" : "fatal error")); + } + double cost = ComputePerfectMatchingCost(node_num, edge_num, edges, weights, pm); + printf("cost = %.1f\n", cost); + if (save_filename) SaveMatching(node_num, pm, save_filename); + delete pm; + } + else + { + int geom_node_num; + int* x_array; + int* y_array; + LoadGeomFile(geom_node_num, x_array, y_array, geom_filename); + GeomPerfectMatching *gpm = new GeomPerfectMatching(geom_node_num, 2); + for (i=0; iAddPoint(coord); + } + delete [] x_array; + delete [] y_array; + gpm->options = options; + gpm->gpm_options = gpm_options; + if (filename) + { + if (node_num != geom_node_num) { printf("%s and %s don't match!\n", geom_filename, filename); exit(1); } + for (e=0; eDist(edges[2*e], edges[2*e+1])) + { printf("edge lengths in %s and %s don't match!\n", geom_filename, filename); exit(1); } + gpm->AddInitialEdge(edges[2*e], edges[2*e+1]); + } + } + gpm->Solve(); + if (save_filename) SaveMatching(geom_node_num, gpm, save_filename); + delete gpm; + } + + if (filename) + { + delete [] edges; + delete [] weights; + } + + return 0; +} + + diff --git a/src/blossom5/timer.h b/src/blossom5/timer.h new file mode 100644 index 0000000..6c3917f --- /dev/null +++ b/src/blossom5/timer.h @@ -0,0 +1,98 @@ +#ifndef NJAKSDTHASKJERAXJGFBZJDLAGZ +#define NJAKSDTHASKJERAXJGFBZJDLAGZ + +#include + +// At most one of the flags +// PM_TIMER_MSVC +// PM_TIMER_CLOCK_GETTIME +// PM_TIMER_GETRUSAGE +// PM_TIMER_EXTERNAL +// PM_TIMER_NONE +// can be defined externally. If PM_TIMER_EXTERNAL is defined, +// then there must exist a definition of function "double get_time()" elsewhere. + +#if defined (PM_TIMER_MSVC) || defined (PM_TIMER_CLOCK_GETTIME) || defined (PM_TIMER_GETRUSAGE) || defined (PM_TIMER_EXTERNAL) || defined (PM_TIMER_NONE) +#else + // default option + #ifdef _MSC_VER + #define PM_TIMER_MSVC + #else + #define PM_TIMER_CLOCK_GETTIME + #endif +#endif + +////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////// + +#ifdef PM_TIMER_MSVC + + #include + + inline double get_time() + { + LARGE_INTEGER t, frequency; + QueryPerformanceCounter(&t); + QueryPerformanceFrequency(&frequency); + return (double)t.QuadPart/(double)frequency.QuadPart; + } + +#endif + +////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////// + +#ifdef PM_TIMER_CLOCK_GETTIME + + #include + + inline double get_time() + { + struct timespec t; + clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &t); + return (double)t.tv_nsec*1.00E-9 + (double)t.tv_sec; + } + +#endif + +////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////// + +#ifdef PM_TIMER_GETRUSAGE + + #include + + inline double get_time() + { + struct rusage t; + getrusage (RUSAGE_SELF, &t); + return (double)t.ru_utime.tv_usec*1.00E-6 + (double)t.ru_utime.tv_sec; + } + +#endif + +////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////// + +#ifdef PM_TIMER_EXTERNAL + + extern double get_time(); + +#endif + +////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////// + +#ifdef PM_TIMER_NONE + + inline double get_time() { return 0; } + +#endif + +#endif + diff --git a/src/bts/analysis/fisher_gradient_matrix_tester.h b/src/bts/analysis/fisher_gradient_matrix_tester.h new file mode 100644 index 0000000..6de678f --- /dev/null +++ b/src/bts/analysis/fisher_gradient_matrix_tester.h @@ -0,0 +1,121 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS is free software: you can reobjectibute 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. + + BTS is objectibuted 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 BTS. If not, see . + + */ + + +#ifndef __bts_analysis_fishergradientmatrixtester_h__ +#define __bts_analysis_fishergradientmatrixtester_h__ + + +#include "bts/mcmc/state/tensor.h" +#include "bts/triple.h" + + + +namespace BTS { + + namespace Analysis { + + + template class FisherGradientMatrixTester { + + + public: + + //typedef the pointer to the function to test as 'Function'. + typedef double (Object::*Function)(const State&, State&, typename State::Tensor&, std::vector&); + + protected: + + Object *object; + + public: + + FisherGradientMatrixTester(Object& object) + : object(&object) {} + + + ~FisherGradientMatrixTester() {} + + void test(Function function, State& state, double step_size, std::vector& analytic_fisher_gradient, std::vector& numeric_fisher_gradient); + + }; + + + } + +} + + + +#include "progressbar.h" +#include "math/vector.h" +#include "math/matrix.h" + + +namespace BTS { + + namespace Analysis { + + template void FisherGradientMatrixTester::test(Function function, State& state, double step_size, std::vector& analytic_fisher_gradient, std::vector& numeric_fisher_gradient) { + + State dummy_gradient(state); + typename State::Tensor fisher(state), perturbed_fisher(state); + std::vector dummy_fisher_gradient; + + fisher.invalidate(); + + numeric_fisher_gradient.clear(); + + (*object.*function)(state, dummy_gradient, fisher, analytic_fisher_gradient); + + MR::Math::Vector& state_vector = state; + + MR::ProgressBar progress_bar ("Testing fisher_gradient calculations...", state_vector.size()); + + for (size_t elem_i = 0; elem_i < state_vector.size(); ++elem_i) { + + perturbed_fisher.invalidate(); + + state_vector[elem_i] += step_size; + + (*object.*function)(state, dummy_gradient, perturbed_fisher, dummy_fisher_gradient); + + state_vector[elem_i] -= step_size; + + numeric_fisher_gradient.push_back(perturbed_fisher); + numeric_fisher_gradient.back() -= fisher; + numeric_fisher_gradient.back() /= step_size; + + ++progress_bar; + + } + + } + + + } + +} + + + +#endif diff --git a/src/bts/analysis/fisher_gradient_tester.h b/src/bts/analysis/fisher_gradient_tester.h new file mode 100644 index 0000000..9b4f9ea --- /dev/null +++ b/src/bts/analysis/fisher_gradient_tester.h @@ -0,0 +1,122 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS is free software: you can reobjectibute 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. + + BTS is objectibuted 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 BTS. If not, see . + + */ + + +#ifndef __bts_analysis_fishergradienttester_h__ +#define __bts_analysis_fishergradienttester_h__ + + +#include "bts/mcmc/state/tensor.h" +#include "bts/triple.h" + + + +namespace BTS { + + namespace Analysis { + + + template class FisherGradientTester { + + + public: + + //typedef the pointer to the function to test as 'Function'. + typedef double (Object::*Function)(const State&, State&, typename State::Tensor&, std::vector&); + + protected: + + Object *object; + + public: + + FisherGradientTester(Object& object) + : object(&object) {} + + + ~FisherGradientTester() {} + + void test(Function function, State& state, double step_size, std::vector& analytic_fisher_gradient, std::vector& numeric_fisher_gradient); + + }; + + + } + +} + + + +#include "progressbar.h" +#include "math/vector.h" +#include "math/matrix.h" + + +namespace BTS { + + namespace Analysis { + + template void FisherGradientTester::test(Function function, State& state, double step_size, std::vector& analytic_fisher_gradient, std::vector& numeric_fisher_gradient) { + + State perturbed_state(state), dummy_gradient(state); + typename State::Tensor fisher(state), perturbed_fisher(state); + std::vector dummy_fisher_gradient; + + fisher.invalidate(); + perturbed_fisher.invalidate(); + + numeric_fisher_gradient.clear(); + + (*object.*function)(state, dummy_gradient, fisher, analytic_fisher_gradient); + + MR::Math::Vector& state_vector = state; + + MR::ProgressBar progress_bar ("Testing fisher_gradient calculations...", state_vector.size()); + + for (size_t elem_i = 0; elem_i < state_vector.size(); ++elem_i) { + + perturbed_fisher.invalidate(); + + state_vector[elem_i] += step_size; + + (*object.*function)(state, dummy_gradient, perturbed_fisher, dummy_fisher_gradient); + + state_vector[elem_i] -= step_size; + + numeric_fisher_gradient.push_back(perturbed_fisher); + numeric_fisher_gradient.back() -= fisher; + numeric_fisher_gradient.back() /= step_size; + + ++progress_bar; + + } + + } + + + } + +} + + + +#endif diff --git a/src/bts/analysis/gradient_tester.h b/src/bts/analysis/gradient_tester.h new file mode 100644 index 0000000..4dcf87f --- /dev/null +++ b/src/bts/analysis/gradient_tester.h @@ -0,0 +1,112 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS is free software: you can reobjectibute 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. + + BTS is objectibuted 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 BTS. If not, see . + + */ + + +#ifndef __bts_analysis_gradienttester_h__ +#define __bts_analysis_gradienttester_h__ + + +namespace BTS { + + namespace Analysis { + + + template class GradientTester { + + + public: + + //typedef the pointer to the function to test as 'Function'. + typedef double (Object::*Function)(const State, State); + + protected: + + Object *object; + + public: + + GradientTester(Object& object) + : object(&object) {} + + ~GradientTester() {} + + void test(Function function, State state, double step_size, State analytic_gradient, State numeric_gradient); + + + }; + + + } + +} + + + +#include "progressbar.h" +#include "math/vector.h" + + +namespace BTS { + + namespace Analysis { + + + template void GradientTester::test(Function function, State state, double step_size, State analytic_gradient, State numeric_gradient) { + + analytic_gradient = state; + analytic_gradient.invalidate(); + + double px = (*object.*function)(state, analytic_gradient); + + numeric_gradient = state; + numeric_gradient.invalidate(); + + MR::Math::Vector& state_vector = state; + MR::Math::Vector& gradient_vector = numeric_gradient; + + State dummy_gradient(state); + + MR::ProgressBar progress_bar ("Testing gradient calculations...", state_vector.size()); + + for (size_t elem_i = 0; elem_i < state_vector.size(); ++elem_i) { + + state_vector[elem_i] += step_size; + + gradient_vector[elem_i] = ((*object.*function)(state, dummy_gradient) - px) / step_size; + + state_vector[elem_i] -= step_size; + + ++progress_bar; + + } + + + } + + + } + +} + + + +#endif diff --git a/src/bts/analysis/hessian_tester.h b/src/bts/analysis/hessian_tester.h new file mode 100644 index 0000000..888cbcc --- /dev/null +++ b/src/bts/analysis/hessian_tester.h @@ -0,0 +1,124 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS is free software: you can reobjectibute 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. + + BTS is objectibuted 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 BTS. If not, see . + + */ + + +#ifndef __bts_analysis_hessiantester_h__ +#define __bts_analysis_hessiantester_h__ + + +#include "bts/mcmc/state/tensor.h" +#include "bts/triple.h" + + + +namespace BTS { + + namespace Analysis { + + + template class HessianTester { + + + public: + + //typedef the pointer to the function to test as 'Function'. + typedef double (Object::*Function)(const State&, State&, typename State::Tensor&); + + protected: + + Object *object; + + public: + + HessianTester(Object& object) + : object(&object) {} + + + ~HessianTester() {} + + void test(Function function, State& state, double step_size, typename State::Tensor& analytic_hessian, typename State::Tensor& numeric_hessian); + + }; + + + } + +} + + + +#include "progressbar.h" +#include "math/vector.h" +#include "math/matrix.h" + + +namespace BTS { + + namespace Analysis { + + template void HessianTester::test(Function function, State& state, double step_size, typename State::Tensor& analytic_hessian, typename State::Tensor& numeric_hessian) { + + State perturbed_state(state), gradient(state), perturbed_gradient(state); + + gradient.invalidate(); + + typename State::Tensor dummy_hessian(state); + + (analytic_hessian = typename State::Tensor(state)).invalidate(); + + (*object.*function)(state, gradient, analytic_hessian); + + MR::Math::Vector& state_vector = state; + + numeric_hessian.invalidate(); + + MR::ProgressBar progress_bar ("Testing hessian calculations...", state_vector.size()); + + for (size_t elem_i = 0; elem_i < state_vector.size(); ++elem_i) { + + perturbed_gradient.invalidate(); + + state_vector[elem_i] += step_size; + + (*object.*function)(state, perturbed_gradient, dummy_hessian); + + state_vector[elem_i] -= step_size; + + perturbed_gradient -= gradient; + perturbed_gradient /= step_size; + + numeric_hessian.row(elem_i) = perturbed_gradient; + + ++progress_bar; + + } + + } + + + } + +} + + + +#endif diff --git a/src/bts/analysis/image_gradient_tester.h b/src/bts/analysis/image_gradient_tester.h new file mode 100644 index 0000000..7f6efb9 --- /dev/null +++ b/src/bts/analysis/image_gradient_tester.h @@ -0,0 +1,149 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS is free software: you can reimageibute 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. + + BTS is imageibuted 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 BTS. If not, see . + + */ + + +#ifndef __bts_analysis_imagegradienttester_h__ +#define __bts_analysis_imagegradienttester_h__ + +namespace BTS { + + namespace Analysis { + + template class ImageGradientTester { + + + public: + + //typedef the pointer to the function to test as 'Function'. + typedef ImageClass& (ImageClass::*Function)(const State&, typename Image::Container::Buffer&); + + protected: + + ImageClass image; + + public: + + ImageGradientTester(const ImageClass& image) + : image(image) { this->image.clear_and_enforce_bounds(); } + + ~ImageGradientTester() {} + + void test(Function function, State& state, double step_size, Image::Container::Buffer& analytic_gradient, Image::Container::Buffer& numeric_gradient); + + + }; + + } + +} + + +#include "progressbar.h" + +#include "bts/common.h" +#include "bts/image/observed/buffer.h" + +#include "bts/analysis/image_gradient_tester.h" + + +namespace BTS { + + namespace Analysis { + + template + void ImageGradientTester::test(Function function, + State& state, + double step_size, + Image::Container::Buffer& analytic_gradient, + Image::Container::Buffer& numeric_gradient) { + + //Initialise gradient buffers. + + Image::Container::Buffer dummy_gradient (image.dims(), image.num_encodings()); + + analytic_gradient.reset(image.dims(), image.num_encodings()); + numeric_gradient.reset(image.dims(), image.num_encodings()); + + //Calculate analytic hessian and unperturbed gradient + + image.zero(); + + Image::Buffer image_intensities = (image.*function)(state, analytic_gradient); + + //Initialize state vector + + MR::Math::Vector& state_vector = state; + + Image::Container::Buffer< MR::Math::Vector > numeric_gradient_vectors (image.dims(), image.num_encodings()); + + for (size_t z = 0; z < image.dim(Z); z++) + for (size_t y = 0; y < image.dim(Y); y++) + for (size_t x = 0; x < image.dim(X); x++) + for (size_t encode_i = 0; encode_i < image.num_encodings(); encode_i++) + numeric_gradient_vectors(x,y,z)[encode_i].resize(state_vector.size(), 0.0); + + + MR::ProgressBar progress_bar ("Testing gradient calculations...", state_vector.size()); + + for (size_t elem_i = 0; elem_i < state_vector.size(); ++elem_i) { + + state_vector[elem_i] += step_size; + + image.zero(); + + ImageClass& perturbed_image_intensities = (image.*function)(state, dummy_gradient); + + for (Image::Buffer::iterator vox_it = image_intensities.begin(); vox_it != image_intensities.end(); ++vox_it) + for (size_t encode_i = 0; encode_i < image.num_encodings(); encode_i++) + if (!perturbed_image_intensities.is_empty(vox_it->first)) + numeric_gradient_vectors(vox_it->first)[encode_i][elem_i] = (perturbed_image_intensities(vox_it->first)[encode_i] - vox_it->second[encode_i]) / step_size; + + + state_vector[elem_i] -= step_size; + + ++progress_bar; + + } + + + for (size_t z = 0; z < image.dim(Z); z++) + for (size_t y = 0; y < image.dim(Y); y++) + for (size_t x = 0; x < image.dim(X); x++) { + + for (size_t encode_i = 0; encode_i < image.num_encodings(); encode_i++) { + numeric_gradient(x,y,z)[encode_i] = state; + numeric_gradient(x,y,z)[encode_i] = numeric_gradient_vectors(x,y,z)[encode_i]; + } + + if (analytic_gradient.is_empty(x,y,z)) + for (size_t encode_i = 0; encode_i < image.num_encodings(); encode_i++) + analytic_gradient(x,y,z)[encode_i] = State(state).zero(); + + } + + } + + } + +} + +#endif diff --git a/src/bts/analysis/image_hessian_tester.h b/src/bts/analysis/image_hessian_tester.h new file mode 100644 index 0000000..74ede60 --- /dev/null +++ b/src/bts/analysis/image_hessian_tester.h @@ -0,0 +1,152 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS is free software: you can reimageibute 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. + + BTS is imageibuted 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 BTS. If not, see . + + */ + + +#ifndef __bts_analysis_imagehessiantester_h__ +#define __bts_analysis_imagehessiantester_h__ + +namespace BTS { + + namespace Analysis { + + template class ImageHessianTester { + + + public: + + //typedef the pointer to the function to test as 'Function'. + typedef ImageClass& (ImageClass::*Function)(const State&, Image::Container::Buffer&, Image::Container::Buffer&); //, typename Image::Container::Buffer& + + protected: + + ImageClass image; + + public: + + ImageHessianTester(const ImageClass& image) + : image(image) { this->image.clear_and_enforce_bounds(); } + + ~ImageHessianTester() {} + + void test(Function function, State& state, double step_size, Image::Container::Buffer& analytic_hessian, Image::Container::Buffer& numeric_hessian); + + + }; + + } + +} + + +#include "progressbar.h" + +#include "bts/image/container/buffer.h" + +#include "bts/analysis/image_hessian_tester.h" + +namespace BTS { + + namespace Analysis { + + template void ImageHessianTester::test(Function function, State& state, double step_size, Image::Container::Buffer& analytic_hessian, Image::Container::Buffer& numeric_hessian) { + + Triple dims = analytic_hessian.dims(); + size_t num_encodings = analytic_hessian.num_encodings(); + + analytic_hessian.clear(); + numeric_hessian.clear(); + + Image::Container::Buffer dummy_hessian (analytic_hessian); + Image::Container::Buffer gradient(dims,num_encodings), perturbed_gradient(dims, num_encodings); + + //Calculate analytic hessian and unperturbed gradient + + gradient.zero(); + + (image.*function)(state, gradient, analytic_hessian); + + //Initialize + + + MR::Math::Vector& state_vector = state; + + typename State::Tensor state_tensor(state); + MR::Math::Matrix blank_tensor_matrix(state_vector.size(), state_vector.size()); + blank_tensor_matrix = 0.0; + + Image::Container::Buffer< MR::Math::Matrix > numeric_hessian_matrices (dims, num_encodings); + + for (size_t z = 0; z < image.dim(Z); z++) + for (size_t y = 0; y < image.dim(Y); y++) + for (size_t x = 0; x < image.dim(X); x++) + for (size_t encode_i = 0; encode_i < num_encodings; encode_i++) + numeric_hessian_matrices(x,y,z)[encode_i] = blank_tensor_matrix; + + + MR::ProgressBar progress_bar ("Testing hessian calculations...", state_vector.size()); + + State perturbed_state = state; + + for (size_t row_i = 0; row_i < state_vector.size(); ++row_i) { + + state_vector[row_i] += step_size; + + perturbed_gradient.zero(); + + (image.*function)(state, perturbed_gradient, dummy_hessian); + + for (typename Image::Container::Buffer::iterator vox_it = perturbed_gradient.begin(); vox_it != perturbed_gradient.end(); ++vox_it) + for (size_t encode_i = 0; encode_i < num_encodings; encode_i++) + numeric_hessian_matrices(vox_it->first)[encode_i].row(row_i) = ((vox_it->second[encode_i] - gradient(vox_it->first)[encode_i]) / step_size); + + + state_vector[row_i] -= step_size; + + ++progress_bar; + + } + + + for (size_t z = 0; z < image.dim(Z); z++) + for (size_t y = 0; y < image.dim(Y); y++) + for (size_t x = 0; x < image.dim(X); x++) { + + for (size_t encode_i = 0; encode_i < num_encodings; encode_i++) { + numeric_hessian(x,y,z)[encode_i] = state_tensor; + numeric_hessian(x,y,z)[encode_i] = numeric_hessian_matrices(x,y,z)[encode_i]; + } + + if (analytic_hessian.is_empty(x,y,z)) + for (size_t encode_i = 0; encode_i < image.num_encodings(); encode_i++) + analytic_hessian(x,y,z)[encode_i] = typename State::Tensor(state_tensor).zero(); + + } + + } + + + } +} + +#undef LOOP + +#endif diff --git a/src/bts/analysis/inline_functions.h b/src/bts/analysis/inline_functions.h new file mode 100644 index 0000000..d33668a --- /dev/null +++ b/src/bts/analysis/inline_functions.h @@ -0,0 +1,28 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, 16/07/2010. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + +#ifndef __bts_diffusion_inline_functions_h__ +#define __bts_diffusion_inline_functions_h__ + + + +#endif /* __bts_diffusion_inline_functions_h__ */ diff --git a/src/bts/analysis/rank3_hessian_tester.h b/src/bts/analysis/rank3_hessian_tester.h new file mode 100644 index 0000000..ed2bf24 --- /dev/null +++ b/src/bts/analysis/rank3_hessian_tester.h @@ -0,0 +1,134 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS is free software: you can reobjectibute 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. + + BTS is objectibuted 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 BTS. If not, see . + + */ + + +#ifndef __bts_analysis_rank3hessiantester_h__ +#define __bts_analysis_rank3hessiantester_h__ + +#include + + +#include "bts/mcmc/state/tensor.h" +#include "bts/triple.h" + + + + +namespace BTS { + + namespace Analysis { + + + template class Rank3HessianTester { + + + public: + + //typedef the pointer to the function to test as 'Function'. + typedef double (Object::*Function)(const State&, State&, typename State::Tensor&, std::vector&); + + protected: + + Object *object; + + public: + + Rank3HessianTester(Object& object) + : object(&object) {} + + + ~Rank3HessianTester() {} + + void test(Function function, State& state, double step_size, std::vector& analytic_rank3hessian, std::vector& numeric_rank3hessian); + + }; + + + } + +} + + + +#include "progressbar.h" +#include "math/vector.h" +#include "math/matrix.h" + + +namespace BTS { + + namespace Analysis { + + template void Rank3HessianTester::test(Function function, State& state, double step_size, std::vector& analytic_rank3hessian, std::vector& numeric_rank3hessian) { + + State perturbed_state(state), dummy_gradient(state); + + typename State::Tensor hessian(state), perturbed_hessian(state); + + hessian.invalidate(); + perturbed_hessian.invalidate(); + + std::vector dummy_rank3hessian; + + (*object.*function)(state, dummy_gradient, hessian, analytic_rank3hessian); + + MR::Math::Vector& state_vector = state; + + MR::Math::Matrix template_rank3hessian_matrix(state_vector.size(), state_vector.size()); + template_rank3hessian_matrix = NAN; + + + MR::ProgressBar progress_bar ("Testing rank3hessian calculations...", state_vector.size()); + + for (size_t elem_i = 0; elem_i < state_vector.size(); ++elem_i) { + + perturbed_hessian.invalidate(); + + state_vector[elem_i] += step_size; + + perturbed_state.from_vector(state_vector); + + (*object.*function)(perturbed_state, dummy_gradient, perturbed_hessian, dummy_rank3hessian); + + state_vector[elem_i] -= step_size; + + MR::Math::Matrix& perturbed_hessian_matrix = perturbed_hessian; + + perturbed_hessian_matrix -= hessian; + perturbed_hessian_matrix /= step_size; + + numeric_rank3hessian.push_back(perturbed_hessian_matrix); + + ++progress_bar; + + } + + } + + + } + +} + + + +#endif diff --git a/src/bts/analysis/scan.h b/src/bts/analysis/scan.h new file mode 100644 index 0000000..56fb93d --- /dev/null +++ b/src/bts/analysis/scan.h @@ -0,0 +1,373 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + + +#ifndef __bts_analysis_scan_h__ +#define __bts_analysis_scan_h__ + + +#include "bts/common.h" + +#include "progressbar.h" +#include "bts/prob/prior.h" +#include "bts/prob/likelihood.h" + +#include "image/header.h" +#include "dataset/loop.h" + + + +namespace BTS { + + namespace Analysis { + + template void scan ( + Prob::Likelihood& likelihood, + Prob::Prior& prior, + const T& origin, + const T& axis, + size_t num_steps, + const std::string& output_location, + std::map& run_properties); + + + template void scan ( + Prob::Likelihood& likelihood, + Prob::Prior& prior, + const Fibre::Base::Set& sequence, + const std::string& output_location, + std::map& run_properties); + + + template void scan ( + Prob::Likelihood& likelihood, + Prob::Prior& prior, + const T& origin, + const T& axis1, + const T& axis2, + size_t num_steps1, + size_t num_steps2, + const std::string& output_location, + std::map& properties + ); + + template void scan ( + Prob::Likelihood& likelihood, + Prob::Prior& prior, + const T& origin, + const T& axis1, + const T& axis2, + const T& axis3, + size_t num_steps1, + size_t num_steps2, + size_t num_steps3, + const std::string& output_location, + std::map& properties + ); + + } + +} + + +namespace BTS { + + namespace Analysis { + + + template void scan ( + Prob::Likelihood& likelihood, + Prob::Prior& prior, + const T& origin, + const T& axis, + size_t num_steps, + const std::string& output_location, + std::map& run_properties, + bool save_gradient) { + + if (origin.size() != axis.size()) + throw Exception ("Size of origin state (" + str(origin.size()) + ") does not match size of axis state (" + str(axis.size()) + ")."); + + std::string gradient_location = File::strip_extension(output_location) + ".gradient." + File::extension(output_location); + std::vector header; + header.push_back("log_px"); + header.push_back("likelihood_px"); + header.push_back("prior_px"); + header.push_back("acs_px"); + + std::vector components_list = prior.list_components(); + + header.insert(header.end(), components_list.begin(), components_list.end()); + + typename T::Writer writer(output_location, origin, header, run_properties); + typename T::Writer gradient_writer(gradient_location, origin); //FIXME: This file shouldn't be created unless 'save_gradient' flag is set. + + MR::ProgressBar progress_bar ("Scanning over 1 dimension...", num_steps); + + double inc = 2.0 / (double)(num_steps - 1); + + for (double frac = -1.0; frac <= 1.0 + inc/2.0; frac += inc) { // The +inc/2.0 safeguards against rounding errors. + + T gradient(origin), prior_gradient(origin), likelihood_gradient(origin); + + T state = origin + axis * frac; + + double prior_px; + double likelihood_px; + + if (save_gradient) { + gradient.zero(); + + prior_px = prior.log_prob(state, prior_gradient); + gradient += prior_gradient; + + likelihood_px = likelihood.log_prob(state,likelihood_gradient); + gradient += likelihood_gradient; + + gradient_writer.append(gradient); + + } else { + prior_px = prior.log_prob(state); + likelihood_px = likelihood.log_prob(state); + } + + double lprob = prior_px + likelihood_px; + + std::map properties; + + properties["log_px"] = str(lprob); + properties["likelihood_px"] = str(likelihood_px); + properties["prior_px"] = str(prior_px); + + std::map component_values = prior.get_component_values(state); + + for (std::map::iterator comp_it = component_values.begin(); comp_it != component_values.end(); ++comp_it) + properties[comp_it->first] = comp_it->second; + + writer.append(state, properties); + + ++progress_bar; + + } + + } + + + template void scan ( + Prob::Likelihood& likelihood, + Prob::Prior& prior, + const Fibre::Base::Set& sequence, + const std::string& output_location, + std::map& run_properties) { + + std::string gradient_location = File::strip_extension(output_location) + ".gradient." + File::extension(output_location); + std::vector header; + header.push_back("log_px"); + header.push_back("likelihood_px"); + header.push_back("prior_px"); + header.push_back("acs_px"); + + typename T::Writer writer(output_location, run_properties, header); + typename T::Writer gradient_writer(gradient_location); + + MR::ProgressBar progress_bar ("Scanning over 1 dimension...", sequence.size()); + + for (typename Fibre::Base::Set::const_iterator it = sequence.begin(); it != sequence.end(); ++it) { + + T gradient(*it), prior_gradient(*it), likelihood_gradient(*it); + + T& state = *it; + + gradient.zero(); + + double prior_px = prior.log_prob(state, prior_gradient); + gradient += prior_gradient; + + double likelihood_px = likelihood.log_prob(state,likelihood_gradient); + gradient += likelihood_gradient; + + double log_prob = prior_px + likelihood_px; + + std::map properties_row; + properties_row["log_px"] = str(log_prob); + properties_row["likelihood_px"] = str(likelihood_px); + properties_row["prior_px"] = str(prior_px); + + + writer.append(state, properties_row); + gradient_writer.append(gradient, std::map()); + + ++progress_bar; + + } + + } + + + template void scan ( + Prob::Likelihood& likelihood, + Prob::Prior& prior, + const T& origin, + const T& axis1, + const T& axis2, + size_t num_steps1, + size_t num_steps2, + const std::string& output_location, + std::map& properties + ) { + + if (origin.size() != axis1.size()) + throw Exception ("Size of origin state (" + str(origin.size()) + ") does not match size of axis1 state (" + str(axis1.size()) + ")."); + + if (origin.size() != axis2.size()) + throw Exception ("Size of origin state (" + str(origin.size()) + ") does not match size of axis2 state (" + str(axis2.size()) + ")."); + + MR::Image::Header header; + + header.insert(properties.begin(), properties.end()); + + header.set_ndim(2); + + header.set_dim(0, num_steps1); + header.set_dim(1, num_steps2); + + header.set_description(0, File::strip_extension(properties["axis1_location"])); + header.set_description(1, File::strip_extension(properties["axis2_location"])); + + header.set_vox(0, 2.0 / (double)num_steps1); + header.set_vox(1, 2.0 / (double)num_steps2); + + File::clear_path(output_location); + + header.create(output_location); + + double inc1 = 2.0 / (double)(num_steps1 - 1); + double inc2 = 2.0 / (double)(num_steps2 - 1); + + MR::Image::Voxel pixel (header); + + MR::DataSet::Loop loop ("Scanning over 2 dimensions...", 0, 2); + loop.start(pixel); + + for (double frac1 = -1.0; frac1 <= 1.0 + inc1/2.0; frac1 += inc1) { // The +inc/2.0 safeguards against rounding errors. + + for (double frac2 = -1.0; frac2 <= 1.0 + inc2/2.0; frac2 += inc2) { + + T state = origin + axis1 * frac1 + axis2 * frac2; + + pixel.value() = prior.log_prob(state) + likelihood.log_prob(state); + + loop.next(pixel); + + } + + } + + } + + + template void scan ( + Prob::Likelihood& likelihood, + Prob::Prior& prior, + const T& origin, + const T& axis1, + const T& axis2, + const T& axis3, + size_t num_steps1, + size_t num_steps2, + size_t num_steps3, + const std::string& output_location, + std::map& properties + ) { + + if (origin.size() != axis1.size()) + throw Exception ("Size of origin state (" + str(origin.size()) + ") does not match size of axis1 state (" + str(axis1.size()) + ")."); + + if (origin.size() != axis2.size()) + throw Exception ("Size of origin state (" + str(origin.size()) + ") does not match size of axis2 state (" + str(axis2.size()) + ")."); + + if (origin.size() != axis3.size()) + throw Exception ("Size of origin state (" + str(origin.size()) + ") does not match size of axis3 state (" + str(axis3.size()) + ")."); + + MR::Image::Header header; + + header.insert(properties.begin(), properties.end()); + + header.set_ndim(3); + + header.set_dim(0, num_steps1); + header.set_dim(1, num_steps2); + header.set_dim(2, num_steps3); + + + header.set_description(0, File::strip_extension(properties["axis1_location"])); + header.set_description(1, File::strip_extension(properties["axis2_location"])); + header.set_description(2, File::strip_extension(properties["axis3_location"])); + + + header.set_vox(0, 2.0 / (double)num_steps1); + header.set_vox(1, 2.0 / (double)num_steps2); + header.set_vox(2, 2.0 / (double)num_steps3); + + File::clear_path(output_location); + + header.create(output_location); + + + double inc1 = 2.0 / (double)(num_steps1 - 1); + double inc2 = 2.0 / (double)(num_steps2 - 1); + double inc3 = 2.0 / (double)(num_steps3 - 1); + + + MR::Image::Voxel pixel (header); + + MR::DataSet::Loop loop ("Scanning over 3 dimensions...", 0, 3); + loop.start(pixel); + + for (double frac1 = -1.0; frac1 <= 1.0 + inc1/2.0; frac1 += inc1) { // The +inc/2.0 safeguards against rounding errors. + + for (double frac2 = -1.0; frac2 <= 1.0 + inc2/2.0; frac2 += inc2) { + + for (double frac3 = -1.0; frac3 <= 1.0 + inc3/2.0; frac3 += inc3) { + + T state = origin + axis1 * frac1 + axis2 * frac2 + axis3 * frac3; + + pixel.value() = prior.log_prob(state) + likelihood.log_prob(state); + + loop.next(pixel); + + } + + } + + } + + + } + + + } + +} + + +#endif diff --git a/src/bts/cmd.h b/src/bts/cmd.h new file mode 100644 index 0000000..b1cc2a3 --- /dev/null +++ b/src/bts/cmd.h @@ -0,0 +1,84 @@ +/* + Copyright 2010 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close on Jun 3, 2010. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + +*/ + +#ifndef __bts_cmd_h__ +#define __bts_cmd_h__ + +#include "app.h" +#include "args.h" +#include "progressbar.h" + +namespace BTS { + + class Argument : public MR::Argument { + + public: + Argument (const char* name = NULL, const char* description = NULL) + : MR::Argument(name, description) {} + + Argument& type_string(const char* string); + + }; + + class Option : public MR::Option { + + public: + + typedef enum _ByDefault { + Active, + Inactive + } ByDefault; + + protected: + + ByDefault by_default; + + public: + Option () {} + + Option (const char* name, const char* description) + : MR::Option(name, description), by_default(Inactive) {} + + Option& active_by_default(bool is_active = true) + { by_default = is_active ? Active : Inactive; return *this; } + + }; + + class App : public MR::App { + + public: + App (int argc, char** argv, const char** cmd_desc, const MR::Argument* cmd_args, const MR::Option* cmd_opts, + const size_t* cmd_version, const char* cmd_author, const char* cmd_copyright) + : MR::App(argc, argv, cmd_desc, cmd_args, cmd_opts, cmd_version, cmd_author, cmd_copyright) {} + + virtual ~App (); + }; + + +// MR::ActiveByDefault NA = MR::NA; +// MR::ActiveByDefault Active = MR::Active; +// MR::ActiveByDefault Inactive = MR::Inactive; + +} + + +#endif /* __bts_cmd_h__ */ diff --git a/src/bts/common.cpp b/src/bts/common.cpp new file mode 100644 index 0000000..787c5bd --- /dev/null +++ b/src/bts/common.cpp @@ -0,0 +1,187 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + +#include +#include + + + +#include "bts/common.h" + + + +namespace BTS { + + void breakpoint() { + size_t i = 0; + i++; + } + + + double rand_double() { + + size_t rand_size_t = rand(); + + return (double)rand_size_t / (double)RAND_MAX; + + } + + + std::vector parse_double_vector(const std::string& s) { + + std::vector v; + + size_t start_number = 0; + size_t end_number; + + int i = 0; + + start_number = s.find_first_of("0123456789.-"); + + while (start_number != std::string::npos) { + + end_number = s.find_first_not_of("0123456789.-", start_number); + + std::string num_string = s.substr(start_number, end_number-start_number); + + + if (num_string.find_first_of('-', 1) != std::string::npos || num_string.find('.', num_string.find('.')+1) != std::string::npos) // If there is a '-' character anywhere other than the first character, or if there is more than one decimal point then throw an error. + throw Exception("Value, " + num_string + " at position: " + str(i+1) + ", is invalid"); + + v.push_back(atof(num_string.c_str())); + + start_number = s.find_first_of("0123456789.-", end_number); + i++; + + } + + return v; + + } + + + std::vector parse_int_vector(const std::string& s) { + + std::vector v; + + size_t start_number = 0; + size_t end_number; + + int i = 0; + + start_number = s.find_first_of("0123456789-"); + + while (start_number != std::string::npos) { + + end_number = s.find_first_not_of("0123456789-", start_number); + + std::string num_string = s.substr(start_number, end_number-start_number); + + if (num_string.find_first_of('-', 1) != std::string::npos) // If there is a '-' character anywhere other than the first character then throw an error. + throw Exception("Value, " + num_string + " at position: " + str(i+1) + ", is invalid"); + + v.push_back(atoi(num_string.c_str())); + + start_number = s.find_first_of("0123456789-", end_number); + i++; + + } + + return v; + + } + + //TODO: Make this a template function and improve the parse to include ranges. + std::vector parse_size_t_vector(const std::string& s) { + + std::vector v; + + size_t start_number = 0; + size_t end_number; + + size_t i = 0; + + start_number = s.find_first_of("0123456789-"); + + while (start_number != std::string::npos) { + + end_number = s.find_first_not_of("0123456789-", start_number); + + std::string num_string = s.substr(start_number, end_number-start_number); + + if (num_string.find_first_of('-', 1) != std::string::npos) // If there is a '-' character anywhere other than the first character then throw an error. + throw Exception("Value, " + num_string + " at position: " + str(i+1) + ", is invalid"); + + v.push_back(atoi(num_string.c_str())); + + start_number = s.find_first_of("0123456789-", end_number); + i++; + + } + + return v; + + } + + + int num_dec_places(int number) { + int num_places, ten_power; + + num_places = 1; + ten_power = 10; + while ((number / ten_power) != 0) { + num_places++; + ten_power *= 10; + } + + return num_places; + } + + + int num_precision_places(double number) { + int num_places = 0; + + double remainder = number - floor(number); + + while (remainder != 0.0) { + num_places++; + remainder *= 10; + remainder = remainder - floor(remainder); + } + + return num_places; + } + + + + + + +} + + + + + + + + diff --git a/src/bts/common.h b/src/bts/common.h new file mode 100644 index 0000000..1ba19b4 --- /dev/null +++ b/src/bts/common.h @@ -0,0 +1,354 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + + +#ifndef __bts_common_h__ +#define __bts_common_h__ + + +//Defines the parameters +#define COMMON_PARAMETERS \ + Option ("comments", "Description of the fibres/image, and/or the purpose of the performed experiment.") \ + + Argument ("comments", "").type_text() \ + + +//Loads the parameters into variables +#define SET_COMMON_PARAMETERS \ + std::string cmn_comments = ""; \ +\ + Options cmn_opt = get_options("comments"); \ + if (cmn_opt.size()) \ + cmn_comments = cmn_opt[0][0].c_str(); \ + + + +//Adds the parameters to the properties to be saved with the data. +#define ADD_COMMON_PROPERTIES(properties) \ + properties["comments"] = cmn_comments; \ + + +#include +#include +#include + + +#include "types.h" +#include "mrtrix.h" + + +#undef X +#undef Y +#undef Z +#undef DW +#undef AZ +#undef EL +#undef RAD +#undef INV_M_PI +#undef SQRT_3 +#undef SQRT_2 +#undef M_PI_ON_2 + + +namespace BTS { + + //Standard dimension order + const size_t X = 0; + const size_t Y = 1; + const size_t Z = 2; + const size_t DW = 3; + + //Standard spherical dimension order + const size_t EL = 0; + const size_t AZ = 1; + const size_t RAD = 2; + + //Common mathematical constants + const double INV_M_PI = 0.318309886; + const double GAUSS_NORM = 0.398942280; + const double JUST_UNDER_PI_ON_2 = 1.5706; + const double SQRT_3 = 1.732050807; + const double SQRT_2 = 1.414213562; + const double SQRT_LOG_2 = 0.832554611; + const double LOG_2 = 0.693147181; + const double LOG_PI = 1.144729886; + + const std::string PARAM_DIRECTORY = "/home/tclose/data/"; + + const double LARGE_FLOAT = 1e10; //A large double still with a bit of room to move. + const double SMALL_FLOAT = 1e-10; //A small double still with a bit of room to move. + const size_t LARGE_INT = 1e8; //A large number still with a bit of room to move. + + typedef MR::Exception Exception; + +// using std::cout; +// using std::endl; + +} + +extern "C" { +#include +#include +} + + +#include +#include +#include "file/path.h" +#include "exception.h" +#include "math/math.h" +#include "math/vector.h" + + +namespace BTS { + + template class CompareFirst { public: bool operator()(const std::pair& p1, const std::pair& p2) { return p1.first < p2.first; }}; + template class CompareSecond { public: bool operator()(const std::pair& p1, const std::pair& p2) { return p1.second < p2.second; }}; + + template T min2 (T const x, T const y) throw () { return (x < y)? x: y;} + + + template T max2 (T const x, T const y) throw () { return (x > y)? x: y;} + + + template void zero(T& element) { + element.zero(); + } + + + inline void zero(float& element) { + element = 0.0; + } + + + inline void zero(double& element) { + element = 0.0; + } + + + inline void zero(int& element) { + element = 0; + } + + + inline void zero(size_t& element) { + element = 0; + } + + + template void negate(T& value) { + value.negate(); + } + + + inline void negate(float& value) { + value = -value; + } + + + inline void negate(double& value) { + value = -value; + } + + + inline void negate(int& value) { + value = -value;; + } + + + inline void negate(size_t& value) { + value = -value;; + } + + + template void invalidate(T& element) { + element.invalidate(); + } + + + inline void invalidate(float& element) { + element = NAN; + } + + + inline void invalidate(double& element) { + element = NAN; + } + + + inline void invalidate(int& element) { + element = std::numeric_limits::max(); + } + + + template bool is_empty(const T& element) { + return !element.size(); + } + + + inline bool is_empty(double dble) { + return isnan(dble); + } + + + + void breakpoint(); + + + double rand_double(); + + + std::vector parse_double_vector(const std::string& str); + + + std::vector parse_int_vector(const std::string& str); + + + std::vector parse_size_t_vector(const std::string& str); + + + int num_dec_places(int number); + + + int num_precision_places(double number); + + + template std::string str(const T& value) { + std::stringstream ss; + ss << value; + return ss.str(); + } + + + inline std::string str (int number, size_t dec_places) { + std::stringstream ss; + ss << std::setfill('0') << std::setw(dec_places + (number < 0)) << number; + return ss.str(); + } + + + inline std::string str (double number, size_t dec_places, size_t precision) { + std::stringstream ss; + ss << std::fixed << std::setprecision(precision) << std::setfill('0') << std::setw(dec_places + precision + (precision > 0) + (number < 0)) << number; + return ss.str(); + } + + + template T to(const std::string &s) { + + //Copied from http://snippets.dzone.com/posts/show/347 + + T t; + std::istringstream iss(s); + iss >> t; + return t; + } + + + inline std::string current_datetime(std::string format_string = "%c") { + + //Adapted from example at http://www.cplusplus.com/reference/clibrary/ctime/strftime/ . + + time_t rawtime; + struct tm *timeinfo; + char current_time[200]; + + time (&rawtime); + timeinfo = localtime (&rawtime); + + + strftime (current_time, 200, format_string.c_str(), timeinfo); + + return str(current_time); + + } + + // Used to sort vectors of const char* + inline bool cstr_sort(const char* a, const char* b) { + + return strcmp(a, b) < 0; + + } + + + template + struct PrintMap : public std::unary_function + { + std::ostream& os; + PrintMap(std::ostream& strm) : os(strm) {} + + void operator()(const T& elem) const + { + os << elem.first << ", " << elem.second << std::endl; + } + }; + + template std::vector parse_sequence (const std::string& spec, T last = std::numeric_limits::max()) { + std::vector V; + if (!spec.size()) throw Exception ("unsigned integer sequence specifier is empty"); + std::string::size_type start = 0, end; + T num[3]; + T i = 0; + try { + do { + end = spec.find_first_of (",:", start); + std::string str (MR::strip (spec.substr (start, end-start))); + MR::lowercase (str); + if (str == "end") { + if (last == std::numeric_limits::max()) + throw Exception ("value of \"end\" is not known in number sequence \"" + spec + "\""); + num[i] = last; + } + else num[i] = to (spec.substr (start, end-start)); + + char last_char = end < spec.size() ? spec[end] : '\0'; + if (last_char == ':') { i++; if (i > 2) throw Exception ("invalid number range in number sequence \"" + spec + "\""); } + else { + if (i) { + T inc, last; + if (i == 2) { inc = num[1]; last = num[2]; } + else { inc = 1; last = num[1]; } + if (inc * (last - num[0]) < 0) inc = -inc; + for (; ( inc > 0 ? num[0] <= last : num[0] >= last ) ; num[0] += inc) V.push_back (num[0]); + } + else V.push_back (num[0]); + i = 0; + } + + start = end+1; + } while (end < spec.size()); + } + catch (Exception& E) { + throw Exception (E, "can't parse unsigned integer sequence specifier \"" + spec + "\""); + } + + return (V); + + } + + + // A gdb pretty printing hack + class CoordView {}; + +} + +#endif + diff --git a/src/bts/coord.cpp b/src/bts/coord.cpp new file mode 100644 index 0000000..a70eef2 --- /dev/null +++ b/src/bts/coord.cpp @@ -0,0 +1,156 @@ +/* + Copyright 2012 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, 07/08/2010. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + +#include "bts/coord.h" +#include "bts/coord/tensor.h" + +namespace BTS { + + const Coord Coord::Invalid (NAN, NAN, NAN); + const Coord Coord::Zeros (0.0, 0.0, 0.0); + const Coord Coord::Ones(1.0,1.0,1.0); + const Coord Coord::Halves(0.5,0.5,0.5); + const std::string Coord::FILE_EXTENSION = "crd"; + + std::ostream& operator<< (std::ostream& stream , const Coord& c) + { + stream << "[ " << c[X] << ", " << c[Y] << ", " << c[Z] << " ]"; + return (stream); + } + + + Coord& Coord::zero() { + + operator[](X) = 0.0; + operator[](Y) = 0.0; + operator[](Z) = 0.0; + + return *this; + } + + Coord& Coord::invalidate() { + + operator[](X) = NAN; + operator[](Y) = NAN; + operator[](Z) = NAN; + + return *this; + } + + bool Coord::operator== (const Coord& A) const + { return (operator[](X) == A[X]) && (operator[](Y) == A[Y]) && (operator[](Z) == A[Z]); }; + + bool Coord::operator!= (const Coord& A) const + { return (operator[](X) != A[X]) || (operator[](Y) != A[Y]) || (operator[](Z) != A[Z]); }; + + + Coord operator* (double M, const Coord& c) + { return Coord (c[X]*M, c[Y]*M, c[Z]*M); } + + + double dist2 (const Coord& a, const Coord& b) + { return ((a-b).norm2()); } + + double dist (const Coord& a, const Coord& b) + { return ((a-b).norm()); } + + + + + double Coord::dot (const Coord& t, Coord& gradient) const { + + gradient = *this; + + return dot(t); + + } + + + double Coord::angle(const Coord& t) const { + + return MR::Math::acos(dot(t)/(norm() * t.norm())); + + } + + + double Coord::norm2 (Coord& gradient) const { + + gradient = *this * 2.0; + + return norm2(); + + } + + + double Coord::norm (Coord& gradient) const { + + double nrm = norm(); + + gradient = *this / nrm; + + return nrm; + + } + + + double Coord::norm2 (Coord& gradient, typename Coord::Tensor& hessian) const { + + gradient = *this * 2.0; + + hessian.diagonal() = 2.0; + + return norm2(); + + } + + + double Coord::norm (Coord& gradient, typename Coord::Tensor& hessian) const { + + double nrm = norm(); + + gradient = *this / nrm; + + hessian = this->outer(*this); + hessian *= - MR::Math::pow3(1/nrm); + hessian.diagonal() += 1/nrm; + + return nrm; + + } + + + + Coord::Tensor Coord::outer(const Coord& c) const { + + Coord::Tensor tensor; + + tensor.row(X) = c * operator[](X); + tensor.row(Y) = c * operator[](Y); + tensor.row(Z) = c * operator[](Z); + + return tensor; + + } + + + +} diff --git a/src/bts/coord.h b/src/bts/coord.h new file mode 100644 index 0000000..cd4fa51 --- /dev/null +++ b/src/bts/coord.h @@ -0,0 +1,240 @@ +/* + Copyright 2012 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, 07/08/2010. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + + +#ifndef __bts_coord_h__ +#define __bts_coord_h__ + +namespace BTS { + + class Coord; + + +} + +#include "math/vector.h" +#include "bts/triple.h" + + +namespace BTS { + + class Coord : public MR::Math::Vector { + + public: + + class Tensor; + typedef Utilities::Reader Reader; + typedef Utilities::Writer Writer; + + public: + + const static Coord Invalid; + const static Coord Zeros; + const static Coord Halves; + const static Coord Ones; + + static const std::string FILE_EXTENSION; + + public: + + /*! Generates a basic fibre coordinate derived from a base fibre object of length three and row size 1 */ + Coord() + : MR::Math::Vector(3) { set(NAN); } + + Coord(double x, double y, double z) + : MR::Math::Vector(3) { set(x,y,z); } + + Coord(const Triple& t) + : MR::Math::Vector(3) { set(t[0],t[1],t[2]); } + + Coord(const MR::Math::Vector& v) + : MR::Math::Vector(v) { assert(v.size() == 3); } + + Coord(const MR::Math::Vector::View& view) + : MR::Math::Vector(view) { assert(view.size() == 3); } + + bool operator! () const + { return (isnan(operator[](X)) || isnan(operator[](Y)) || isnan(operator[](Z))); } + + bool valid () const + { return (!(isnan(operator[](X)) || isnan(operator[](Y)) || isnan(operator[](Z)))); } + + + Coord& set (double x_value, double y_value, double z_value) + { operator[](X) = x_value; operator[](Y) = y_value; operator[](Z) = z_value; return *this; } + + Coord& set (double value) + { set(value,value,value); return *this; } + + Coord& zero (); + + Coord& invalidate (); + + Coord abs() const + { return Coord(fabs(operator[](X)), fabs(operator[](Y)), fabs(operator[](Z)));} + + Coord invert() const + { return Coord (1/operator[](X), 1/operator[](Y), 1/operator[](Z)); } + + void copy_to(double* array) { array[X] = operator[](X); array[Y] = operator[](Y); array[Z] = operator[](Z); } + + bool operator== (const Coord& A) const; + bool operator!= (const Coord& A) const; + + Coord operator- () const + { return (Coord (-operator[](X), -operator[](Y), -operator[](Z))); } + + Coord& operator= (const Coord& A) + { operator[](X) = A[X]; operator[](Y) = A[Y]; operator[](Z) = A[Z]; return (*this); } + + + //Scalar addition, subtraction, multiplication and division. + Coord& operator+= (double inc) + { operator[](X) += inc; operator[](Y) += inc; operator[](Z) += inc; return *this; } + + Coord& operator-= (double inc) + { operator[](X) -= inc; operator[](Y) -= inc; operator[](Z) -= inc; return *this; } + + Coord& operator*= (double M) + { operator[](X)*=M; operator[](Y)*=M; operator[](Z)*=M; return *this; } + + Coord& operator/= (double M) + { operator[](X)/=M; operator[](Y)/=M; operator[](Z)/=M; return *this; } + + + Coord operator+ (double inc) const + { return (Coord (operator[](X)+inc, operator[](Y)+inc, operator[](Z)+inc)); } + + Coord operator- (double inc) const + { return (Coord (operator[](X)-inc, operator[](Y)-inc, operator[](Z)-inc)); } + + Coord operator* (double M) const + { return (Coord (operator[](X)*M, operator[](Y)*M, operator[](Z)*M)); } + + Coord operator/ (double M) const + { return (Coord (operator[](X)/M, operator[](Y)/M, operator[](Z)/M)); } + + + //Pairwise addition, subtraction, multiplication and division. + Coord operator+ (const Coord& c) const + { return Coord (operator[](X)+c[X], operator[](Y)+c[Y], operator[](Z)+c[Z]); } + + Coord operator- (const Coord& c) const + { return Coord (operator[](X)-c[X], operator[](Y)-c[Y], operator[](Z)-c[Z]); } + + Coord operator* (const Coord& c) const + { return Coord (operator[](X)*c[X], operator[](Y)*c[Y], operator[](Z)*c[Z]); } + + Coord operator/ (const Coord& c) const + { return Coord (operator[](X)/c[X], operator[](Y)/c[Y], operator[](Z)/c[Z]); } + + + Coord& operator+= (const Coord& c) + { operator[](X) += c[X]; operator[](Y) += c[Y]; operator[](Z) += c[Z]; return *this; } + + Coord& operator-= (const Coord& c) + { operator[](X) -= c[X]; operator[](Y) -= c[Y]; operator[](Z) -= c[Z]; return *this; } + + Coord& operator*= (const Coord& c) + { operator[](X) *= c[X]; operator[](Y) *= c[Y]; operator[](Z) *= c[Z]; return *this; } + + Coord& operator/= (const Coord& c) + { operator[](X) /= c[X]; operator[](Y) /= c[Y]; operator[](Z) /= c[Z]; return *this; } + + + bool positive() const + { return (operator[](X) > 0.0) && (operator[](Y) > 0.0) && (operator[](Z) > 0.0); } + + bool non_negative() const + { return (operator[](X) >= 0.0) && (operator[](Y) >= 0.0) && (operator[](Z) >= 0.0); } + + bool non_zero() const + { return operator[](X) || operator[](Y) || operator[](Z); } + + + template bool upper_bounded(U bound) const + { return (operator[](X) <= (double)bound) && (operator[](Y) <= (double)bound) && (operator[](Z) <= (double)bound); } + + template bool lower_bounded(U bound) const + { return (operator[](X) >= (double)bound) && (operator[](Y) >= (double)bound) && (operator[](Z) >= (double)bound); } + + template bool upper_bounded(const Triple& bound) const + { return (operator[](X) <= (double)bound[X]) && (operator[](Y) <= (double)bound[Y]) && (operator[](Z) <= (double)bound[Z]); } + + template bool lower_bounded(const Triple& bound) const + { return (operator[](X) >= (double)bound[X]) && (operator[](Y) >= (double)bound[Y]) && (operator[](Z) >= (double)bound[Z]); } + + double dot (const Coord& A) const + { return (operator[](X)*A[X] + operator[](Y)*A[Y] + operator[](Z)*A[Z]); } + + double dot (const Coord& t, Coord& gradient) const; + + double angle(const Coord& t) const; + + Tensor outer(const Coord& t) const; + + double norm2 () const + { return (operator[](X)*operator[](X) + operator[](Y)*operator[](Y) + operator[](Z)*operator[](Z)); } + + double norm () const + { return (sqrt (norm2())); } + + double norm2 (Coord& gradient) const; + + double norm (Coord& gradient) const; + + double norm2 (Coord& gradient, Tensor& hessian) const; + + double norm (Coord& gradient, Tensor& hessian) const; + + const Coord& normalise () + { double nrm = norm(); operator[](X) /= nrm; operator[](Y) /= nrm; operator[](Z) /= nrm; return (*this); } + + Coord cross (const Coord& A) const + { return (Coord (operator[](Y)*A[Z]-operator[](Z)*A[Y], operator[](Z)*A[X]-operator[](X)*A[Z], operator[](X)*A[Y]-operator[](Y)*A[X])); } + + Coord min_axis() const + { Coord axis(0.0,0.0,0.0); if (fabs(operator[](X)) < fabs(operator[](Y))) { if (fabs(operator[](X)) < fabs(operator[](Z))) axis[X] = 1.0; else axis[Z] = 1.0; } else if (fabs(operator[](Y)) < fabs(operator[](Z))) axis[Y] = 1.0; else axis[Z] = 1.0; return axis; } + + Coord sign() const + { Coord s; for (size_t i = 0; i < 3; ++i) s[i] = operator[](i) > 0 ? 1 : (operator[](i) < 0 ? -1 : 0); return s; } + + double vsize() const + { return 3; } + + void clear() + { // do nothing, overrides MR::Math::Vector clear to make sure it doesn't resize the vector. + // TODO: Reimplement Coord class so that it doesn't need to use MR::Math::Vector and remove redundencies like this one. + } + + + }; + + std::ostream& operator<< (std::ostream& stream , const Coord& c); + + + inline Coord operator* (double M, Coord c) { return Coord(M * c[X], M * c[Y], M * c[Z]); } + inline Coord operator+ (double inc, Coord c) { return Coord(inc + c[X], inc + c[Y], inc + c[Z]); } + +} + +#endif /* __fibre_coord_h__ */ diff --git a/src/bts/coord/tensor.h b/src/bts/coord/tensor.h new file mode 100644 index 0000000..ea81310 --- /dev/null +++ b/src/bts/coord/tensor.h @@ -0,0 +1,120 @@ +/* + Copyright 2012 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, 07/08/2010. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + + +#ifndef __bts_coord_tensor_h__ +#define __bts_coord_tensor_h__ + +#include "math/matrix.h" +#include "bts/coord.h" +#include "bts/fibre/base/tensor_writer.h" + +namespace BTS { + + class Coord::Tensor : public MR::Math::Matrix { + + public: + + typedef Fibre::Base::TensorWriter Writer; + typedef Coord RowType; + + public: + + static Tensor create_diagonal(double value) + { Tensor t; t.diagonal() = value; return t; } + + public: + + Tensor() + : MR::Math::Matrix(3,3) {} + + //Only included for template consistency in gradient tester + Tensor(const Coord& c) + : MR::Math::Matrix(3,3) { invalidate(); } + + Tensor(const MR::Math::Matrix::View& view) + : MR::Math::Matrix(view) { assert(rows()==3); assert(columns() == 3); } + + Coord operator[](size_t idx) + { return Coord(row(idx)); } + + const Coord operator[](size_t idx) const + { return Coord(row(idx)); } + + Tensor& invalidate() + { for (size_t i = 0; i < 3; ++i) for (size_t j = 0; j < 3; ++j) operator()(i,j) = NAN; return *this; } + + Tensor& zero() + { for (size_t i = 0; i < 3; ++i) for (size_t j = 0; j < 3; ++j) operator()(i,j) = NAN; return *this; } + + Tensor& operator*= (const Tensor& t) + { MR::Math::Matrix::operator*=(t); return *this; } + + Tensor& operator*= (double c) + { MR::Math::Matrix::operator*=(c); return *this; } + + Tensor& operator/= (const Tensor& t) + { MR::Math::Matrix::operator/=(t); return *this; } + + Tensor& operator/= (double c) + { MR::Math::Matrix::operator/=(c); return *this; } + + Tensor operator* (const Tensor& t) const + { Tensor answer (*this); answer *= t; return answer;} + + Tensor operator* (double c) const + { Tensor answer (*this); answer *= c; return answer;} + + Tensor operator/ (const Tensor& t) const + { Tensor answer (*this); answer /= t; return answer;} + + Tensor operator/ (double c) const + { Tensor answer (*this); answer /= c; return answer;} + + + Tensor& operator+= (const Tensor& t) + { MR::Math::Matrix::operator+=(t); return *this; } + + Tensor& operator-= (const Tensor& t) + { MR::Math::Matrix::operator-=(t); return *this; } + + Tensor operator+ (const Tensor& t) const + { Tensor answer (*this); answer += t; return answer;} + + Tensor operator- (const Tensor& t) const + { Tensor answer (*this); answer -= t; return answer;} + + + double vsize() const + { return 3; } + + }; + + inline Coord::Tensor operator*(double c, const Coord::Tensor& t) + { return t * c; } + + +} + +#endif /* #ifndef __bts_fibre_coord_tensor_h__*/ + + diff --git a/src/bts/diffusion/encoding.h b/src/bts/diffusion/encoding.h new file mode 100644 index 0000000..dc08765 --- /dev/null +++ b/src/bts/diffusion/encoding.h @@ -0,0 +1,171 @@ +/* + Copyright 2010 Brain Research Institute/National ICT Australia (NICTA), Melbourne, Australia + + Written by Thomas G Close, 5/05/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + +*/ + +#ifndef __bts_diffusion_encoding_h__ +#define __bts_diffusion_encoding_h__ + + + +namespace BTS { + + namespace Diffusion { + + class Encoding; + + } + +} + +#include + +#include "math/matrix.h" + +#include "bts/triple.h" + +#include "bts/common.h" + + + + +namespace BTS { + + namespace Diffusion { + + class Encoding { + + public: + + class Set; + + protected: + + double b; + + Coord orient; + + public: + + Encoding(const MR::Math::Vector::View& encoding) + : b(encoding[3]), orient(encoding[X], encoding[Y], encoding[Z]) { + normalise_orient(); + } + + + Encoding(const Triple& orientation, double b_value) + : b(b_value), orient(orientation) { normalise_orient(); } + + + Encoding(const Triple& direction) + : b(direction.norm()), orient(direction) { normalise_orient(); } + + + Encoding(const Encoding& e) + : b(e.b), orient(e.orient) {} + + + Encoding& operator= (const Encoding& e) + { b = e.b; orient = e.orient; return *this; } + + + double& operator[] (size_t dim_i) + { return orient[dim_i]; } + + const double& operator[] (size_t dim_i) const + { return orient[dim_i]; } + + Coord orientation() const + { return orient; } + + + double b_value() const + { return b; } + + + static std::vector parse_encodings(const MR::Math::Matrix::View& encodings_matrix); + + + static MR::Math::Matrix encodings_matrix(const std::vector& encodings); + + protected: + + /*! Normalises the orientation, checking to see if the norm of the orientation vector isn't zero first */ + void normalise_orient() { + + double norm = orient.norm(); + + //Check to see if the orientation vector isn't all zero before normalising. + if (norm) { + orient[X] /= norm; + orient[Y] /= norm; + orient[Z] /= norm; + } + + } + + + friend std::ostream& operator<< (std::ostream& stream, const Encoding& e); + + }; + + + inline std::vector parse_encodings(const MR::Math::Matrix::View& encodings_matrix) { + + std::vector encodings; + + for (size_t encode_i = 0; encode_i < encodings_matrix.rows(); ++encode_i) + encodings.push_back(Encoding(encodings_matrix.row(encode_i))); + + return encodings; + + } + + + inline MR::Math::Matrix encodings_matrix(const std::vector& encodings) { + + MR::Math::Matrix encodings_matrix(encodings.size(), 4); + + for (size_t encode_i = 0; encode_i < encodings.size(); ++encode_i) { + encodings_matrix(encode_i, X) = encodings[encode_i].orientation()[X]; + encodings_matrix(encode_i, Y) = encodings[encode_i].orientation()[Y]; + encodings_matrix(encode_i, Z) = encodings[encode_i].orientation()[Z]; + encodings_matrix(encode_i, 3) = encodings[encode_i].b_value(); + } + + return encodings_matrix; + + } + + + inline std::ostream& operator<< (std::ostream& stream, const Encoding& e) { + + stream << "b=" << e.b << ", orient=" << e.orient << std::endl; + + return stream; + + } + + } + +} + + +#endif diff --git a/src/bts/diffusion/encoding/set.cpp b/src/bts/diffusion/encoding/set.cpp new file mode 100644 index 0000000..9c08c50 --- /dev/null +++ b/src/bts/diffusion/encoding/set.cpp @@ -0,0 +1,70 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + +#include "bts/diffusion/encoding/set.h" + +#include "bts/diffusion/inline_functions.h" + +namespace BTS { + + namespace Diffusion { + + + Encoding::Set::Set (const Model& m) { + + for (size_t encode_i = 0; encode_i < m.num_encodings(); encode_i++) + encodings.push_back(m.encoding(encode_i)); + + } + + + void Encoding::Set::load(const std::string& location) { + + MR::Math::Matrix encodings_matrix (location); + set(encodings_matrix); + + } + + void Encoding::Set::set(const MR::Math::Matrix& encodings_matrix) { + + encodings.clear(); + + if (encodings_matrix.columns() != 4) + throw Exception ("Encoding matrix must have exactly 4 columns (" + str(encodings_matrix.columns()) + " found)."); + + for (size_t encode_i = 0; encode_i < encodings_matrix.rows(); encode_i++) + encodings.push_back(Encoding(encodings_matrix.row(encode_i))); + + } + + std::ostream& operator<< (std::ostream& stream, const Encoding::Set& e_set) { + + for (std::vector::const_iterator encode_it = e_set.encodings.begin(); encode_it != e_set.encodings.end(); encode_it++) + stream << *encode_it; + + return stream; + + } + + } + +} diff --git a/src/bts/diffusion/encoding/set.h b/src/bts/diffusion/encoding/set.h new file mode 100644 index 0000000..488e252 --- /dev/null +++ b/src/bts/diffusion/encoding/set.h @@ -0,0 +1,98 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + +#ifndef __bts_diffusion_encoding_settemplate_h__ +#define __bts_diffusion_encoding_settemplate_h__ + +#include + +#include "bts/diffusion/encoding.h" +#include "bts/diffusion/model.h" + + + + + + +namespace BTS { + + namespace Diffusion { + + class Encoding::Set { + + protected: + + std::vector encodings; + + + //Public member functions + public: + + + Set() {} + + Set (const MR::Math::Matrix& encodings_matrix) + { set(encodings_matrix); } + + Set (const std::string& location) + { load(location); } + + Set (const Set& s) : + encodings(s.encodings) + {} + + + Set (const Model& m); + + + Set& operator= (const Set& s) { + + this->encodings = s.encodings; + + return *this; + } + + void load(const std::string& location); + + void set(const MR::Math::Matrix& encodings_matrix); + + Encoding& operator[](size_t index) { return encodings[index]; } + const Encoding& operator[](size_t index) const { return encodings[index]; } + + size_t num_encodings() const { return encodings.size(); } + size_t size() const { + return encodings.size(); + } + + const Encoding& encoding(size_t index) const { return encodings[index]; } + + friend std::ostream& operator<<(std::ostream& stream, const Encoding::Set& encodings); + }; + + std::ostream& operator<< (std::ostream& stream, const Encoding::Set& encodings); + + } +} + + + +#endif diff --git a/src/bts/diffusion/inline_functions.h b/src/bts/diffusion/inline_functions.h new file mode 100644 index 0000000..d33668a --- /dev/null +++ b/src/bts/diffusion/inline_functions.h @@ -0,0 +1,28 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, 16/07/2010. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + +#ifndef __bts_diffusion_inline_functions_h__ +#define __bts_diffusion_inline_functions_h__ + + + +#endif /* __bts_diffusion_inline_functions_h__ */ diff --git a/src/bts/diffusion/model.cpp b/src/bts/diffusion/model.cpp new file mode 100644 index 0000000..c4f32b1 --- /dev/null +++ b/src/bts/diffusion/model.cpp @@ -0,0 +1,338 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + + + +#include "dwi/gradient.h" +#include "math/matrix.h" + +#include "math/SH.h" + +#include "bts/common.h" + +#include "bts/triple.h" +// + +#include "bts/diffusion/encoding.h" + +#include "bts/diffusion/model.h" +#include "bts/diffusion/response.h" + +#include "bts/diffusion/inline_functions.h" + +namespace BTS { + + namespace Diffusion { + + const char* Model::ENCODINGS_LOCATION_DEFAULT = "/home/tclose/Code/Common/parameters/encoding_60.b"; + const bool Model::ISOTROPIC_DEFAULT = 0; + const double Model::ADC_DEFAULT = 5e-4; + const double Model::FA_DEFAULT = 0.8; +// const double Model::B_VALUE_DEFAULT = 3000.0; + +// const char* Model::RESPONSE_SH_LOCATION_DEFAULT = "/home/tclose/Code/Tractography/params/diffusion/tensor.SH"; +// const char* Model::RESPONSES_LOCATION_DEFAULT = "/home/tclose/Code/Tractography/params/diffusion/tensor-no_iso.poly"; + + // Maximum order ('l') spherical harmonic that can be calculated; + const size_t Model::LMAX = 8; + + // 0-8th order m=0 Associated Legendre polynomial coefficients multiplied by the common factor for each order. + // (Note, The common factor is omitted in the constant for accuracy and is calculated from the expression + // sqrt[(2*l+1)/(4*pi)] / 2^l). Higher orders can be added, just need to track down the right Legendre coefficients. + const double Model::M0_HARMONIC_L0[5] = { 1, 0, 0, 0, 0}; + const double Model::M0_HARMONIC_L2[5] = { -2, 6, 0, 0, 0}; + const double Model::M0_HARMONIC_L4[5] = { 6, -60, 70, 0, 0}; + const double Model::M0_HARMONIC_L6[5] = {-20, 420, -1260, 924, 0}; + const double Model::M0_HARMONIC_L8[5] = { 70, -2320, 13860, -24024, 12870}; + + + + + Model Model::factory(const MR::Math::Matrix& encodings_matrix, + const MR::Math::Matrix& response_SHs, + double adc, + double fa, + bool include_isotropic) { + + Model model; + + //If response_SHs is an empty matrix, use adc and fa values to generate response spherical harmonics from tensor model. + if (!response_SHs.rows() && !response_SHs.columns()) + model = Model(encodings_matrix, adc, fa, include_isotropic); + + //Else if response matrix only has one column assume that it meant to be a column vector. + else if (response_SHs.columns() == 1) + model = Model(encodings_matrix, response_SHs.column(0), include_isotropic); + + //Else if response matrix only has one row assume that it meant to be a row vector. + else if (response_SHs.rows() == 1) + model = Model(encodings_matrix, response_SHs.row(0), include_isotropic); + + //Otherwise assume that it has separate response coefficients on each row. + else + model = Model(encodings_matrix, response_SHs, include_isotropic); + + return model; + + } + + + Model::Model (const MR::Math::Matrix& encodings_matrix, const MR::Math::Matrix& response_SHs, + bool include_isotropic) { + + if (response_SHs.rows() != encodings_matrix.rows()) + throw Exception ("If multiple rows to thre response_SHs spherical harmonics are provided then they must match" + + str(" the number of rows in the encodings matrix.")); + + init(encodings_matrix, response_SHs, include_isotropic); + + } + + + + + void Model::precalculate_weightings(Fibre::Strand::Section& section) const { + + section.precalc_weightings.resize(num_encodings()); + + for (size_t response_i = 0; response_i < num_encodings(); ++response_i) + section.precalc_weightings[response_i] = operator[](response_i).weighting(section.tangent()); + + } + + void Model::precalculate_weightings_and_gradients(Fibre::Strand::Section& section) const { + + section.precalc_weightings.resize(num_encodings()); + section.precalc_weight_gradients.resize(num_encodings()); + + for (size_t response_i = 0; response_i < num_encodings(); ++response_i) + section.precalc_weightings[response_i] = operator[](response_i).weighting(section.tangent(), section.precalc_weight_gradients[response_i]); + + + } + + void Model::precalculate_weightings_gradients_and_hessians(Fibre::Strand::Section& section) const { + + section.precalc_weightings.resize(num_encodings()); + section.precalc_weight_gradients.resize(num_encodings()); + section.precalc_weight_hessians.resize(num_encodings()); + + for (size_t response_i = 0; response_i < num_encodings(); ++response_i) + section.precalc_weightings[response_i] = operator[](response_i).weighting(section.tangent(), section.precalc_weight_gradients[response_i], section.precalc_weight_hessians[response_i]); + + } + + + + MR::Math::Vector Model::tensor_m0_SH(double adc, double fa, double b_value) { + + MR::Math::Vector sh (LMAX/2 + 1); + + MR::Math::SH::FA2SH (sh, fa, adc, b_value, LMAX); + + return sh; + + } + + + MR::Math::Vector Model::SH_to_coeffs(MR::Math::Vector loaded_SH, bool include_isotropic) { + + size_t num_coeffs = LMAX/2 + 1; + + size_t num_loaded_harmonic_coeffs = loaded_SH.size(); + + if (num_loaded_harmonic_coeffs > num_coeffs) + throw Exception ("Can only calculate polynomial coefficients up to spherical harmonic order " + str((num_coeffs-1)*2) + "."); + + MR::Math::Vector SH (loaded_SH); + + SH.resize(num_coeffs); + + // Pad out the remaining coefficients with zeros. + for (size_t sh_i = num_loaded_harmonic_coeffs; sh_i < num_coeffs; sh_i++) + SH[sh_i] = 0.0; + + //Pre-weight the spherical harmonics by the common factor for each polynomial. + for (size_t sh_i = 0; sh_i < num_coeffs; sh_i++) { + + double l = (double)sh_i * 2.0; + + //Normalising scalar for each basis: sqrt[(2*l+1)/(4*pi)] / 2^l + SH[sh_i] *= sqrt((2.0 * l + 1.0) / (4.0 * M_PI)) / pow(2.0, l); + } + + + //Set up m=0 associated Legendre polynomials (spherical harmonic basis functions) + std::vector< std::vector > uncollated; + + if (include_isotropic) + uncollated.push_back(std::vector(M0_HARMONIC_L0, M0_HARMONIC_L0 + num_coeffs)); + else + uncollated.push_back(std::vector(num_coeffs, 0.0)); + + + uncollated.push_back(std::vector(M0_HARMONIC_L2, M0_HARMONIC_L2 + num_coeffs)); + uncollated.push_back(std::vector(M0_HARMONIC_L4, M0_HARMONIC_L4 + num_coeffs)); + uncollated.push_back(std::vector(M0_HARMONIC_L6, M0_HARMONIC_L6 + num_coeffs)); + uncollated.push_back(std::vector(M0_HARMONIC_L8, M0_HARMONIC_L8 + num_coeffs)); + + + // Multiply spherical harmonic basis functions with weighted coefficients. + for (size_t sh_i = 0; sh_i < num_coeffs; sh_i++) + for (size_t poly_i = 0; poly_i < num_coeffs; poly_i++) + uncollated[sh_i][poly_i] *= SH[sh_i]; + + + //Collect like terms between the polynomial equations to form one set of polynomial coefficients. + MR::Math::Vector collated(num_coeffs); + collated.zero(); + + for (size_t poly_i = 0; poly_i < num_coeffs; poly_i++) + for (size_t sh_i = 0; sh_i < num_coeffs; sh_i++) + collated[poly_i] += uncollated[sh_i][poly_i]; + + return collated; + + } + + + Model::Model (const MR::Math::Matrix& encodings_matrix, double adc, double fa, bool include_isotropic) { + + MR::Math::Matrix response_SHs(encodings_matrix.rows(), LMAX/2 + 1); + + for (size_t row_i = 0; row_i < encodings_matrix.rows(); row_i++) + response_SHs.row(row_i) = tensor_m0_SH(adc, fa, encodings_matrix(row_i,3)); + + init(encodings_matrix, response_SHs, include_isotropic); + + } + + + + + Model::Model (const MR::Math::Matrix& encodings_matrix, const MR::Math::Vector& response_SH, bool include_isotropic) { + + if (!encodings_matrix.rows()) + throw Exception ("No rows found in encodings matrix."); + + if (!encodings_matrix.columns() != 4) + throw Exception ("Four columns required in encodings matrix, found " + str(encodings_matrix.columns()) + "."); + + + double consistent_b_value = 0; + + MR::Math::Matrix response_SHs(encodings_matrix.rows(), LMAX/2 + 1); + + for (size_t row_i = 0; row_i < encodings_matrix.rows(); row_i++) { + + //If b value == previously set b value or the previous b value hasn't been set yet. + if (encodings_matrix(row_i,3) == consistent_b_value || consistent_b_value == 0) { + + response_SHs.row(row_i) = response_SH; + + consistent_b_value = encodings_matrix(row_i,3); + + //If b value == 0. Set response coeffs to NAN, as they should be ignored in 'init' method. + } else if (encodings_matrix(row_i,3) == 0) + + response_SHs.row(row_i) = NAN; + + else + + throw Exception ("Inconsistent b values used in encoding matrix, please either supply a seperate response harmonics for each row or use the automatic tensor harmonic calculation. Previously found b value " + str(consistent_b_value) + + ", found " + str(encodings_matrix(row_i,3)) + " at row " + str(row_i) + "."); + + } + + + init(encodings_matrix, response_SHs, include_isotropic); + + + } + + + + + + void Model::init (const MR::Math::Matrix& encodings_matrix, const MR::Math::Matrix& response_SHs, bool include_isotropic) { + + if (encodings_matrix.columns() <= 3) + throw Exception ("Insufficient columns in loaded diffusion-weighting matrix"); + + if (encodings_matrix.columns() > 4) + throw Exception ("More than 4 columns (" + str(encodings_matrix.columns()) + ") were found in diffusion-weighting matrix"); + + if (encodings_matrix.rows() != response_SHs.rows()) + throw Exception ("Number of rows in encodings_matrix (" + str(encodings_matrix.rows()) + ") and response_SH matrix (" + str(response_SHs.rows()) + ") do not match."); + + for (size_t row_i = 0; row_i < encodings_matrix.rows(); row_i++) { + + MR::Math::Vector response_coeffs(1); + + if (encodings_matrix(row_i, 3)) + response_coeffs = SH_to_coeffs(response_SHs.row(row_i), include_isotropic); + + //If b value == 0, the 0th order coefficient is set to one and the remaining are 0. + else + response_coeffs[0] = 1.0; + + Response response(encodings_matrix.row(row_i), response_coeffs, row_i); + + responses.push_back(response); + + } + + this->includes_iso = include_isotropic; + + + } + + + + + void Model::scale_coeffs(double scalar) { + + for (size_t encode_i = 0; encode_i < this->num_encodings(); encode_i++) + this->operator[](encode_i).scale_coeffs(scalar); + + } + + + + + std::ostream& operator<< (std::ostream& stream, const Diffusion::Model& model) { + + stream << std::endl; + + for (std::vector::const_iterator response_it = model.responses.begin(); response_it != model.responses.end(); ++response_it) + stream << *response_it << std::endl; + + return (stream); + + } + + + + } + + +} diff --git a/src/bts/diffusion/model.h b/src/bts/diffusion/model.h new file mode 100644 index 0000000..bfd2807 --- /dev/null +++ b/src/bts/diffusion/model.h @@ -0,0 +1,245 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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 diff_option) any later version. + + BTS 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 BTS. If not, see . + + */ + +#ifndef __bts_diffusion_model_h__ +#define __bts_diffusion_model_h__ + + +//Defines the parameters required to initialise a Proposal::Distribution object. +#define DIFFUSION_PARAMETERS \ +\ + Option ("diff_response_SH_location", "The location of the axially symmetric (m=0) spherical harmonic coefficients of the diffusion response function.") \ + + Argument ("diff_response_SH_location", "").type_file (), \ +\ + Option ("diff_encodings_location", "The location of the gradient encoding used, supplied as a 4xN text file with each line is in the format [ X Y Z b ], where [ X Y Z ] describe the direction of the applied gradient, and b gives the b-value in units (1000 s/mm^2).") \ + + Argument ("diff_encodings_location", "").type_file (), \ +\ + Option ("diff_isotropic", "Include isotropic component of the signal."), \ +\ + Option ("diff_adc", "The mean apparent diffusion coefficient (mm^2/s) of the tensor model.") \ + + Argument ("diff_adc", "").type_float (SMALL_FLOAT, Diffusion::Model::ADC_DEFAULT, LARGE_FLOAT), \ +\ + Option ("diff_fa", "The fractional anisotropy (FA) of the diffusion tensor model.") \ + + Argument ("diff_fa", "").type_float (0.0, Diffusion::Model::FA_DEFAULT, 1.0) \ +\ + +// Option ("precision", "azimuthal angle precision", "precision of the samples about the azimuthal angle") +// + Argument ("precision", "precision of the samples about the azimuthal angle").type_integer (3,1e6,100)) + + +//Loads the 'proposal' parameters into variables +#define SET_DIFFUSION_PARAMETERS \ +\ + std::string diff_response_SH_location; \ + std::string diff_encodings_location = Diffusion::Model::ENCODINGS_LOCATION_DEFAULT; \ + bool diff_isotropic = Diffusion::Model::ISOTROPIC_DEFAULT; \ + double diff_adc = Diffusion::Model::ADC_DEFAULT; \ + double diff_fa = Diffusion::Model::FA_DEFAULT; \ +\ + Options diff_opt = get_options("diff_response_SH_location"); \ + if (diff_opt.size()) \ + diff_response_SH_location = diff_opt[0][0].c_str(); \ +\ + diff_opt = get_options("diff_encodings_location"); \ + if (diff_opt.size()) \ + diff_encodings_location = diff_opt[0][0].c_str(); \ +\ + diff_opt = get_options("diff_isotropic"); \ + if (diff_opt.size()) \ + diff_isotropic = !Diffusion::Model::ISOTROPIC_DEFAULT; \ +\ + diff_opt = get_options("diff_adc"); \ + if (diff_opt.size()) {\ + diff_adc = Diffusion::Model::ADC_DEFAULT; \ + if (diff_response_SH_location.size()) \ + std::cout << "WARNING!! Supplied value for diff_option '-diff_adc' (" + str(diff_adc) + ") will be ignored as supplied value for diff_option '-diff_response_SH' overrides it." << std::endl; \ + } \ +\ + diff_opt = get_options("diff_fa"); \ + if (diff_opt.size()) {\ + diff_fa = Diffusion::Model::FA_DEFAULT; \ + if (diff_response_SH_location.size()) \ + std::cout << "WARNING!! Supplied value for diff_option '-diff_fa' (" + str(diff_fa) + ") will be ignored as supplied value for diff_option '-diff_response_SH' overrides it." << std::endl; \ + } \ +\ + MR::Math::Matrix diff_response_SH; \ + if (diff_response_SH_location.size()) { \ + diff_response_SH.load (diff_response_SH_location); \ + } \ +\ + MR::Math::Matrix diff_encodings (diff_encodings_location); \ +\ + + +// = Diffusion::Model::RESPONSE_SH_LOCATION_DEFAULT; +// std::string diff_spherical_harmonic_location = Diffusion::Model::SPHERICAL_HARMONIC_LOCATION_DEFAULT; +// MR::Math::Vector diff_spherical_harmonic (diff_spherical_harmonic_location); + +//Adds the 'signal' parameters to the properties to be saved with the data. +#define ADD_DIFFUSION_PROPERTIES(properties) \ + properties["diff_encodings_location"] = str(diff_encodings_location); \ + properties["diff_isotropic"] = str(diff_isotropic); \ + if (diff_response_SH.rows()) { \ + properties["diff_response_SH"] = Math::matlab_str(diff_response_SH); \ + properties["diff_response_SH_location"] = diff_response_SH_location; \ + } else { \ + properties["diff_adc"] = str(diff_adc); \ + properties["diff_fa"] = str(diff_fa); \ + } \ + + + + +namespace BTS { + namespace Diffusion { + + class Model; + + } +} + +#include + +#include "bts/fibre/strand/set.h" + + +#include "bts/diffusion/encoding.h" +#include "bts/diffusion/response.h" + +#define LOOP(op) \ +for (std::vector::iterator response_it = responses.begin(); response_it != responses.end(); ++response_it) { op } + +namespace BTS { + + namespace Diffusion { + + class Model { + + //Public const static members + public: + + const static char* ENCODINGS_LOCATION_DEFAULT; + + const static bool ISOTROPIC_DEFAULT; + + const static double ADC_DEFAULT; + const static double FA_DEFAULT; +// const static double B_VALUE_DEFAULT; + + const static double AZ_PRECISION_DEFAULT; +// const static char* SPHERICAL_HARMONIC_LOCATION_DEFAULT; +// const static char* RESPONSE_SH_LOCATION_DEFAULT; + + const static size_t LMAX; //Maximum lmax that can be calculated; + + //0-8th order m=0 Associated Legendre polynomial coefficients multiplied by the common factor for each order. + static const double M0_HARMONIC_L0[5], M0_HARMONIC_L2[5], M0_HARMONIC_L4[5], M0_HARMONIC_L6[5], M0_HARMONIC_L8[5]; + + + //Protected member variables + protected: + + std::vector responses; + bool includes_iso; + + public: + + + static MR::Math::Vector tensor_m0_SH(double adc, double fa, double b_value); + + static MR::Math::Vector SH_to_coeffs(MR::Math::Vector spherical_harmonics, bool include_isotropic); + + static Model factory(const MR::Math::Matrix& encodings_matrix, + const MR::Math::Matrix& response_SHs, + double adc, + double fa, + bool include_isotropic); + + //Public member functions + public: + + Model() {} + + //TODO: Use b_value from encoding matrix to generate response function per direction. + Model (const MR::Math::Matrix& encodings_matrix, double adc, double fa, bool include_isotropic); + + //TODO: Use take a matrix of response_SH, allowing a different response function per direction. + Model (const MR::Math::Matrix& encodings_matrix, const MR::Math::Vector& response_SH, bool include_isotropic); + + + Model (const MR::Math::Matrix& encodings_matrix, const MR::Math::Matrix& response_SHs, bool include_isotropic); + + + Model (const Model& m) + : responses(m.responses), includes_iso(m.includes_iso) + {} + + + Model& operator= (const Model& m) { + + this->responses = m.responses; + this->includes_iso = m.includes_iso; + + return *this; + } + + + const static double default_strand_volume_fraction = 0.2262 * .0005 * 1e5 * 2.0; + + size_t num_encodings() const + { return responses.size(); } + size_t size() const + { return responses.size(); } + + Response& operator[](size_t index) + { return responses[index]; } + const Response& operator[](size_t index) const + { return responses[index]; } + + const Encoding& encoding(size_t index) const + { return responses[index]; } + + void precalculate_weightings(Fibre::Strand::Section& section) const; + + void precalculate_weightings_and_gradients(Fibre::Strand::Section& section) const; + + void precalculate_weightings_gradients_and_hessians(Fibre::Strand::Section& section) const; + + void scale_coeffs(double scalar); + + bool includes_isotropic() const + { return includes_iso; } + + protected: + + void init(const MR::Math::Matrix& encodings_matrix, const MR::Math::Matrix& response_SHs, bool include_isotropic); + + friend std::ostream& operator<< (std::ostream& stream, const Diffusion::Model& model); + + }; + + } +} + +#undef LOOP + +#endif diff --git a/src/bts/diffusion/response.cpp b/src/bts/diffusion/response.cpp new file mode 100644 index 0000000..fbe2c3f --- /dev/null +++ b/src/bts/diffusion/response.cpp @@ -0,0 +1,204 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, Aug 12, 2010. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + +#ifndef __bts_diffusion_response_cpp_h__ +#define __bts_diffusion_response_cpp_h__ + +#include "bts/diffusion/response.h" +#include "bts/coord/tensor.h" + +namespace BTS { + + namespace Diffusion { + + + //TODO: Encapsulate logic into inline functions to avoid replication between weighting functions. + + double Response::weighting(const Coord& tangent) const { + + //Initalize the weighting with the 0th order coefficient. + double weight = coeffs[0]; + + double tan_dot_orient = Encoding::orient.dot(tangent); + double tan_dot_tan = tangent.norm2(); + + //Otherwise the total added value = 0 anyway. + if (tan_dot_orient != 0.0 && tan_dot_tan != 0.0) { + + double tan_dot_orient2 = MR::Math::pow2(tan_dot_orient); + + double cos2 = tan_dot_orient2 / tan_dot_tan; + + //Will hold the even powers of the cosine of the angle between DW and tangent. + double cos2p = 1.0; + + for (size_t p_int = 1; p_int < coeffs.size(); ++p_int) { + + const double& coeff_p = coeffs[p_int]; + + cos2p *= cos2; + + weight += coeff_p * cos2p; + + } + + } + + return weight; + + } + + + double Response::weighting(const Coord& tangent, Coord& gradient) const { + + //Initalize the weighting with the 0th order coefficient. + double weight = coeffs[0]; + +#ifndef GRADIENT_NOT_REQUIRED + gradient.zero(); //coeffs[0]; Not sure why this was coeffs[0]. +#endif + + double tan_dot_orient = Encoding::orient.dot(tangent); + double tan_dot_tan = tangent.norm2(); + + //Otherwise the total added value = 0 anyway. + if (tan_dot_orient != 0.0 && tan_dot_tan != 0.0) { + + double tan_dot_orient2 = MR::Math::pow2(tan_dot_orient); + + double cos2 = tan_dot_orient2 / tan_dot_tan; + + //Will hold the even powers of the cosine of the angle between DW and tangent. + double cos2p = 1.0; + + for (size_t p_int = 1; p_int < coeffs.size(); ++p_int) { + + const double& coeff_p = coeffs[p_int]; + + double p = (double)p_int; + + cos2p *= cos2; + + weight += coeff_p * cos2p; + +#ifndef GRADIENT_NOT_REQUIRED + gradient += coeff_p * 2 * p * cos2p * (Encoding::orient / tan_dot_orient - tangent / tan_dot_tan); +#endif + + } + + } + + + return weight; + + } + + + double Response::weighting(const Coord& tangent, Coord& gradient, Coord::Tensor& hessian) const { + + //Initalize the weighting with the 0th order coefficient. + double weight = coeffs[0]; + +#ifndef GRADIENT_NOT_REQUIRED + gradient.zero(); //coeffs[0]; Not sure why this was coeffs[0]. + +#ifndef HESSIAN_NOT_REQUIRED + hessian.zero(); +#endif + +#endif + + double tan_dot_orient = Encoding::orient.dot(tangent); + double tan_dot_tan = tangent.norm2(); + + //Otherwise the total added value = 0 anyway. + if (tan_dot_orient != 0.0 && tan_dot_tan != 0.0) { + + double tan_dot_orient2 = MR::Math::pow2(tan_dot_orient); + +#ifndef HESSIAN_NOT_REQUIRED + double tan_dot_tan2 = MR::Math::pow2(tan_dot_tan); +#endif + + double cos2 = tan_dot_orient2 / tan_dot_tan; + + //Will hold the even powers of the cosine of the angle between DW and tangent. + double cos2p = 1.0; + + for (size_t p_int = 1; p_int < coeffs.size(); ++p_int) { + + const double& coeff_p = coeffs[p_int]; + + double p = (double)p_int; + + cos2p *= cos2; + + weight += coeff_p * cos2p; + +#ifndef GRADIENT_NOT_REQUIRED + + gradient += coeff_p * 2 * p * cos2p * (Encoding::orient / tan_dot_orient - tangent / tan_dot_tan); + +#ifndef HESSIAN_NOT_REQUIRED + + //Note that the Hessian calculation could be slightly more efficient by only calculating the upper triangle + //of the matrix but has been implemented this way for mathematical clarity. + hessian += coeff_p * 2 * p * cos2p * ( + ((2 * p - 1) / tan_dot_orient2) * orient.outer(orient) + - ( 2 * p / (tan_dot_orient * tan_dot_tan)) * (tangent.outer(orient) + orient.outer(tangent)) + + ((2 * p + 2) / tan_dot_tan2) * tangent.outer(tangent) + - Coord::Tensor::create_diagonal(1/tan_dot_tan) ); + +#endif + +#endif + + } + + } + + + return weight; + + } + + + std::ostream& operator<< (std::ostream& stream, const Diffusion::Response& response) { + + stream << "b=" << response.b; + + stream << ", orient=" << response.orient; + + stream << ", coeffs=" << response.coeffs; + + stream << std::endl; + + return stream; + + } + + } + +} + +#endif /* __bts_diffusion_response_cpp_h__ */ diff --git a/src/bts/diffusion/response.h b/src/bts/diffusion/response.h new file mode 100644 index 0000000..0589c11 --- /dev/null +++ b/src/bts/diffusion/response.h @@ -0,0 +1,152 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + + +#ifndef __bts_diffusion_response_h__ +#define __bts_diffusion_response_h__ + +namespace BTS { + + namespace Diffusion { + + class Response; + + } + +} + +#include "bts/common.h" + +#include "bts/triple.h" +#include "bts/coord.h" +#include "bts/diffusion/encoding.h" + + +namespace BTS { + + namespace Diffusion { + + class Response : public Encoding { + + protected: + + MR::Math::Vector coeffs; + size_t index; + + +#ifdef OPTIMISED +// // Used to store the weighting and the gradient of the weighting for the current Fibre::Strand::Section +// // to save it being recalculated at every voxel it affects. +// double precalc_weighting; +// +// Triple precalc_gradient; +// Coord::Tensor precalc_hessian; +#endif + + //NB: b value is incorporated into the response coefficients. + + public: + + Response (const MR::Math::Vector::View& encoding_row, MR::Math::Vector& coeffs, size_t index) + : Encoding(encoding_row), coeffs(coeffs), index(index) {} + + Response (const Triple& orientation, double b_value, MR::Math::Vector& coeffs, size_t index) + : Encoding(orientation, b_value), coeffs(coeffs), index(index) {} + + Response (const Triple& direction, MR::Math::Vector& coeffs, size_t index) + : Encoding(direction), coeffs(coeffs), index(index) {} + + Response (const Response& r) + : Encoding(r), coeffs(r.coeffs), index(r.index) {} + + Response& operator= (const Response& r) + { Encoding::operator= (r); coeffs = r.coeffs; index = r.index; return *this; } + + + double weighting (const Coord& tangent) const; + + double weighting (const Coord& tangent, Coord& tangent_gradient) const; + + double weighting (const Coord& tangent, Coord& tangent_gradient, Coord::Tensor& tangent_hessian) const; + +//--------------------------------------------------------------------------------------------------// +//These functions are only used to get the signature right for the GradientTester::Function classes. +//--------------------------------------------------------------------------------------------------// + + double weighting (const Coord& tangent) + { const Response& const_this = *this; return const_this.weighting(tangent); } + + double weighting (const Coord& tangent, Coord& tangent_gradient) + { const Response& const_this = *this; return const_this.weighting(tangent, tangent_gradient); } + + double weighting (const Coord& tangent, Coord& tangent_gradient, Coord::Tensor& tangent_hessian) + { const Response& const_this = *this; return const_this.weighting(tangent, tangent_gradient, tangent_hessian); } +//--------------------------// + + + size_t get_index() const + { return index; } + +#ifdef OPTIMISED +// void precalculate_weighting(const Triple& tangent) +// { this->precalc_weighting = weighting(tangent); } +// +// void precalculate_weighting_and_gradient(const Triple& tangent) +// { this->precalc_weighting = weighting(tangent, this->precalc_gradient); } +// +// void precalculate_weighting_gradient_and_hessian(const Triple& tangent) +// { this->precalc_weighting = weighting(tangent, this->precalc_gradient, this->precalc_hessian); } +// +// double precalculated_weighting() const +// { return precalc_weighting; } +// +// +// const Triple& precalculated_gradient() const +// { return precalc_gradient; } +// +// const Coord::Tensor& precalculated_hessian() const +// { return precalc_hessian; } + +#endif + + void scale_coeffs(double scalar) + { this->coeffs *= scalar; } + + + + + friend std::ostream& operator<< (std::ostream& stream, const Diffusion::Response& response); + + }; + + +// inline + std::ostream& operator<< (std::ostream& stream, const Diffusion::Response& response); + + + } + + +} + + +#endif diff --git a/src/bts/fibre/base/object.cpp b/src/bts/fibre/base/object.cpp new file mode 100644 index 0000000..b2d6851 --- /dev/null +++ b/src/bts/fibre/base/object.cpp @@ -0,0 +1,443 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, Jan 27, 2011. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + +#include "exception.h" + +#include "bts/common.h" +#include "bts/file.h" + +#include "bts/fibre/base/object.h" +#include "bts/fibre/strand.h" +#include "bts/fibre/tractlet.h" +#include "bts/fibre/strand/set.h" +#include "bts/fibre/tractlet/set.h" +#include "bts/math/common.h" + +namespace BTS { + + namespace Fibre { + + namespace Base { + + const char* Object::ACS_SQRT_PROP = "acs_sqrt"; + + const char* Object::PROPS_LIST_END = 0; + + // Sorry a bit of a hack. Is passed to the operator[]() when constructing a strand element without the properties. + std::vector Object::EMPTY_PROPS; + + + void Object::reset(size_t size, size_t row_size, const std::vector& properties, double fill_value) { + + if (!owner) + throw Exception ("Cannot reset object as it is a view onto a larger object."); + + MR::Math::Vector::resize(size * row_size + properties.size()); + sze = size; + + *props = properties; + + set(fill_value); + + } + + + void Object::reset(const std::vector& properties, double fill_value) { + + if (!owner) + throw Exception ("Cannot reset object as it is a view onto a larger object."); + + MR::Math::Vector::resize(properties.size(), fill_value); + sze = 0; + + *props = properties; + + set(fill_value); + + } + + + bool Object::props_match(const std::vector* properties) const { + + bool match; + + if (props == properties) // Point to the same properties + match = true; + else if (!props->size() && !properties->size()) // Both contain no properties + match = true; + else if (num_props() != properties->size()) // Are of different size + match = false; + else // Compare the property pointers (relies on the fact that properties are sorted by order of memory location when they are inserted). + match = !memcmp(&(props->operator[](0)),&(properties->operator[](0)), num_props()); + + return match; + + } + + + + Object& Object::operator=(const Object& b) { + + if (is_owner()) { + + MR::Math::Vector::operator=(b); + + sze = b.sze; + *props = *b.props; + + + } else { + + // Might consider making these Exceptions instead of assertions, but this function probably should be as fast as possible. + assert(vsize() == b.vsize()); // Sizes need to match when fibre object is not owner of data. + assert(props_match(b)); // Properties need to match exactly when fibre object is not owner of data. + + const MR::Math::Vector& bvec = b; + + for (size_t i = 0; i < vsize(); ++i) + MR::Math::Vector::operator[](i) = bvec[i]; + + } + + return *this; + + } + + + Object& Object::operator=(const MR::Math::Vector& v) { + + assert(vsize() == v.size()); // Sizes need to match + + for (size_t i = 0; i < vsize(); ++i) + MR::Math::Vector::operator[](i) = v[i]; + + return *this; + + } + + + void Object::add_prop(const char* const name, double value) { + + if (!is_owner()) + throw Exception ("Cannot add property to a fibre object that does not own the underlying data (i.e. is a view onto part of a larger structure)."); + + //Loop through properties and insert the new property in the appropriate position for alphabetical order + size_t insert_index = 0; + + for (std::vector::iterator prop_it = props->begin(); prop_it != props->end(); ++prop_it) { + + int compare = strcmp(name, *prop_it); + + if (!compare) + throw Exception ("Property with the same name ('" + str(name) + "') already exists in fibre object"); + + // If new property name comes before current property in alphabetical order, insert it and break loop + if (compare < 0) { + props->insert(prop_it,name); + break; + } + + ++insert_index; + + } + + //Increment state vector to hold new property + MR::Math::Vector::resize(vsize()+1); + + //If the property wasn't inserted within the existing properties append it to the end of the list + if (insert_index == props->size()) { + + props->push_back(name); //Add pointer to property name to properties list + + MR::Math::Vector::operator[](vsize()-1) = value; //Set property value. + + } else { + + // Shuffle the values of the existing properties after the inserted property up a position + for (int prop_i = props->size()-1; prop_i > (int)insert_index; --prop_i) + MR::Math::Vector::operator[](bsize() + prop_i) = MR::Math::Vector::operator[](bsize() + prop_i - 1); + + MR::Math::Vector::operator[](bsize() + insert_index) = value; //Set property value of inserted property + + } + + } + + + void Object::remove_prop(const char* const name, bool ignore_missing) { + + if (!is_owner()) + throw Exception ("Cannot remove property from a fibre object that does not own the underlying data (i.e. is a view onto part of a larger structure)."); + + //Find iterator to property that matches given property name. + std::vector::iterator prop_it = props->begin(); + + for (; prop_it != props->end(); ++prop_it) + if (name == *prop_it) + break; + + if (prop_it != props->end()) { + + //Shift property values with indices higher than the removed property down a position + for (size_t i = (prop_it - props->begin()) + 1; i < num_props(); ++i) + MR::Math::Vector::operator[](bsize() + i-1) = MR::Math::Vector::operator[](bsize() + i); + + // Remove property from list + props->erase(prop_it); + + // Resize state vector + MR::Math::Vector::resize(vsize()-1); + + } else if (!ignore_missing) + throw Exception ("Fibre object does not have property '" + str(name) + "' (use 'ignore_missing' parameter to ignore)."); + + } + + + void Object::clear_props() { + + if (!is_owner()) + throw Exception ("Cannot clear properties from a fibre object that does not own the underlying data (i.e. is a view onto part of a larger structure)."); + + // Resize state vector to remove appended properties + MR::Math::Vector::resize(bsize()); + + // Clear properties list. + props->clear(); + + } + + + //FIXME: Change this to template function and make it so that only the properties relevant for the current object are copied. + void Object::copy_all_props(const Object& obj) { + + for (size_t prop_i = 0; prop_i < obj.num_props(); ++prop_i) { + + const char* key = obj.prop_key(prop_i); + + if (!has_prop(key)) + add_prop(key); + + prop(key) = obj.prop(prop_i); + + } + + } + + + + Object& Object::clear() { + + //Check to see if has props because if it does they will be retained (and MR::Math::Vector::resize(0) + //will throw an exception. + if (num_props()) { + + for (size_t prop_i = 0; prop_i < num_props(); ++prop_i) + MR::Math::Vector::operator[](prop_i) = MR::Math::Vector::operator[](bsize() + prop_i); + + MR::Math::Vector::resize(num_props()); + + } else + MR::Math::Vector::clear(); + + sze = 0; + + return *this; + + } + + Object& Object::clear(const std::vector& properties) { + + if (!props_match(&properties)) { + + clear_props(); + for (size_t prop_i = 0; prop_i < properties.size(); ++prop_i) + add_prop(properties[prop_i]); + + } + + clear(); + + return *this; + + } + + + + size_t Object::prop_index(const char* const name) const { + + // Find index of property + size_t prop_index = 0; + + for (; prop_index < num_props(); ++prop_index) + if (props->operator[](prop_index) == name) + break; + + //Check to see if property was found. + if (prop_index == num_props()) + throw Exception ("Fibre object does not have property '" + str(name) + "', it needs to be added by the 'add_prop' command beforehand.\n" + "Note that the comparison is performed by comparing pointer addresses, so the same (const char*) needs to be used throughout."); + + return prop_index; + + } + + + void Object::resize(size_t new_size, size_t row_size, double fill_value) { + + if (!is_owner()) + throw Exception ("Cannot resize fibre object that does not own the underlying data (i.e. is a view onto part of a larger structure)."); + + size_t old_bsize = bsize(); + size_t new_bsize = row_size * new_size; + + assert(old_bsize == row_size * sze); + + if (new_bsize > old_bsize) { + + //Extend state vector to hold the new base state data + MR::Math::Vector::resize(new_bsize + num_props()); + + //Shift the property values out to their new positions + for (int prop_i = num_props()-1; prop_i >= 0; --prop_i) + MR::Math::Vector::operator[](new_bsize + prop_i) = MR::Math::Vector::operator[](old_bsize + prop_i); + + for (size_t i = old_bsize; i < new_bsize; ++i) + MR::Math::Vector::operator[](i) = fill_value; + + } else if (new_bsize < old_bsize) { + + //Shift the property values in to their new positions + for (size_t prop_i = 0; prop_i < num_props(); ++prop_i) + MR::Math::Vector::operator[](new_bsize + prop_i) = MR::Math::Vector::operator[](old_bsize + prop_i); + + //Resize the underlying vector. + MR::Math::Vector::resize(new_bsize + num_props()); + + } + + sze = new_size; + + } + + + + Object& Object::set(double value) { + + for (uint i = 0; i < vsize(); ++i) + this->MR::Math::Vector::operator[](i) = value; + + return *this; + + } + + + Object& Object::push_back(const Coord& c) { + + if (!is_owner()) + throw Exception ("Cannot push back to a fibre object that does not own the underlying data (i.e. is a view onto part of a larger structure)."); + + //Add room for the new coord + resize(size() + 1); + + //Set the newly added coord. + operator[](size()-1) = c; + + return *this; + + } + + + Object& Object::invert() { + + for (uint i = 0; i < vsize(); ++i) + MR::Math::Vector::operator[](i) = -MR::Math::Vector::operator[](i); + + return *this; + + } + + + Coord Object::left_product(const MR::Math::Vector& row_vector) const { + + assert(row_vector.size() == size()); + + Coord product(0,0,0); + + for (size_t i = 0; i < size(); ++i) + product += operator[](i) * row_vector[i]; + + return product; + + } + + + std::string Object::load_matlab_str(const std::string& location, double scale) { + + std::string output; + + if (File::has_or_txt_extension(location)) { + Fibre::Strand::Set strands (location); + strands *= scale; + output = strands.matlab_str(); + + } else if (File::has_or_txt_extension(location)) { + Fibre::Tractlet::Set tractlets (location); + tractlets *= scale; + output = tractlets.matlab_str(); + + } else if (File::extension(location) == "sta") { + + MR::Math::Vector state (location); + state *= scale; + output = Math::matlab_str(state); + + } else + throw Exception ("Unrecognised file extension '" + File::extension(location) + "'."); + + return output; + + } + + std::ostream& operator<< (std::ostream& stream, const Object& fibre) { + + stream << std::endl; + + for (uint prop_i = 0; prop_i < fibre.num_props(); ++prop_i) + stream << fibre.prop_key(prop_i) << ": " << fibre.prop(prop_i) << std::endl; + + for (size_t i = 0; i < fibre.size(); i++) + stream << fibre[i] << std::endl; + + return (stream); + + } + + + + } + + } + +} + + diff --git a/src/bts/fibre/base/object.h b/src/bts/fibre/base/object.h new file mode 100644 index 0000000..969cd22 --- /dev/null +++ b/src/bts/fibre/base/object.h @@ -0,0 +1,795 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, Jan 27, 2011. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + +#ifndef __bts_fibre_base_h__ +#define __bts_fibre_base_h__ + +#include "math/vector.h" +#include "math/matrix.h" +#include "bts/triple.h" +#include "bts/coord.h" + +#define LOOP(op) \ + for (size_t i = 0; i < vsize(); ++i) { \ + op \ + } + + +// Derived base() +// { assert(!EMPTY_PROPS.size()); return Derived(sze, bvector(), &EMPTY_PROPS); } + +//! Redefines general functions inherited from Fibre::Object so they return references to the derived class +#define BASE_GENERAL_FUNCTIONS(Derived) \ +\ + Derived& set(double value) \ + { Base::Object::set(value); return *this;} \ +\ + void copy_props(const Base::Object& source) \ + { Base::Object::copy_props(*this, source); } \ +\ + std::map extract_and_set_props(std::map& combined_props) \ + { return Base::Object::extract_and_set_props(combined_props); } \ +\ + Derived& operator=(double c) \ + { MR::Math::Vector::operator=(c); return *this; } \ +\ + Derived& operator=(const MR::Math::Vector& v) \ + { Base::Object::operator=(v); return *this; } + +//! Redefines mulitiplication and division functions inherited from Fibre::Object so they return references to the derived class +#define BASE_INVERSION_FUNCTIONS(Derived) \ + Derived invert() \ + { invert(); return *this; } \ + \ + Derived operator-() const \ + { Derived answer (*this); answer.invert(); return answer; } \ + + +//! Redefines mulitiplication and division functions inherited from Fibre::Object so they return references to the derived class +#define BASE_MULT_DIVIDE_FUNCTIONS(Derived) \ + Derived& operator*= (const Derived& f) \ + { assert(props_match(f)); MR::Math::Vector::operator*=(f); return *this; } \ + \ + Derived& operator*= (double c) \ + { MR::Math::Vector::operator*=(c); return *this; } \ + \ + Derived& operator/= (const Derived& f) \ + { assert(props_match(f)); MR::Math::Vector::operator/=(f); return *this; } \ + \ + Derived& operator/= (double c) \ + { MR::Math::Vector::operator/=(c); return *this; } \ + \ + Derived operator* (const Derived& f) const \ + { Derived answer (*this); answer *= f; return answer;} \ + \ + Derived operator* (double c) const \ + { Derived answer (*this); answer *= c; return answer;} \ + \ + Derived operator/ (const Derived& f) const \ + { Derived answer (*this); answer /= f; return answer;} \ + \ + Derived operator/ (double c) const \ + { Derived answer (*this); answer /= c; return answer;} \ + + +//! Redefines addition and subtraction functions inherited from Fibre::Object so they return references to the derived class +#define BASE_ADD_SUBTRACT_FUNCTIONS(Derived) \ + Derived& operator+= (const Derived& f) \ + { assert(props_match(f)); MR::Math::Vector::operator+=(f); return *this; } \ + \ + Derived& operator-= (const Derived& f) \ + { assert(props_match(f)); MR::Math::Vector::operator-=(f); return *this; } \ + \ + Derived operator+ (const Derived& f) const \ + { Derived answer (*this); answer += f; return answer;} \ + \ + Derived operator- (const Derived& f) const \ + { Derived answer (*this); answer -= f; return answer;} \ + + + +namespace BTS { + + namespace Fibre { + + class Strand; + class Track; + class Tractlet; + + namespace Base { + + template class Set; + template class Tensor; + template class Reader; + template class Writer; + + /*! Forms the base of all fibre objects (with the exception of tensors). + * + * Objectd on MR::Math::Vector it can be treated as a one dimensional vector by statically casting it to + * MR::Math::Vector. However, note that the operator[]() is overidden in Fibre::Object to return a + * BTS::Triple. + * + */ + class Object : public MR::Math::Vector { + + friend class Tensor; + + public: + + const static char* ACS_SQRT_PROP; /**< Human-readable name of the Apparrent Connection Strength (ACS) property used for printing and saving. + NB: Existence checks for properties use the pointer address not + the character strings they refer to, so be sure to use exactly this char* + when using the acs property (same for all properties). */ + + //! Used to signify the end of a props array. + const static char* PROPS_LIST_END; + + /*! Passed to the operator[]() when constructing a fibre object view without the properties. + * Would like to make it const but the properties member variable of an object needs to be non const + * for the cases when it owns the properties. */ + static std::vector EMPTY_PROPS; + + public: + + /*! Loads a BTS data file and converts the loaded fibre object into a string that is readable by the MATLAB + * software package. Is used to store fibre objects used as parameters (such as step sizes) within fibre object + * file headers. + * + * @param location Location of the file containing the fibre object data + * @param scale An optional scalar that scales the loaded values + */ + static std::string load_matlab_str(const std::string& location, double scale = 1.0); + + + /*! Extracts properties for the template type T (i.e. those present in T::PROPS_LIST) from a map containing + * both template properties and extended properties, such as those loaded from a properties file, and + * returns them in a map. + * + * @param combined_properties map containing string versions of property keys and values amongst extended properties + * @return map of present property keys and their values as doubles + */ + template static std::map + extract_props(std::map& combined_properties); + + /*! Extracts propert keys for the template type T (i.e. those present in T::PROPS_LIST) from a vector containing + * both template property keys and extended property keys, such as those loaded from a properties file, and + * returns them in a vector. + * + * @param combined_header vector containing string versions of property keys amongst extended property keys + * @return vector of present property keys + */ + template static std::vector extract_props(std::vector& combined_header); + + /*! Selects propert keys for the template type T (i.e. those present in T::PROPS_LIST) from a vector containing + * both template property keys and extended property keys, such as those loaded from a properties file, and + * returns them in a vector. Differs from extract_props in that it doesn't delete the properties after they + * are selected. @see extract_props + * + * @param combined_header vector containing string versions of property keys amongst extended property keys + * @return vector of present property keys + */ + template static std::vector + select_props(const std::vector& combined_header); + + + + /*! Copies properties present in the source object into the destination if they appear in the PROPS_LIST + * of the destination + * + * @param destination Destination where the properties are copied to. + * @param source Source where the properties are copied from + */ + template void copy_props(T& destination, const Object& source); + + + + public: + + //TODO: Make all fibre objects implement a 'template_match' function that determines if all their fields are equivalent. + + protected: + + size_t sze; /**< The size of the fibre object */ + std::vector* props; /**< List of keys for properties that the fibre object has (the values are appended to the state vector). */ + + public: + + /*! Initialises a fibre base object with a given base_size, predefind props + * + * @param size Size of the base fibre object + * @param v_size the total "vector size" of the object + * @param props A list of props to be appended to the state vector. + */ + Object (size_t size, size_t v_size, const std::vector& properties) + : MR::Math::Vector (v_size), + sze(size), + props(new std::vector(properties)) { + + assert(props); + } + + + protected: + + /*! Initialises a fibre base object 'view' from an existing fibre object. As distinct + * from the first constructor the fibre object return does not 'own' the underlying data and therefore + * it cannot be resized and properties cannot be added or removed. However, the existing data fields can be + * freely accessed and changed see base MR::Math::Vector class. + * + * @param size The number of elements in the fibre object (not including properties) + * @param view MR::Math::Vector::View onto the underlying data + * @param props A list of props to be appended to the state vector. + * + * @see MR::Math::Vector::View + */ + Object (size_t size, const MR::Math::Vector::View& view, std::vector* props) + : MR::Math::Vector(view), + sze(size), + props(props) { + + assert(props); + } + + + public: + + + //! Copy constructor. + Object(const Object& b) + : MR::Math::Vector(b), sze(b.sze), props(new std::vector(*b.props)) {} + + + //! Deletes properties if owner of the data + ~Object() { + + if (owner) + delete props; + + } + + + /*! Sets the LHS fibre object to the RHS value. If the LHS object does not own the data (i.e. is a view onto + * part of a larger object) both the size and properties must match + * + * @param b The RHS fibre object + * @return Reference to LHS object + */ + Object& operator=(const Object& b); + + + /*! Sets the values of the object to the vector values in @arg v + * + * @param v Vector containing the values of the object + * @return Reference to LHS object + */ + Object& operator=(const MR::Math::Vector& v); + + /*! Clears the fibre object and resizes it out to the provided size filling with the @arg fill_value + * + * @param size Size of the new object + * @param row_size Row size of the new object + * @param props Properties of the new object + * @param fill_value Value used to fill the new object + */ + void reset(size_t size, + size_t row_size, + const std::vector& props, + double fill_value = NAN); + + /*! Clears the fibre object and frees the row size + * + * @param props Properties of the new object + */ + void reset(const std::vector& props, double fill_value = NAN); + + + + /*! Returns the value of the underlying GSLVector::owner field to specify if the fibre object is the + * owner of the data or does not own the data (i.e. is a view onto part of a larger structure + * + * @return Whether the fibre object owns the data + */ + bool is_owner() const + { return this->GSLVector::owner; } + + + //! Returns the "size" of the object, i.e. the number of @see BTS::Triple objects it contains + size_t size() const + { return sze; } + + + //! Returns the "vector size" of the object, i.e. the size of the underlying MR::Math::Vector object + size_t vsize() const + { return MR::Math::Vector::size(); } + + + /*! Returns the "base size" of the object, i.e. the vector size of the underlying MR::Math::Vector object + * minus the size of the properties. + */ + size_t bsize() const + { assert(MR::Math::Vector::size() >= num_props()); return MR::Math::Vector::size() - num_props(); } + + + //! Returns the number of properties the object has. + size_t num_props() const + { return props->size(); } + + + /*! Checks to see if the (intrinsic) properties match between two fibre objects, i.e. whether they have the same + * property keys. Is used before some mathematical operations + * + * @param props the props to match to + * @return true if fibre object matches the properties exactly. + */ + bool props_match(const std::vector* props) const; + + + /*! Checks to see if the (intrinsic) properties match between the current object and a second fibre object. + * @see props_match(const std::vecor& o) + * + * @param o Second fibre object + * @return true if fibre object matches the properties of the second fibre object exactly. + */ + bool props_match(const Object& o) const + { return props_match(o.props); } + + + /*! Adds a new property to the object. + * Can only be used if the object is not part of a larger object (eg. a set) + * + * @param[in] name Pointer to the property string (NB: comparisons are performed on the pointer itself not its + * contents so must be consitent application wide. It is implemented as a c-string instead of + * an enum so for input/output purposes only) + * @param[in] value The value assigned to the property + */ + void add_prop(const char* const name, double value = NAN); + + + /*! Adds a new property to the object. + * Can only be used if the object is not part of a larger object (eg. a set) + * + * @param[in] name Pointer to the property string (NB: comparisons are performed on the pointer itself not its + * contents so must be consitent application wide. It is implemented as a c-string instead of + * an enum so for input/output purposes only) + */ + bool has_prop(const char* name) const + { for (size_t prop_i = 0; prop_i < num_props(); ++prop_i) { if (name == props->operator[](prop_i)) return true; } return false; } + + + /*! Adds a new property to the object. + * Can only be used if the object is not part of a larger object (eg. a set) + * + * @param[in] name The property name + * @param[in] ignore_missing Set to true if it doesn't matter whether the property is present + */ + void remove_prop(const char* const name, bool ignore_missing = false); + + + //! Removes all properties. + void clear_props(); + + + /*! Copies all properties from the object @arg obj to the current object + * + * @param obj + */ + void copy_all_props(const Object& obj); + + + /*! Returns the index of the given property relative the other properties + * + * @param name + * @return index of property for the given objecct + */ + size_t prop_index(const char* const name) const; + + + /*! Access the property at the given index. + * + * @param index of property + * @return reference of corresponding property + */ + double& prop(size_t index) + { assert(index < num_props()); return MR::Math::Vector::operator[](bsize() + index); } + + + /*! Access the property at the given index for const object. + * + * @param index of property + * @return reference of corresponding property + */ + const double& prop(size_t index) const + { assert(index < num_props()); return MR::Math::Vector::operator[](bsize() + index); } + + + /*! Return the name of the property at the given index + * + * @param index of property + * @return key for the current index + */ + const char* prop_key(size_t index) const + { assert(index < num_props()); return props->operator[](index); } + + + /*! Return a copy of the property names vector + * + * @return a copy of the property names vector + */ + std::vector prop_keys() const + { return *props; } + + + /*! Access the property at the given index. + * + * @param name of property + * @return reference of corresponding property + */ + double& prop(const char* const name) + { return prop(prop_index(name)); } + + + /*! Access the property at the given index for const object + * + * @param name of property + * @return reference of corresponding property + */ + const double& prop(const char* const name) const + { return prop(prop_index(name)); } + + + /*! Sets all values (including intrinsic properties) to the given value. + * + * @param value The double to set all values of the fibre object to + */ + Object& set(double value); + + + /*! Accesses the element at the given index + * + * @param idx the index of the element + * @return The fibre object at the given index + */ + Coord operator[](size_t idx) + { return Coord(sub(idx * 3, (idx+1) * 3)); } + + + /*! Accesses the element at the given index + * + * @param idx the index of the element + * @return The fibre object at the given index + */ + const Coord operator[](size_t idx) const + { return Coord(sub(idx * 3, (idx+1) * 3)); } + + + /*! Accesses the element at the given index (synonym for operator[]) + * + * @param idx the index of the element + * @return The fibre object at the given index + */ + Coord elem(size_t idx) + { return operator[](idx); } + + + /*! Accesses the element at the given index (synonym for operator[] const) + * + * @param idx the index of the element + * @return The fibre object at the given index + */ + const Coord elem(size_t idx) const + { return operator[](idx); } + + + /*! Append another @see Coord to the the fibre object + * + * @param c A coord to set the fibre object base values to. + */ + Object& push_back(const Coord& c); + + + //! Remove all base values from the fibre object (preserves properties) + Object& clear(); + + /*! Remove all base values from the fibre object and reset properties to those provided + * + * @param props New properties to be used for the object + * @return + */ + Object& clear(const std::vector& props); + + //! Sets all values to zero + Object& zero() + { set(0.0); return *this; } + + + //! Sets all values to Not-a-Number (NaN) + Object& invalidate() + { set(NAN); return *this; } + + + /*! Inverts all values in a copy of the fibre object + * + * @return A copy of the fibre object that has been inverted + */ + Object& invert(); + + + /*! Inverts all values in a copy of the fibre object + * + * @return A copy of the fibre object that has been inverted + */ + Object operator-() const + { Object answer (*this); answer.invert(); return answer; } + + + /*! Calculates the square of the 2-norm + * + * @return The squared-2-norm + */ + double norm2() const + { return MR::Math::norm2(*this); } + + /*! Calculates the 2-norm + * + * @return The squared-2-norm + */ + double norm() const + { return MR::Math::sqrt(norm2()); } + + + /*! Calculates the inner_product (dot) between two fibres + * + * @param fibre The fibre object to find the inner product with + * @return The inner product + */ + double inner_product(const Object& fibre) + { assert(props_match(fibre)); return MR::Math::dot(*this,fibre); } + + + /*! Treats the fibre object as a Mx3 matrix and then pre-multiplies it with a 1xM vector to produce a 1X3 triple. + * + * @param row_vector A 1xM vector (where M is the size() of the fibre object + * @return The left product + */ + Coord left_product(const MR::Math::Vector& row_vector) const; + + + BASE_MULT_DIVIDE_FUNCTIONS(Object); + + + BASE_ADD_SUBTRACT_FUNCTIONS(Object); + + + /*! Inserts properties present in the current object into the combined properties map provided + * + * @param props The map into which the properties of the current object will be inserted + * @return A reference to the passed map + */ + std::map& insert_props(std::map& props) const; + + + /*! Inserts property keys present in the current object into the combined property keys vector provided + * + * @param props The other properties to be combined with this objects properties. + * @return The vector containing the combined property keys + */ + std::vector insert_prop_keys(const std::vector& props) const; + + + /*! Extracts properties from combined properties that are present in T::PROPS_LIST provided and set them in + * this object. + * + * @param combined_properties Map containing both properties and extended properties. + * @return A reference to the passed properties + */ + template std::map& + extract_and_set_props(std::map& combined_properties); + + + //! Return a MR::Math::Vector window onto the underlying state vector with properties + MR::Math::Vector vector() + { return MR::Math::Vector(data, vsize(), stride()); } + + + //! Return a MR::Math::Vector window onto the underlying state vector without properties + MR::Math::Vector bvector() + { return sub(0,bsize()); } + + + //! Return a MR::Math::Vector window onto the underlying state vector without properties + const MR::Math::Vector bvector() const + { return sub(0,bsize()); } + + //! Return a MR::Math::Matrix window to the underlying state vector interpreted as a matrix (without properties). + MR::Math::Matrix bmatrix(size_t row_size) + { return MR::Math::Matrix(data, size(), row_size, stride()); } + + //! Return a MR::Math::Matrix window to the underlying state vector interpreted as a matrix (without properties). + const MR::Math::Matrix bmatrix(size_t row_size) const + { return MR::Math::Matrix(data, size(), row_size, stride()); } + + + /*! Resize the number of elements in the fibre object (does not effect the properties). + * More general form is provided here for use in Base::Set + * + * @param size The number of elements in the new fibre object + * @param fill_value The value assigned to the any empty values. + */ + void resize(size_t size, double fill_value = NAN) + { resize(size, 3, fill_value); } + + template friend class Set; + + //! Only included to get template function to work (a strand will never have element properties. + Object& push_back(const Coord& c, bool without_properties) + { return push_back(c); } + + protected: + + /*! Resize the number of elements in the fibre object general form is provided here for use in derived classes + * such as Tractlet and Set classes. + * + * @param size The number of elements in the new fibre object + * @param fill_value The value assigned to the any empty values. + * @param new_row_size The size of the new rows (only applicable if row size if variable). + */ + void resize(size_t size, size_t row_size, double fill_value); + + }; + + + + std::ostream& operator<< (std::ostream& stream, const Object& fibre); + + + template std::map Object::extract_props(std::map& loaded_props) { + + std::map intrinsic; + + // Declare the variables used within the loop + size_t prop_i = 0; + const char* prp_key; + + while ((prp_key = T::PROPS_LIST[prop_i]) != PROPS_LIST_END) { + if (loaded_props.count(prp_key)) { + intrinsic[prp_key] = to(loaded_props[prp_key]); + loaded_props.erase(loaded_props.find(prp_key)); + } + ++prop_i; + } + + return intrinsic; + + } + + + template std::vector Object::extract_props(std::vector& header) { + + std::vector intrinsic; + + // Declare the variables used within the loop + size_t prop_i = 0; + const char* prp_key; + std::vector::iterator prop_it; + + while ((prp_key = T::PROPS_LIST[prop_i]) != PROPS_LIST_END) { + + std::string prp_key_str = str(prp_key); + + prop_it = std::find(header.begin(), header.end(), prp_key_str); + + if (prop_it != header.end()) { + intrinsic.push_back(prp_key); + header.erase(prop_it); + } + ++prop_i; + } + + return intrinsic; + + } + + + template std::vector Object::select_props(const std::vector& properties) { + + std::vector selected; + + // Declare the variables used within the loop + size_t prop_i = 0; + const char* prp_key; + + while ((prp_key = T::PROPS_LIST[prop_i]) != PROPS_LIST_END) { + + if (std::find(properties.begin(), properties.end(), prp_key) != properties.end()) + selected.push_back(prp_key); + + ++prop_i; + } + + return selected; + + } + + + + template void Object::copy_props(T& destination, const Object& source) { + + if (source.num_props()) { + + // Declare the variables used within the loop + size_t prop_i = 0; + const char* prp_key; + + while ((prp_key = T::PROPS_LIST[prop_i]) != PROPS_LIST_END) { + + std::vector::const_iterator prop_it = std::find(source.props->begin(), source.props->end(), prp_key); + + if (prop_it != source.props->end()) { + if (destination.has_prop(prp_key)) + destination.prop(prp_key) = source.prop(prp_key); + else + destination.add_prop(prp_key, source.prop(prp_key)); + } + + ++prop_i; + } + + } + + } + + + template std::map& Object::extract_and_set_props(std::map& combined_properties) { + + std::map props = extract_props(combined_properties); + + for (std::map::iterator prop_it = props.begin(); prop_it != props.end(); ++prop_it) + if (!has_prop(prop_it->first)) + add_prop(prop_it->first, prop_it->second); + else + prop(prop_it->first) = prop_it->second; + + return combined_properties; + + } + + + + inline std::map& Object::insert_props(std::map& properties) const { + + for (uint prop_i = 0; prop_i < num_props(); ++prop_i) + properties[prop_key(prop_i)] = str(prop(prop_i)); + + return properties; + + } + + + } + + } + +} + +#undef LOOP + +#endif /* __bts_fibre_object_h__ */ diff --git a/src/bts/fibre/base/properties_old.h b/src/bts/fibre/base/properties_old.h new file mode 100644 index 0000000..fa8b121 --- /dev/null +++ b/src/bts/fibre/base/properties_old.h @@ -0,0 +1,70 @@ +/* + Copyright 2010 Brain Research Institute/National ICT Australia (NICTA), Melbourne, Australia + + Written by Thomas G Close, 04/06/2010. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + +*/ + +#ifndef __bts_fibre_properties_h__ +#define __bts_fibre_properties_h__ + +#include +#include + + +namespace BTS { + + namespace Fibre { + + + class Properties : public std::map { + + public: + + class Extended; + class Header; + template class Intrinsic_tpl; + class Intrinsic; + + public: + + Properties() {} + + Properties(const std::map& properties) + : std::map(properties) {} + + + Properties(const MR::DWI::Tractography::Properties& mr_properties) + : std::map(mr_properties) {} + + + Properties& operator=(const std::map& properties) + { std::map::operator=(properties); return *this; } + + + ~Properties() {} + + + }; + + + } + +} + +#endif /* __bts_fibre_properties_h__ */ diff --git a/src/bts/fibre/base/reader.cpp.h b/src/bts/fibre/base/reader.cpp.h new file mode 100644 index 0000000..df24494 --- /dev/null +++ b/src/bts/fibre/base/reader.cpp.h @@ -0,0 +1,353 @@ +/* + Copyright 2010 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close on Jun 3, 2010. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + +*/ + +#ifndef __bts_fibre_base_reader_cpp_h__ +#define __bts_fibre_base_reader_cpp_h__ + +#include "mrtrix.h" +#include "file/key_value.h" + +#include "bts/fibre/base/object.h" + +namespace BTS { + + namespace Fibre { + + namespace Base { + + template const Coord Reader::END_OF_DATA (INFINITY, INFINITY, INFINITY); + + template const std::string Reader::PROP_FILE_PREAMBLE = "%%% Extended Properties File %%% - keys: "; + + + template void Reader::open (const std::string& location) { + + ext_props.clear(); + + MR::File::KeyValue kv (location, "mrtrix tracks"); + std::string data_file; + + while (kv.next()) { + std::string key = MR::lowercase (kv.key()); + if (key == "file") data_file = kv.value(); + else if (key == "datatype") dtype.parse (kv.value()); + else if (key != "roi") ext_props[key] = kv.value(); + } + + if (dtype == MR::DataType::Undefined) throw Exception ("no datatype specified in fibre object file '" + location + "'"); + if (dtype != MR::DataType::Float32LE && dtype != MR::DataType::Float32BE && + dtype != MR::DataType::Float64LE && dtype != MR::DataType::Float64BE) + throw Exception ("only supported datatype for tracks location are Float32LE, Float32BE, Float64LE & Float64BE (in tracks location \"" + location + "\")"); + + if (data_file.empty()) throw Exception ("missing 'file' specification in fibre object file '" + location + "'"); + + std::istringstream locations_stream (data_file); + std::string fname; + locations_stream >> fname; + int64_t offset = 0; + if (locations_stream.good()) { + try { locations_stream >> offset; } + catch (...) { throw Exception ("invalid data offset specified, \"" + fname + "\", in fibre object file '" + location + "'"); } + } + + if (fname != ".") fname = MR::Path::join (MR::Path::dirname (location), fname); + else fname = location; + + in.open (fname.c_str(), std::ios::in | std::ios::binary); + if (!in) throw Exception ("error opening fibre object file \"" + fname + "\": " + strerror(errno)); + in.seekg (offset); + + begin = in.tellg(); + + //------------------------- + // Load element_properties + //-------------------------- + + std::string elem_props_location = location + "x"; + + if (File::is_file(elem_props_location)) { + + prop_in.open(elem_props_location.c_str()); + + prop_hdr = read_props_header(prop_in); + ext_prp_keys = prop_hdr; + prp_keys = Object::extract_props(ext_prp_keys); + + prop_begin = prop_in.tellg(); + + } else { + + prop_hdr.clear(); + prp_keys.clear(); + ext_prp_keys.clear(); + + prop_begin = 0; + + } + + } + + + template void Reader::rewind() { + + in.seekg(begin); + + if (prop_begin) + prop_in.seekg(prop_begin); + + } + + + template bool Reader::next_basic (T& fibre_object) { + + if (!in.good()) + return false; + + Coord first_coord = read_coord(); + + if ((Triple)first_coord == (Triple)END_OF_DATA) + return false; + + read(fibre_object, first_coord); + + return true; + + } + + + template bool Reader::next (T& fibre_object, std::map& properties_row) { + + + fibre_object.clear(prp_keys); + properties_row.clear(); + + if (next_basic(fibre_object)) { + + if (prop_hdr.size()) { + std::string line; + + if (!std::getline(prop_in, line)) + throw Exception ("No corresponding line found in extended properties file."); + + properties_row = parse_props_line(prop_hdr, line); + + fibre_object.extract_and_set_props(properties_row); + + } + + } else + return false; + + return true; + + } + + + template bool Reader::next (T& fibre_object) { + + std::map properties_row; + + return next(fibre_object, properties_row); + + } + + + template Coord Reader::read_coord () { + + if (!in.good()) + throw Exception ("Corrupted fibre object file '" + file_location +"'."); + + Coord t; + + if (dtype == MR::DataType::Float64LE) { + + in.read ((char*) &t[0], sizeof (double)*3); + + t[X] = MR::ByteOrder::LE(t[X]); + t[Y] = MR::ByteOrder::LE(t[Y]); + t[Z] = MR::ByteOrder::LE(t[Z]); + + } else if (dtype == MR::DataType::Float64BE){ + + in.read ((char*) &t[0], sizeof (double)*3); + + t[X] = MR::ByteOrder::BE(t[X]); + t[Y] = MR::ByteOrder::BE(t[Y]); + t[Z] = MR::ByteOrder::BE(t[Z]); + + } else if (dtype == MR::DataType::Float32LE) { + + Triple t_float; + + in.read ((char*) &t_float[0], sizeof(float)*3); + + t[X] = (double)MR::ByteOrder::LE(t_float[X]); + t[Y] = (double)MR::ByteOrder::LE(t_float[Y]); + t[Z] = (double)MR::ByteOrder::LE(t_float[Z]); + + } else if (dtype == MR::DataType::Float32BE){ + + Triple t_float; + + in.read ((char*) &t_float[0], sizeof (float)*3); + + t[X] = (double)MR::ByteOrder::BE(t_float[X]); + t[Y] = (double)MR::ByteOrder::BE(t_float[Y]); + t[Z] = (double)MR::ByteOrder::BE(t_float[Z]); + + } else + throw Exception ("Unsupported dataype '" + str(dtype.specifier()) + "'."); + + return t; + + } + + + template void Reader::read (Coord& t, const Coord& first_t) { + + t = first_t; + + } + + + template template inline void Reader::read (U& fibre_object, const Coord& first_t) { + + Coord first_coord = first_t; + + while ((Triple)first_coord != (Triple)U::FILE_SEPARATOR) { + + typename U::Element elem; + + elem.clear(); + + read(elem, first_coord); + + fibre_object.push_back(elem, false); // Push back ignoring properties. + + first_coord = read_coord(); + + } + + + } + + + template std::map Reader::parse_props_line(const std::vector& header, const std::string& line) { + + std::istringstream line_stream(line); + + std::string value; + std::map prop_row; + + size_t count = 0; + while(std::getline(line_stream, value, '\t')) { + if (count > header.size()) + throw Exception ("More elements found on line (" + str(count) + ") than exist in header (" + str(header.size()) + "). The line was {" + line + "} and the header is " + str(header) + "."); + prop_row[header[count]] = value; + ++count; + } + + return prop_row; + + } + + + + template void Reader::read_props_preamble(std::ifstream& file_in) { + + check_good(file_in); + + char file_intro[PROP_FILE_PREAMBLE.size()+2]; + + file_in.get(file_intro, PROP_FILE_PREAMBLE.size()+1); + + if (strcmp(file_intro, PROP_FILE_PREAMBLE.c_str())) + throw Exception ("Required file intro '" +PROP_FILE_PREAMBLE + "' was not found at start of extended properties file (found '" + std::string(file_intro) +"' instead)."); + + } + + + template std::vector Reader::read_props_header(std::ifstream& file_in) { + + read_props_preamble(file_in); + + check_good(file_in); + + std::vector header; + + std::string key_line; + + if (!std::getline(file_in, key_line)) + throw Exception ("No header found in extended properties file."); + + std::istringstream line_stream(key_line); + + std::string key; + + header.clear(); + + while(std::getline(line_stream, key, '\t')) + header.push_back(key); + + return header; + + } + + + template Coord TextReader::read_coord () { + + Coord coord; + + if (!this->in.good()) + throw Exception ("Corrupted fibre object file '" + this->file_location +"'."); + + std::string next_value; + + for (int dim_i = 0; dim_i < 3; dim_i++) { + + this->in >> next_value; + + if (next_value == "nan") + coord[dim_i] = NAN; + else if (next_value == "inf") + coord[dim_i] = INFINITY; + else if (next_value == "-inf") + coord[dim_i] = -INFINITY; + else if (strspn(next_value.c_str(),"-e0.123456789") == next_value.size()) + coord[dim_i] = to(next_value); + else + dim_i--; //If next_value is not a number empty skip. (this is mainly for the start of the file which has some funny bits). + + } + + return coord; + } + + + + } + + } + +} + +#endif /* __bts_fibre_reader_icpp__ */ diff --git a/src/bts/fibre/base/reader.h b/src/bts/fibre/base/reader.h new file mode 100644 index 0000000..8ee00d2 --- /dev/null +++ b/src/bts/fibre/base/reader.h @@ -0,0 +1,175 @@ +/* + Copyright 2010 Brain Research Institute/National ICT Australia (NICTA), Melbourne, Australia + + Written by Thomas G Close, 5/05/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + +*/ + +#ifndef __bts_fibre_base_reader_forward_h__ +#define __bts_fibre_base_reader_forward_h__ + +namespace BTS { + + namespace Fibre { + + namespace Base { + + template class Reader; + + } + + } + +} +#include "data_type.h" +#include "get_set.h" +#include "bts/coord.h" + +#include "bts/common.h" + +#include "bts/file.h" + + +namespace BTS { + + namespace Fibre { + + namespace Base { + + template class Reader { + + public: + + static const Coord END_OF_DATA; + const static std::string PROP_FILE_PREAMBLE; + + public: + + static std::map parse_props_line(const std::vector& header, + const std::string& line); + + static std::vector read_props_header(std::ifstream& line); + + static void read_props_preamble(std::ifstream& file_in); + + static void check_good(std::ifstream& in) + { if (!in.good()) throw Exception ("Could not read from properties file."); } + + + protected: + + std::ifstream in; + MR::DataType dtype; + size_t count; + std::string file_location; + std::map ext_props; + std::vector prop_hdr; + std::vector prp_keys; + std::vector ext_prp_keys; + std::ifstream prop_in; + off64_t prop_begin; + off64_t begin; + + public: + + Reader () {} + + Reader (const std::string& location) + { open(location); } + + virtual ~Reader() + { close(); } + + + bool next(T& fibre); + + bool next(T& fibre, std::map& properties_row); + + void close() + { in.close(); prop_in.close(); } + + void open (const std::string& location); + + //TODO: Refactor to extend_elem_prop_keys() or something + std::vector extend_prop_keys() const + { return ext_prp_keys; } + + + std::vector prop_keys() const + { return prp_keys; } + + + std::map get_extend_props() const + { return ext_props; } + + void rewind(); + + protected: + + std::vector prop_header() const + { return prop_hdr; } + + + bool next_basic(T& fibre); + +#ifdef FAST_READWRITE // Means that Text::Writer will no longer work but avoids a virtual function call here (maybe a bit OTT but an option if you feel like it) + Coord read_coord (); +#else + virtual Coord read_coord (); +#endif + + void read (Coord& coord, const Coord& first_t); + + + template void read (U& fibre_object, const Coord& first_t); + + + }; + + + template class TextReader : public Fibre::Base::Reader { + + //Public static variables, nested classes and typedefs + public: + + TextReader () {} + + TextReader (const std::string& location) + : Fibre::Base::Reader(location) {} + + Coord read_coord (); + + }; + + + } + + } + +} + + + +#include "bts/fibre/base/reader.cpp.h" + +#endif + + + + + diff --git a/src/bts/fibre/base/set.cpp.h b/src/bts/fibre/base/set.cpp.h new file mode 100644 index 0000000..9fccceb --- /dev/null +++ b/src/bts/fibre/base/set.cpp.h @@ -0,0 +1,1935 @@ +/* + Copyright 2010 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close on Jun 3, 2010. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + +*/ + +#ifndef ___bts_fibre_base_set_cpp_h__ +#define ___bts_fibre_base_set_cpp_h__ + +#include "bts/common.h" + +#include "bts/fibre/base/set.h" +#include "bts/coord.h" + +#include "bts/fibre/base/writer.h" +#include "bts/fibre/base/reader.h" + + +namespace BTS { + + namespace Fibre { + + namespace Base { + + template const char* Set::BASE_INTENSITY_PROP = "base_intensity"; + template const Coord Set::FILE_SEPARATOR = Triple(-INFINITY, NAN, INFINITY); + template const std::string Set::PROPS_FILE_PREAMBLE = "%%% Extended Properties File %%% - keys: "; + template const std::string Set::BUNDLE_INDEX_EPROP = "bundle_index"; + template const std::string Set::NUM_ELEMS_EXT_PROP = "__num_elems__"; + template const std::string Set::ELEM_SIZE_EXT_PROP = "__elem_degree__"; + template const std::string Set::ELEM_VSIZE_EXT_PROP = "__elem_row_size__"; + + + template Set::Set (const Set& set) + : Object(set), + vrows(set.vrows), + rsize(set.rsize), + elem_dgree(set.elem_dgree), + row_ends(set.row_ends ? (size_t*)malloc(sizeof(size_t) * set.size()) : 0), + elem_dgrees(set.elem_dgrees ? (size_t*)malloc(sizeof(size_t) * set.size()) : 0), + elem_props(new std::vector(*set.elem_props)) { + + if (size() && var_elem_degrees()) { + + if (!elem_dgrees) + throw Exception ("Allocation of elem_dgrees (" + str(sizeof(size_t) * size()) + ") failed." ); + + if (!row_ends) + throw Exception ("Allocation of row_ends (" + str(sizeof(size_t) * size()) + ") failed." ); + + memcpy(row_ends,set.row_ends, sizeof(size_t) * size()); + memcpy(elem_dgrees,set.elem_dgrees, sizeof(size_t) * size()); + + } + + ext_props = set.ext_props ? new std::map(*set.ext_props) : 0; + ext_elem_prop_keys = set.ext_elem_prop_keys ? new std::vector(*set.ext_elem_prop_keys) : 0; + ext_elem_prop_defaults = set.ext_elem_prop_defaults ? new std::vector(*set.ext_elem_prop_defaults) : 0; + ext_elem_prop_values = set.ext_elem_prop_values ? new std::vector >(*set.ext_elem_prop_values) : 0; + + } + + + template std::vector Set::extend_prop_keys() const { + + std::vector prp_keys; + + if (ext_props) + for (std::map::iterator prop_it = ext_props->begin(); prop_it != ext_props->end(); ++prop_it) + prp_keys.push_back(prop_it->first); + + return prp_keys; + + } + + + template bool Set::elem_props_match(const std::vector* elem_properties) const { + + bool match; + + if (elem_props == elem_properties) // Point to the same properties + match = true; + else if (!elem_props->size() && !elem_properties->size()) // Both contain no properties + match = true; + else if (num_elem_props() != elem_properties->size()) // Are of different size + match = false; + else // Compare the property pointers (relies on the fact that properties are sorted by order of memory location when they are inserted). + match = !memcmp(&(elem_props->operator[](0)),&(elem_properties->operator[](0)), num_elem_props()); + + return match; + + } + + + + template size_t Set::initial_vsize(size_t size, size_t* elem_degrees, size_t elem_row_size, size_t num_elem_props, size_t num_props) { + + size_t vsize = 0; + + for (size_t i = 0; i < size; ++i) + vsize += elem_degrees[i] * elem_row_size + num_elem_props; + + vsize += num_props; + + return vsize; + + } + + + + template void Set::set_extend_props(const std::map& extended_props) { + + if (ext_props) + delete ext_props; + + ext_props = new std::map(extended_props); + + } + + + template void Set::set_extend_prop(const std::string& prop, const std::string& value) { + + if (!ext_props) + ext_props = new std::map(); + + (*ext_props)[prop] = value; + + } + + + + template Set& Set::operator=(const Set& set) { + + // If owner recreate all structures (if not check to see if all intrinsic properties and sizes are the same. + if (is_owner()) { + + MR::Math::Vector::operator=(set); + + *props = *set.props; + *elem_props = *set.elem_props; + + // Copy across the variable row ends and elem sizes if present + if (set.var_elem_degrees() && set.sze) { + + if (!var_elem_degrees()) { + row_ends = (size_t*)malloc(sizeof(size_t) * set.sze); + elem_dgrees = (size_t*)malloc(sizeof(size_t) * set.sze); + } else { + row_ends = (size_t*)realloc(row_ends,sizeof(size_t) * set.sze); + elem_dgrees = (size_t*)realloc(elem_dgrees,sizeof(size_t) * set.sze); + } + + if (!row_ends) + throw Exception ("Allocation of row_ends (" + str(sizeof(size_t) * set.sze) + ") failed."); + + if (!elem_dgrees) + throw Exception ("Allocation of elem_dgrees (" + str(sizeof(size_t) * set.sze) + ") failed."); + + memcpy(row_ends, set.row_ends, sizeof(size_t) * set.sze); + memcpy(elem_dgrees, set.elem_dgrees, sizeof(size_t) * set.sze); + + } else if (var_elem_degrees() && sze) { + + free(row_ends); + free(elem_dgrees); + row_ends = 0; + elem_dgrees = 0; + + } + + //Now that all the (possibly) variable row sizes componenets are copied across copy the fixed row size components. + sze = set.sze; + vrows = set.vrows; + rsize = set.rsize; + elem_dgree = set.elem_dgree; + + // Copy across the element properties if present + if (set.ext_elem_prop_keys) { + + assert(set.ext_elem_prop_defaults); + assert(set.ext_elem_prop_values); + + if (!ext_elem_prop_keys) { + + assert(!ext_elem_prop_defaults); + assert(!ext_elem_prop_values); + + ext_elem_prop_keys = new std::vector(*set.ext_elem_prop_keys); + ext_elem_prop_defaults = new std::vector(*set.ext_elem_prop_defaults); + ext_elem_prop_values = new std::vector< std::vector >(*set.ext_elem_prop_values); + + } else { + + assert(ext_elem_prop_defaults); + assert(ext_elem_prop_values); + + ext_elem_prop_keys->operator=(*set.ext_elem_prop_keys); + ext_elem_prop_defaults->operator=(*set.ext_elem_prop_defaults); + ext_elem_prop_values->operator=(*set.ext_elem_prop_values); + + } + + } else { + + assert(!set.ext_elem_prop_defaults); + assert(!set.ext_elem_prop_values); + + if (ext_elem_prop_keys) { + + free(ext_elem_prop_keys); + free(ext_elem_prop_defaults); + free(ext_elem_prop_values); + ext_elem_prop_keys = 0; + ext_elem_prop_defaults = 0; + ext_elem_prop_values = 0; + + } + + } + + + //Copy accross the set-wide properties if present + if (set.ext_props) { + if (!ext_props) + ext_props = new std::map(*set.ext_props); + else + *ext_props = *set.ext_props; + + } else if (ext_props) { + free(ext_props); + ext_props = 0; + } + + + + } else { + + // Might consider making these Exceptions instead of assertions, but this function probably should be as fast as possible. + assert(size() == set.size()); // Sizes need to match when fibre object is not owner of data. + assert(props_match(set)); // Properties need to match exactly when fibre object is not owner of data. + assert(rsize == set.rsize); // Row sizes need to be the same (NB: when variable they should both be 0). + assert(elem_dgree == set.elem_dgree); + assert(!var_elem_degrees() || memcmp(row_ends, set.row_ends, size() * sizeof(size_t))); // All row sizes must match for variable row sizes case. + assert(!var_elem_degrees() || memcmp(elem_dgrees, set.elem_dgrees, size() * sizeof(size_t))); // All row sizes must match for variable row sizes case. + assert(var_elem_degrees() == set.var_elem_degrees()); + + const MR::Math::Vector& setvec = set; + + for (size_t i = 0; i < vsize(); ++i) + MR::Math::Vector::operator[](i) = setvec[i]; + + } + + return *this; + + } + + + + template void Set::resize(size_t new_size, double fill_value, size_t new_elem_degree, size_t new_elem_vsize) { + + //FIXME: Needs some restructuring as functionality from Object was moved in here. + + if (!is_owner()) + throw Exception ("Cannot resize fibre object that does not own the underlying data (i.e. is a view onto part of a larger structure)."); + + // Preserve the old size and base size. + size_t old_size = size(); + size_t old_bsize = bsize(); + + //Calculate the the new base size + size_t new_bsize; + + //If new rsize is set (i.e. non-variable row sizes) simply set the bsize to new_size * rsize + if (!var_elem_degrees()) { + + if (new_elem_degree && (new_elem_degree != elem_dgree)) + throw Exception ("The the new element size does not match that of set, and the set elements are not variable (see free_elem_degrees())."); + + if (new_elem_vsize && (new_elem_vsize != rsize)) + throw Exception ("The the new element vsize does not match that of set, and the set elements are not variable (see free_elem_degrees())."); + + new_bsize = new_size * rsize; + + } else { + + //If variable row and the new size is smaller the previous simply take the row end at that index to be the new bsize(). + if (new_size <= size()) + new_bsize = new_size ? row_end(new_size-1) : 0; + + //If variable row and the new size is greater than the previous take the multiple of the new vsize. + else + new_bsize = (size() ? row_end(size()-1) : 0) + (new_size - size()) * new_elem_vsize; + + } + + //Resize the underlying vector + if (new_bsize > old_bsize) { + + //Extend state vector to hold the new base state data + MR::Math::Vector::resize(new_bsize + num_props()); + + //Shift the property values out to their new positions + for (int prop_i = num_props()-1; prop_i >= 0; --prop_i) + MR::Math::Vector::operator[](new_bsize + prop_i) = MR::Math::Vector::operator[](old_bsize + prop_i); + + for (size_t i = old_bsize; i < new_bsize; ++i) + MR::Math::Vector::operator[](i) = fill_value; + + } else if (new_bsize < old_bsize) { + + //Shift the property values in to their new positions + for (size_t prop_i = 0; prop_i < num_props(); ++prop_i) + MR::Math::Vector::operator[](new_bsize + prop_i) = MR::Math::Vector::operator[](old_bsize + prop_i); + + //Resize the underlying vector. + MR::Math::Vector::resize(new_bsize + num_props()); + + } + + + //If variable rows then extend the variable rows and elem sizes variables. + if (var_elem_degrees()) { + + if (new_size) { + + if (row_ends) + row_ends = (size_t*)realloc(row_ends, sizeof(size_t) * new_size); + else + row_ends = (size_t*)malloc(sizeof(size_t) * new_size); + + if (!row_ends) + throw Exception ("Failed to allocate array for row_ends (" + str(sizeof(size_t) * new_size) + " bytes requested)."); + + if (elem_dgrees) + elem_dgrees = (size_t*)realloc(elem_dgrees, sizeof(size_t) * new_size); + else + elem_dgrees = (size_t*)malloc(sizeof(size_t) * new_size); + + if (!elem_dgrees) + throw Exception ("Failed to allocate array for elem_dgrees (" + str(sizeof(size_t) * new_size) + " bytes requested)."); + + + size_t row_start = old_bsize; + for (size_t row_i = old_size; row_i < new_size; ++row_i) + row_ends[row_i] = row_start = row_start + new_elem_vsize; + + //If new_size > old_size, fill with the new elem sizes + for (size_t row_i = old_size; row_i < new_size; ++row_i) + elem_dgrees[row_i] = new_elem_degree; + + } else { + + if (row_ends) { + assert(elem_dgrees); + + free(row_ends); + free(elem_dgrees); + elem_dgrees = 0; + row_ends = 0; + } + } + + } + + //Update the size of the set + sze = new_size; + + //Extend the element properties. + if (num_extend_elem_props()) { + + for (size_t key_i = 0; key_i < num_extend_elem_props(); ++key_i) + ext_elem_prop_values->operator[](key_i).resize(new_size, ext_elem_prop_defaults->operator[](key_i)); + + } + + } + + + + template T Set::push_back(const T& elem) { + + rand_double(); + + if (!elem.props_match(elem_props)) + throw Exception ("Element properties (" + str(elem.prop_keys()) + ") do not match that of set " + str(elem_props) + "."); + + if (rsize && (elem.vsize() != rsize)) + throw Exception ("vize() of element (" + str(elem.vsize()) + ") does not match that of the other elements in set (" + str(rsize) + "). Call 'free_elem_degree()' on set if this is intentional."); + + resize(size() + 1, NAN, elem.degree(), elem.vsize()); + + T new_elem = operator[](size()-1); + + new_elem = elem; + + return new_elem; + + } + + + template T Set::push_back(const T& elem, bool with_props) { + + if (with_props) + return push_back(elem); + + else { + + if (!var_elem_degrees() && (elem.bsize() != (rsize - num_elem_props()))) + throw Exception ("bize() of element (" + str(elem.bsize()) + ") does not match that of the other elements in set (" + str(rsize - num_elem_props()) + "). Call 'free_elem_degree()' on set if this is intentional."); + + resize(size() + 1, NAN, elem.degree(), elem.bsize() + num_elem_props()); + + T set_elem = operator[](size()-1); + + //Only set base vector part of element (the part without properties). + set_elem.sub(0, elem.bsize()) = elem.bvector(); + + return set_elem; + } + + } + + + template Set& Set::clear() { + + Object::clear(); + + if (row_ends) { + free(row_ends); + row_ends = 0; + } + + if (elem_dgrees) { + free(elem_dgrees); + elem_dgrees = 0; + } + + if (ext_props) { + delete ext_props; + ext_props = 0; + } + if (ext_elem_prop_keys) { + delete ext_elem_prop_keys; + delete ext_elem_prop_defaults; + delete ext_elem_prop_values; + ext_elem_prop_keys = 0; + ext_elem_prop_defaults = 0; + ext_elem_prop_values = 0; + } + + return *this; + } + + + template Set& Set::clear(const std::vector& properties, + const std::vector& elem_properties) { + + + if (!Object::props_match(&properties)) { + + clear_props(); + for (size_t prop_i = 0; prop_i < properties.size(); ++prop_i) + add_prop(properties[prop_i]); + + } + + if (!elem_props_match(&elem_properties)) { + + clear_elem_props(); + for (size_t prop_i = 0; prop_i < elem_properties.size(); ++prop_i) + add_elem_prop(properties[prop_i]); + + } + + return *this; + + } + + + template std::vector Set::extend_elem_prop_keys() const { + + std::vector header; + + if (ext_elem_prop_keys) + header = *ext_elem_prop_keys; + else + header = std::vector(); + + std::sort(header.begin(),header.end()); + + return header; + + } + + + template std::vector Set::elem_prop_keys() const { + + std::vector header = *elem_props; + + std::sort(header.begin(),header.end(), cstr_sort); + + return header; + + } + + + template template void Set::copy_extend_elem_props(const Set& set) { + + if (set.size() != this->size()) + throw Exception ("Size of set (" + str(this->size()) + ") does not match size of source set (" + str(set.size()) + ") for properties copy."); + + clear_extend_elem_props(); + append_extend_elem_props(set); + + } + + + template template void Set::append_extend_elem_props(const Set& set) { + + if (set.size() != this->size()) + throw Exception ("Size of set (" + str(this->size()) + ") does not match size of source set (" + str(set.size()) + ") for properties append."); + + if (set.ext_elem_prop_keys) { + + assert(set.ext_elem_prop_defaults); + assert(set.ext_elem_prop_values); + + if (!ext_elem_prop_keys) { + + ext_elem_prop_keys = new std::vector(*set.ext_elem_prop_keys); + ext_elem_prop_defaults = new std::vector(*set.ext_elem_prop_defaults); + ext_elem_prop_values = new std::vector< std::vector >(*set.ext_elem_prop_values); + + } else { + + assert(ext_elem_prop_defaults); + assert(ext_elem_prop_values); + + for (size_t prop_i = 0; prop_i < set.ext_elem_prop_keys->size(); ++prop_i) { + + std::string& key = set.ext_elem_prop_keys->operator[](prop_i); + + if (!has_extend_elem_prop(key)) + add_extend_elem_prop(key, set.ext_elem_prop_defaults->operator[](prop_i)); + + for (size_t row_i = 0; row_i < size(); ++row_i) + set_extend_elem_prop(key, set.ext_elem_prop_values->operator[](prop_i)[row_i], row_i); + + } + + } + + } else if (ext_elem_prop_keys) { + + assert(!set.ext_elem_prop_defaults); + assert(!set.ext_elem_prop_values); + assert(ext_elem_prop_defaults); + assert(ext_elem_prop_values); + + free(ext_elem_prop_keys); + free(ext_elem_prop_defaults); + free(ext_elem_prop_values); + ext_elem_prop_keys = 0; + ext_elem_prop_defaults = 0; + ext_elem_prop_values = 0; + + } + + } + + + template std::vector& Set::insert_elem_prop_keys(std::vector& header) const { + + for (uint prop_i = 0; prop_i < num_elem_props(); ++prop_i) + header.push_back(elem_prop_key(prop_i)); + + return header; + + } + + + template Set& Set::select(Set& new_set, std::vector& indices) const { + + if (!new_set.is_owner()) + throw Exception ("Cannot select fibres into provided set as it is only a view onto a larger object."); + + new_set.reset(*props,*elem_props); + + new_set.add_extend_elem_props(*this); + + for (size_t i = 0; i < indices.size(); i++) { + + if (indices[i] >= this->size()) + throw Exception ("Supplied index, " + str(indices[i]) + ", is out of range."); + + std::map props_row = get_extend_elem_prop_row(indices[i]); + + T new_elem; + + new_elem = operator[](indices[i]); + + new_set.push_back(new_elem, props_row); + + } + + // Freeze element sizes if frozen in this set. + if (!var_elem_degrees()) + new_set.freeze_elem_degree(); + + return new_set; + + } + + + template void Set::load (const std::string& location) { + + if (File::has_extension(location, File::TXT_FILE_EXTENSTION)) { + + typename T::TextReader reader; + load_tpl(location, reader); + + } else { + + typename T::Reader reader; + load_tpl(location, reader); + + } + + + } + + + template void Set::clear_extend_elem_props() { + + if (ext_elem_prop_keys) { delete ext_elem_prop_keys; ext_elem_prop_keys = 0; } + if (ext_elem_prop_defaults) { delete ext_elem_prop_defaults; ext_elem_prop_defaults = 0; } + if (ext_elem_prop_values) { delete ext_elem_prop_values; ext_elem_prop_values = 0; } + + } + + + template template void Set::load_tpl (const std::string& location, V& reader) { + + if (!is_owner()) + throw Exception ("Cannot load a fibre set that does not own the underlying data (i.e. is a view onto part of a larger structure)."); + + reader.open (location); + + //Separate out the intrinsic and extended properties read from the file header + std::map loaded_extend_props = reader.get_extend_props(); + std::map loaded_props = extract_props(loaded_extend_props); + + // Extract just the keys for the set properties + std::vector loaded_prop_keys; + for (std::map::iterator prop_it = loaded_props.begin(); prop_it != loaded_props.end(); ++prop_it) + loaded_prop_keys.push_back(prop_it->first); + + //Separate out the intrinsic and extended properties read from the element properties file header + std::vector extended_elem_prop_header = reader.extend_prop_keys(); + std::vector loaded_elem_prop_keys = reader.prop_keys(); + + // If the number of elements and their sizes have been stored in the file header use them to initialise the set. + if (loaded_extend_props.count(NUM_ELEMS_EXT_PROP) && loaded_extend_props.count(ELEM_SIZE_EXT_PROP) + && loaded_extend_props.count(ELEM_VSIZE_EXT_PROP)) + reset(to(loaded_extend_props[NUM_ELEMS_EXT_PROP]), + to(loaded_extend_props[ELEM_SIZE_EXT_PROP]), + to(loaded_extend_props[ELEM_VSIZE_EXT_PROP]), + loaded_prop_keys, + loaded_elem_prop_keys); + + // Else reset the set to a variable row size set. + else + reset(loaded_prop_keys, + loaded_elem_prop_keys); + + + for (std::map::iterator prop_it = loaded_props.begin(); prop_it != loaded_props.end(); ++prop_it) + prop(prop_it->first) = prop_it->second; + + + //Add the extended properties to the set + for (std::vector::iterator prop_it = extended_elem_prop_header.begin(); prop_it != extended_elem_prop_header.end(); ++prop_it) + add_extend_elem_prop(*prop_it, ""); + + //Loop through the reader and append the loaded elements. + T elem; + std::map properties_row; + size_t count = 0; + + while (reader.next(elem, properties_row)) { + + if (elem.degree() == 0) { + std::cout << std::endl << "WARNING!! Omitting element " << count << " as it's size is 0." << std::endl; + continue; + } + + // If the next element does not fit the fixed element size loaded from the header, remove the remaining unfilled + // elements and free the element size for the set. + if (!var_elem_degrees() && (elem.degree() != elem_degree())) { + resize(count); + free_elem_degree(); + } + + + //If estimated size is smaller than actual size append a new element to the end + if (count >= size()) + push_back(elem, properties_row); + + //Otherwise just set the already initialised element. + else { + operator[](count) = elem; + set_extend_elem_prop_row(properties_row, count); + } + + ++count; + + } + + if (!size()) + std::cout << "WARNING!! No elements loaded from file '" << location << "'."; + + //If estimated size is larger than actual size, resize the set to match the actual size. + if (size() > count) + resize(count); + + // Attempt to freeze the row sizes for the loaded set, ignoring failure. + freeze_elem_degree(true); + + } + + + template void Set::save (const std::string& location) const { + + if (File::has_extension(location, File::TXT_FILE_EXTENSTION)) { + + typename T::TextWriter writer; + save_tpl(location, writer); + + } else { + + typename T::Writer writer; + save_tpl(location, writer); + + } + + + } + + + template template void Set::save_tpl (const std::string& location, V& writer) const { + + //Copy set properties and append intrinsic properties to them. + std::map properties; + + if (ext_props) + properties = *ext_props; + + //Insert the properties for the set into the header along with the extended properties + insert_props(properties); + + //Copy element properties and append intrinsic properties to them. + std::vector elem_prop_header; + + if (ext_elem_prop_keys) + elem_prop_header = *ext_elem_prop_keys; + + writer.create (location, *elem_props, elem_prop_header, properties); + + for (size_t elem_i = 0; elem_i < size(); elem_i++) + writer.append(operator[](elem_i), get_extend_elem_prop_row(elem_i)); + + + } + + + template Set& Set::permute(Set& permuted_set, const std::vector& indices) const { + + if (indices.size() != this->size()) + throw Exception ("Size of indices (" + str(indices.size()) + ") does not match size of set (" + str(this->size()) + ")."); + + if (permuted_set.size() != this->size()) + throw Exception ("Size of output set (" + str(permuted_set.size()) + ") does not match size of set (" + str(this->size()) + ")."); + +#ifndef NDEBUG + std::vector unique_indices (indices); + + std::unique(unique_indices.begin(), unique_indices.end()); + + if (unique_indices.size() != indices.size()) + throw Exception ("Indices provided to Fibre::Base::Set::permute() are not unique"); +#endif + + //To avoid a bug if *this is the same as permuted_set; + Set this_copy(*this); + + for (size_t indices_i = 0; indices_i < indices.size(); indices_i++) { + permuted_set[indices[indices_i]] = this_copy[indices_i]; + } + + return permuted_set; + + } + + + template double Set::distance(const Set& reference, std::vector& matched_indices, BTS::Math::Munkres&munkres_algorithm, MR::Math::Matrix& similarity, double strands_per_acs, bool add_extra) const { + + + if (reference.size() < this->size()) + throw Exception( "Size of reference Strand::Set (" + str (reference.size()) + ") must be greater than or equal to that of the Strand::Set of interest (" + str(this->size()) + ")."); + + matched_indices.resize(this->size()); + + this->similarity_matrix(reference, similarity, strands_per_acs); + + munkres_algorithm.match(similarity, matched_indices); + + double dist = 0.0; + + for (size_t fibre_i = 0; fibre_i < this->size(); fibre_i++) { + + dist += this->operator[](fibre_i).distance(reference[matched_indices[fibre_i]], strands_per_acs); + // dist += similarity_matrix(fibre_i, matched_indices[fibre_i]); + + } + + if (add_extra) + for (size_t ref_i = 0; ref_i < reference.size(); ++ref_i) + //FIXME: This should not include the displacement terms only the terms that contribute to its length. + if (std::find(matched_indices.begin(), matched_indices.end(), ref_i) == matched_indices.end()) + dist += MR::Math::sqrt(reference[ref_i].norm2()); + + + return dist; + + + } + + + template double Set::distance(const Set& reference, double strands_per_acs, bool add_extra) const { + + std::vector matched_indices(size()); + + return distance(reference, matched_indices, strands_per_acs, add_extra); + + } + + + template double Set::distance(const Set& reference, std::vector& matched_indices, double strands_per_acs, bool add_extra) const { + + BTS::Math::Munkres munkres_algorithm(this->size(), reference.size()); + MR::Math::Matrix similarity(this->size(),reference.size()); + + return distance(reference, matched_indices, munkres_algorithm, similarity, strands_per_acs, add_extra); + + } + + + template void Set::similarity_matrix(const Set& reference, + MR::Math::Matrix& similarity, + double strands_per_acs) const { + + if ((similarity.rows() != size()) || (similarity.columns() != reference.size())) + throw Exception ("Dimensions of similarity matrix, " + str(similarity.rows()) + " X " + str(similarity.columns()) + " do not match Strand::Sets, " + str(size()) + ", " + str(reference.size()) + "."); + + for (size_t this_i = 0; this_i < size(); this_i++) { + for (size_t reference_i = 0; reference_i < reference.size(); reference_i++) + similarity(this_i, reference_i) = operator[](this_i).distance(reference[reference_i], strands_per_acs); + } + + } + + + template Set& Set::smallest_distance_set(const Set& reference, Set& smallest) const { + + if (size() != reference.size()) + throw Exception ("Size of set (" + str(size()) + ") does not match that of reference set (" + str(reference.size()) + ")."); + + std::vector matched_indices(size()); + + distance(reference, matched_indices); + + smallest = *this; + + smallest.permute(smallest, matched_indices); + + for (size_t fibre_i = 0; fibre_i < smallest.size(); ++fibre_i) + smallest[fibre_i] = smallest[fibre_i].smallest_distance_set(reference[fibre_i]); + + return smallest; + + } + + + template void Set::reset_bundle_indices() { + + if (!has_extend_elem_prop(BUNDLE_INDEX_EPROP)) + add_extend_elem_prop(BUNDLE_INDEX_EPROP, "-1"); + + for (size_t elem_i = 0; elem_i < size(); ++elem_i) + set_extend_elem_prop(BUNDLE_INDEX_EPROP, str(elem_i), elem_i); + + } + + + template void Set::add_extend_elem_prop(const std::string& key, const std::string& default_value) { + + this->init_extend_elem_props(); + + //If key is not already present. + if (!has_extend_elem_prop(key)) { + + ext_elem_prop_keys->push_back(key); + ext_elem_prop_defaults->push_back(default_value); + + ext_elem_prop_values->push_back ( std::vector(size(), default_value) ); + + } else + ext_elem_prop_defaults->operator[](key_index(key)) = default_value; + + } + + + template template void Set::add_extend_elem_props(const Set& set) { + + //If set has extended properties + if (set.ext_elem_prop_keys) { + + for (size_t key_i = 0; key_i < set.ext_elem_prop_keys->size(); key_i++) + add_extend_elem_prop(set.ext_elem_prop_keys->operator[](key_i), set.ext_elem_prop_defaults->operator[](key_i)); + } + + } + + + template void Set::remove_extend_elem_prop(const std::string& key) { + + + if (has_extend_elem_prop(key)) { + + size_t index = key_index(key); + + ext_elem_prop_keys->erase(ext_elem_prop_keys->begin() + index); + ext_elem_prop_defaults->erase(ext_elem_prop_defaults->begin() + index); + ext_elem_prop_values->erase(ext_elem_prop_values->begin() + index); + + + } + + } + + + template void Set::set_extend_elem_prop(std::string key, std::string value, size_t elem_index) { + + if (elem_index >= size()) + throw Exception ("Element index (" + str(elem_index) + ") is out of range."); + + size_t key_i = key_index(key); + + ext_elem_prop_values->operator[](key_i)[elem_index] = value; + + + } + + + template std::string Set::get_extend_elem_prop(std::string key, size_t elem_index) const { + + + if (elem_index >= size()) + throw Exception ("Element index (" + str(elem_index) + ") is out of range."); + + size_t key_i = key_index(key); + + //Can't use operator[] for key_index since 'this' is const. NB: Key is guaranteed to exist in 'key_index' from the 'check_key()' function. + std::string value = ext_elem_prop_values->operator[](key_i)[elem_index]; + + return value; + + } + + + template bool Set::has_extend_elem_prop(const std::string& key) const { + + bool found = false; + + if (ext_elem_prop_keys) { + for (size_t key_i = 0; key_i < ext_elem_prop_keys->size(); ++key_i) + if (ext_elem_prop_keys->operator[](key_i) == key) { + found = true; + break; + } + } + + return found; + + } + + + template std::map Set::get_extend_elem_prop_row(size_t elem_index) const { + + if (elem_index >= size()) + throw Exception ("Element index (" + str(elem_index) + ") is out of range."); + + std::map row; + + if (ext_elem_prop_keys) + for (size_t key_i = 0; key_i < ext_elem_prop_values->size(); ++key_i) + row[ext_elem_prop_keys->operator[](key_i)] = ext_elem_prop_values->operator[](key_i)[elem_index]; + + return row; + + } + + + template void Set::set_extend_elem_prop_row(const std::map& properties, size_t row_index, bool ignore_missing) { + + if (ext_elem_prop_keys) { + + std::vector row(ext_elem_prop_keys->size()); + + for (size_t key_i = 0; key_i < ext_elem_prop_keys->size(); key_i++) { + + std::map::const_iterator key_it = properties.find(ext_elem_prop_keys->operator[](key_i)); + + std::string value; + + if (key_it == properties.end()) { + if (ignore_missing) + value = ext_elem_prop_defaults->operator[](key_i); + else + throw Exception ("Property '" + ext_elem_prop_keys->operator[](key_i) + "' not found in added properties row."); + + } else + value = key_it->second; + + //Can't use operator[] for properties since it is constant. + this->ext_elem_prop_values->operator[](key_i)[row_index] = value; + + } + + } + + } + + +// template template void Set::copy_extend_elem_props(const Set& set) { +// +// clear_extend_elem_props(); +// +// append_extend_elem_props(set); +// +// } +// +// +// template template void Set::append_extend_elem_props(const Set& set) { +// +// add_extend_elem_props(set); +// +// for (size_t elem_i = 0; elem_i < size(); ++elem_i) +// copy_extend_elem_prop_row(set,elem_i); +// +// } + + + + template void Set::resize(size_t new_size, const T& elem) { + + assert(elem.props_match(elem_props)); + + size_t old_size = size(); + + resize(new_size, NAN, elem.degree(), elem.vsize()); + + for (size_t elem_i = old_size; elem_i < new_size; ++elem_i) + operator[](elem_i) = elem; + + } + + + template void Set::reset(size_t num_elems, + size_t elem_degree, + size_t elem_vsize, + const std::vector& properties, + const std::vector& elem_properties, + double fill_value) { + + if (!owner) + throw Exception ("Cannot reset set as it is part of a larger object."); + + Object::reset(num_elems, elem_vsize, properties, fill_value); + + elem_dgree = elem_degree; + rsize = elem_vsize; + vrows = false; + + if (row_ends) { + free(row_ends); + row_ends = 0; + } + + if (elem_dgrees) { + free(elem_dgrees); + elem_dgrees = 0; + } + + *elem_props = elem_properties; + + if (ext_props) { + free(ext_props); + ext_props = 0; + } + + if (ext_elem_prop_keys) { + delete ext_elem_prop_keys; + delete ext_elem_prop_defaults; + delete ext_elem_prop_values; + ext_elem_prop_keys = 0; + ext_elem_prop_defaults = 0; + ext_elem_prop_values = 0; + } + + } + + + template void Set::reset(const std::vector& properties, + const std::vector& elem_properties, + double fill_value) { + + if (!owner) + throw Exception ("Cannot reset set as it is part of a larger object."); + + Object::reset(properties, fill_value); + + free_elem_degree(); + + *elem_props = elem_properties; + + if (ext_props) { + free(ext_props); + ext_props = 0; + } + + if (ext_elem_prop_keys) { + delete ext_elem_prop_keys; + delete ext_elem_prop_defaults; + delete ext_elem_prop_values; + ext_elem_prop_keys = 0; + ext_elem_prop_defaults = 0; + ext_elem_prop_values = 0; + } + + } + + + + + + template void Set::erase(size_t index) { + + if (!is_owner()) + throw Exception ("Cannot erase element from fibre object that does not own the underlying data (i.e. is a view onto part of a larger structure)."); + + if (index > sze) + throw Exception ("Index (" + str(index) + ") out of range (" + str(size()) + ")."); + + //Calculate the new base size without the row that is to be erased. + size_t new_bsize = bsize() - row_size(index); + + //Shift the base data into its new positions + for (size_t i = row_start(index); i < new_bsize; ++i) + MR::Math::Vector::operator[](i) = MR::Math::Vector::operator[](i + row_size(index)); + + //Shift the property values in to their new positions + for (size_t prop_i = 0; prop_i < num_props(); ++prop_i) + MR::Math::Vector::operator[](new_bsize + prop_i) = MR::Math::Vector::operator[](bsize() + prop_i); + + //Resize the underlying vector. + MR::Math::Vector::resize(new_bsize + num_props()); + + //deincrement the size. + --sze; + + //If variable row sizes remove the entry for the erased row. + if (var_elem_degrees()) { + + for (size_t i = index; i < size(); ++i) + row_ends[i] = row_start(i) + row_size(i+1); + + if (size()) { + row_ends = (size_t*)realloc(row_ends, sizeof(size_t) * size()); + + if (!row_ends) + throw Exception ("Failed to allocate size (" + str(sizeof(size_t) * size()) + ") for row_ends array."); + + for (size_t i = index; i < size(); ++i) + elem_dgrees[i] = elem_dgrees[i+1]; + + elem_dgrees = (size_t*)realloc(elem_dgrees, sizeof(size_t) * size()); + + if (!elem_dgrees) + throw Exception ("Failed to allocate array for elem_dgrees (" + str(sizeof(size_t) * size()) + " bytes requested)."); + + } else { + free(row_ends); + free(elem_dgrees); + row_ends = 0; + elem_dgrees = 0; + } + } + + //Extended properties are present also remove the corresponding row. + if (num_extend_elem_props()) { + + for (size_t key_i = 0; key_i < num_extend_elem_props(); ++key_i) { + std::vector& value_row = ext_elem_prop_values->operator[](key_i); + value_row.erase(value_row.begin() + index); + } + + } + + } + + + template T Set::insert(const T& element, size_t index) { + + if (!is_owner()) + throw Exception ("Cannot erase element from fibre object that does not own the underlying data (i.e. is a view onto part of a larger structure)."); + + if (index > sze) + throw Exception ("Index (" + str(index) + ") out of range (" + str(size()) + ")."); + + if (!element.props_match(elem_props)) + throw Exception ("Element properties do not match that of set."); + + if (elem_dgree && elem_dgree != element.degree()) + throw Exception ("Element size does not match remainder of set (NB: Use Set::free_elem_degree() function first if this is intentional)."); + + size_t old_bsize = bsize(); + + //Calculate the new base size without the row that is to be erased. + size_t new_bsize = bsize() + element.vsize(); + + //Resize the underlying vector. + MR::Math::Vector::resize(new_bsize + num_props()); + + //Shift the property values out to their new positions + for (int prop_i = num_props()-1; prop_i >= 0; --prop_i) + MR::Math::Vector::operator[](new_bsize + prop_i) = MR::Math::Vector::operator[](old_bsize + prop_i); + + //Shift the base data into its new positions + for (int i = old_bsize-1; i >= (int)row_start(index); --i) + MR::Math::Vector::operator[](i + element.vsize()) = MR::Math::Vector::operator[](i); + + //Increment the size. + ++sze; + + //If variable row sizes remove the entry for the erased row. + if (var_elem_degrees()) { + + if (size()) { + if (row_ends) + row_ends = (size_t*)realloc(row_ends, sizeof(size_t) * size()); + else + row_ends = (size_t*)malloc(sizeof(size_t) * size()); + + if (!row_ends) + throw Exception ("Failed to allocate size (" + str(sizeof(size_t) * size()) + ") for row_ends array."); + + for (int i = (int)size()-1; i >= (int)index; --i) + row_ends[i] = element.vsize() + (i ? row_ends[i-1] : 0); + + + if (elem_dgrees) + elem_dgrees = (size_t*)realloc(elem_dgrees, sizeof(size_t) * size()); + else + elem_dgrees = (size_t*)malloc(sizeof(size_t) * size()); + + if (!elem_dgrees) + throw Exception ("Failed to allocate array for elem_dgrees (" + str(sizeof(size_t) * size()) + " bytes requested)."); + + for (int i = (int)size()-1; i > (int)index; --i) + elem_dgrees[i] = elem_dgrees[i-1]; + + } else { + + if (row_ends) { + free(row_ends); + row_ends = 0; + } + + if (elem_dgrees) { + free(elem_dgrees); + elem_dgrees = 0; + } + + } + elem_dgrees[index] = element.degree(); + + } + + //If extended properties are present, populate the corresponding row, with the default. + if (num_extend_elem_props()) { + + for (size_t key_i = 0; key_i < num_extend_elem_props(); ++key_i) { + std::vector& value_row = ext_elem_prop_values->operator[](key_i); + value_row.insert(value_row.begin() + index, ext_elem_prop_defaults->operator[](key_i)); + } + + } + + //Finally assign the element to the space created for it. + operator[](index) = element; + + return operator[](index); + + } + + + template size_t Set::key_index (const std::string& key) const { + + if (!ext_elem_prop_keys) + throw Exception ("Property '" + key + "' was not found (set has no extended properties)."); + + size_t key_i; + + for (key_i = 0; key_i < ext_elem_prop_keys->size(); ++key_i) + if (ext_elem_prop_keys->operator[](key_i) == key) + return key_i; + + throw Exception ("Property '" + key + "' was not found."); + + } + + + template void Set::init_extend_elem_props() { + + if (!ext_elem_prop_keys) { + + assert(!ext_elem_prop_defaults); + assert(!ext_elem_prop_values); + + ext_elem_prop_keys = new std::vector(); + ext_elem_prop_defaults = new std::vector(); + ext_elem_prop_values = new std::vector >(); + + } + + } + + + template std::ostream& operator<< (std::ostream& stream, const Set& set) { + + for (size_t prop_i = 0; prop_i < set.num_props(); ++prop_i) + stream << set.prop_key(prop_i) << ": " << set.prop(prop_i) << std::endl; + + for (size_t elem_i = 0; elem_i < set.size(); elem_i++) { + + stream << std::endl; + stream << "--------------------" << std::endl; + stream << " " << elem_i << std::endl; + stream << "--------------------" << std::endl; + + + + std::vector header = set.extend_elem_prop_keys(); + + if (set.num_extend_elem_props()) + stream << "{"; + + for (size_t prop_i = 0; prop_i < header.size(); prop_i++) { + stream << header[prop_i] << ": " << set.get_extend_elem_prop(header[prop_i], elem_i); + + if (prop_i != header.size()-1) + stream << ", "; + } + + if (set.num_extend_elem_props()) + stream << "}" << std::endl; + + stream << set[elem_i]; + + stream << std::endl; + + } + + return (stream); + } + + + template void Set::add_elem_prop(const char* const name, double value, bool ignore_present) { + + + if (!is_owner()) + throw Exception ("Cannot add element property to a fibre object that does not own the underlying data (i.e. is a view onto part of a larger structure)."); + + //Loop through properties and insert the new property in the appropriate position for alphabetical order + size_t insert_index = 0; + + for (std::vector::iterator prop_it = elem_props->begin(); prop_it != elem_props->end(); ++prop_it) { + + int compare = strcmp(name, *prop_it); + + //If property is already present. + if (!compare) { + + //If not 'ignore_present' throw and exception + if (!ignore_present) + throw Exception ("Element property with the same name ('" + str(name) + "') already exists in fibre object"); + + //Otherwise if value was supplied set the property to that value, and then return. + if (!isnan(value)) + for (size_t elem_i = 0; elem_i < size(); ++elem_i) + operator[](elem_i).prop(insert_index) = value; + return; + } + + // If new property name comes before current property in alphabetical order, insert it and break loop + if (compare < 0) { + elem_props->insert(prop_it,name); + break; + } + + ++insert_index; + + } + + //If the property wasn't inserted within the existing properties append it to the end of the list + if (insert_index == elem_props->size()) + elem_props->push_back(name); //Add pointer to property name to properties list + + //Increment state vector to hold new property + MR::Math::Vector::resize(vsize() + size()); + + //Move the set properties to their new location + for (int prop_i = num_props()-1; prop_i >=0; --prop_i) + MR::Math::Vector::operator[](bsize() + prop_i) = MR::Math::Vector::operator[](bsize() + prop_i - size()); + + //Adjust the row size to account for the added property + ++rsize; + + //The offset that accounts for the accumulated increase in row size over the whole set due to the added property + //per row. + size_t accum_offset = size(); + + for (int elem_i = size()-1; elem_i >=0; --elem_i) + for (int elem_elem_i = rsize-1; elem_elem_i >= 0; --elem_elem_i) + + if ((size_t)elem_elem_i == insert_index + rsize - elem_props->size()) { + MR::Math::Vector::operator[](elem_i * rsize + elem_elem_i) = value; + --accum_offset; + } else + MR::Math::Vector::operator[](elem_i * rsize + elem_elem_i) = MR::Math::Vector::operator[](elem_i * rsize + elem_elem_i - accum_offset); + + } + + + template void Set::remove_elem_prop(const char* const name, bool ignore_missing) { + + if (!is_owner()) + throw Exception ("Cannot remove element property from a fibre object that does not own the underlying data (i.e. is a view onto part of a larger structure)."); + + //Find iterator to property that matches given property name. + std::vector::iterator prop_it = elem_props->begin(); + + for (; prop_it != elem_props->end(); ++prop_it) + if (name == *prop_it) + break; + + if (prop_it != elem_props->end()) { + + size_t remove_index = prop_it - elem_props->begin(); + + // Remove property from list + elem_props->erase(prop_it); + + //Adjust the row size(s) to account for the removed property + if (var_elem_degrees()) { + for (size_t row_i = 0; row_i < size(); ++row_i) + row_ends[row_i] -= row_i+1; + } else + --rsize; + + + //The offset that accounts for the accumulated increase in row size over the whole set due to the added property + //per row. + size_t accum_offset = 0; + + for (size_t elem_i = 0; elem_i < size(); ++elem_i) { + for (size_t elem_elem_i = 0; elem_elem_i < row_size(elem_i); ++elem_elem_i) { + + //When the elem_elem_i index passes the index of the removed property, increment the accumulated offset + if (elem_elem_i == remove_index + row_size(elem_i) - num_elem_props()) + ++accum_offset; + + MR::Math::Vector::operator[](row_start(elem_i) + elem_elem_i) = MR::Math::Vector::operator[](row_start(elem_i) + elem_elem_i + accum_offset); + + } + + //If the property is the last in the list the accumulated offset is not incremented in the above loop and needs + // to be done here. + if (remove_index == num_elem_props()) + ++accum_offset; + + } + + //Move the set properties to their new location + for (size_t prop_i = 0; prop_i < num_props(); ++prop_i) + MR::Math::Vector::operator[](bsize() + prop_i - size()) = MR::Math::Vector::operator[](bsize() + prop_i); + + + // Resize state vector + MR::Math::Vector::resize(vsize() - size()); + + } else if (!ignore_missing) + throw Exception ("Fibre object does not have element property '" + str(name) + "' (use 'ignore_missing' parameter to ignore)."); + + + } + + + template void Set::clear_elem_props() { + + if (!is_owner()) + throw Exception ("Cannot clear properties from a fibre object that does not own the underlying data (i.e. is a view onto part of a larger structure)."); + + //Adjust the row size to account for the removed property + rsize -= elem_props->size(); + + //The offset that accounts for the accumulated increase in row size over the whole set due to the added property + //per row. + size_t accum_offset = 0; + + for (size_t elem_i = 0; elem_i < size(); ++elem_i) { + for (size_t elem_elem_i = 0; elem_elem_i < rsize; ++elem_elem_i) + MR::Math::Vector::operator[](elem_i * rsize + elem_elem_i) = MR::Math::Vector::operator[](elem_i * rsize + elem_elem_i + accum_offset); + + accum_offset += elem_props->size(); + } + + + //Move the set properties to their new location + for (size_t prop_i = 0; prop_i < num_props(); ++prop_i) + MR::Math::Vector::operator[](bsize() + prop_i - elem_props->size() * size()) = MR::Math::Vector::operator[](bsize() + prop_i); + + // Resize state vector to remove appended properties + MR::Math::Vector::resize(vsize() - elem_props->size() * size()); + + // Clear properties list. + elem_props->clear(); + + } + + + template template void Set::copy_elem_props(const Set& set) { + + if (size() != set.size()) + throw Exception ("Set sizes must be the same (" + str(size()) + " and " + str(set.size()) + ") to copy element properties"); + + for (size_t prop_i = 0; prop_i < set.num_elem_props(); ++prop_i) { + + const char* key = set.elem_prop_key(prop_i); + + if (!has_elem_prop(key)) + add_elem_prop(key); + + for (size_t elem_i = 0; elem_i < size(); ++elem_i) + operator[](elem_i).prop(key) = set[elem_i].prop(prop_i); + + } + + } + + + template size_t Set::elem_prop_index(const char* const name) const { + + // Find index of property + size_t prop_index = 0; + + for (; prop_index < num_elem_props(); ++prop_index) + if (elem_props->operator[](prop_index) == name) + break; + + //Check to see if property was found. + if (prop_index == num_elem_props()) + throw Exception ("Fibre set does not have element property '" + str(name) + "', it needs to be added by the 'add_elem_prop' command beforehand. " + " Note that the comparison is performed by comparing pointer addresses, so the same (const char*) needs to be used throughout."); + + return prop_index; + + } + + + template void Set::elem_resize(size_t new_elem_degree, size_t new_elem_vsize, double fill_value) { + + if (!is_owner()) + throw Exception ("Cannot resize fibre set that does not own the underlying data (i.e. is a view onto part of a larger structure)."); + + if (!new_elem_degree) + throw Exception ("Cannot change fixed element size to 0. However, if row size is 'freed' using 'free_elem_degrees' their size can be 0."); + + //Buffer the current set + Set orig(*this); + + //Get Vector version of buffer to access its MR::Math::Vector::operator[](). + MR::Math::Vector& orig_vector = orig; + + //Fix the row size by removing the variable row_ends + + if (row_ends) { + + if (row_ends) { + free(row_ends); + row_ends = 0; + } + + if (elem_dgrees) { + free(elem_dgrees); + elem_dgrees = 0; + } + + } + + //Set the new elem and row size including element properties + elem_dgree = new_elem_degree; + rsize = new_elem_vsize; + + //Resize the underlying vector class + MR::Math::Vector::resize(rsize * size() + num_props()); + + //Loop through each element and set the new row + for (size_t elem_i = 0; elem_i < size(); ++elem_i) { + + //Copy across the data from the buffer that is to be included in the resized set + for (size_t elem_elem_i = 0; elem_elem_i < std::min(rsize, orig.row_size(elem_i)) - num_elem_props(); ++elem_elem_i) + MR::Math::Vector::operator[](row_start(elem_i) + elem_elem_i) = orig_vector[orig.row_start(elem_i) + elem_elem_i]; + + //Fill in the extra data in the resized set if required + for (size_t elem_elem_i = orig.row_size(elem_i) - num_elem_props(); elem_elem_i < (rsize - num_elem_props()); ++elem_elem_i) + MR::Math::Vector::operator[](row_start(elem_i) + elem_elem_i) = fill_value; + + //Copy across the element properties + for (size_t prop_i = 0; prop_i < num_elem_props(); ++prop_i) + MR::Math::Vector::operator[](row_end(elem_i) - num_elem_props() + prop_i) = orig_vector[orig.row_end(elem_i) - num_elem_props() + prop_i]; + + } + + for (size_t prop_i = 0; prop_i < num_props(); ++prop_i) + MR::Math::Vector::operator[](bsize() + prop_i) = orig_vector[orig.bsize() + prop_i]; + + + + } + + + template std::vector Set::parse_extend_elem_props_line(const std::string& line) { + + std::istringstream line_stream(line); + + std::string value; + std::vector values_row; + + while(std::getline(line_stream, value, '\t')) + values_row.push_back(value); + + return values_row; + + } + + + template std::vector Set::read_extend_elem_prop_header(std::ifstream& file_in) { + + check_good(file_in); + + char file_intro[PROPS_FILE_PREAMBLE.size()+2]; + + file_in.get(file_intro, PROPS_FILE_PREAMBLE.size()+1); + + if (strcmp(file_intro, PROPS_FILE_PREAMBLE.c_str())) + throw Exception ("Required file intro '" + PROPS_FILE_PREAMBLE + "' was not found at start of extended properties file (found '" + std::string(file_intro) +"' instead)."); + + std::vector header; + + std::string key_line; + + if (!std::getline(file_in, key_line)) + throw Exception ("No ext_elem_prop_keys found in extended properties file."); + + std::istringstream line_stream(key_line); + + std::string key; + + header.clear(); + + while(std::getline(line_stream, key, '\t')) + header.push_back(key); + + return header; + + } + + + template void Set::load_extend_elem_props(std::string location) { + + clear(); + + std::ifstream in; + in.open(location.c_str()); + + *ext_elem_prop_keys = read_extend_elem_prop_header(in); + + std::string line; + + try { + while (std::getline(in, line)) { + std::vector values = parse_extend_elem_props_line(line); + + for (size_t key_i = 0; key_i < num_extend_elem_props(); key_i++) + ext_elem_prop_values->operator[](key_i).push_back(values[key_i]); + + } + + } catch (Exception& e) { + throw Exception ("Error reading extended properties from " + location + ": " + e[0] + "."); + } + + + + + } + + + template void Set::save_extend_elem_props(std::string location) { + + std::ofstream out; + + out.open(location.c_str()); + + out << PROPS_FILE_PREAMBLE; + + for (std::vector::const_iterator key_it = ext_elem_prop_keys->begin(); key_it != ext_elem_prop_keys->end(); key_it++) + out << *key_it << '\t'; + + out << std::endl; + + for (size_t row_i = 0; row_i < size(); row_i++) { + + for (size_t key_i = 0; key_i < ext_elem_prop_keys->size(); key_i++) + + out << ext_elem_prop_values->operator[](key_i)[row_i] << '\t'; + + out << std::endl; + + } + + } + + + template void Set::add_extend_elem_prop_row(const std::vector& values_row) { + + if (num_extend_elem_props() != values_row.size()) + throw Exception ("Number of supplied values " + str(values_row.size()) + " does not match extended element properties (" + str(num_extend_elem_props()) + ")."); + + for (size_t key_i = 0; key_i < num_extend_elem_props(); key_i++) + ext_elem_prop_values->operator[](key_i).push_back(values_row[key_i]); + + } + + + template void Set::add_extend_elem_prop_row(const std::map& properties) { + + std::vector row(num_extend_elem_props()); + + for (size_t key_i = 0; key_i < num_extend_elem_props(); key_i++) { + + std::map::const_iterator key_it = properties.find(ext_elem_prop_keys->operator[](key_i)); + + if (key_it == properties.end()) + throw Exception ("Property '" + ext_elem_prop_keys->operator[](key_i)+ "' not found in added properties row."); + + //Can't use operator[] for properties since properties are const. + row[key_i] = key_it->second; + + } + + for (size_t key_i = 0; key_i < num_extend_elem_props(); key_i++) + ext_elem_prop_values->operator[](key_i).push_back(row[key_i]); + + } + + + template size_t Set::freeze_elem_degree(bool ignore_fail) { + + //Check to see if it is already fixed + if (var_elem_degrees()) { + + bool success = true; + size_t fix_elem_dgree = 0; + size_t fix_rsize = 0; + + if (size()) { + fix_rsize = row_size(0); + fix_elem_dgree = elem_degree(0); + + for (size_t row_i = 0; row_i < size(); ++row_i) + if (fix_rsize != row_size(row_i) || fix_elem_dgree != elem_degree(row_i)) { + success = false; + break; + } + + if (success) { + free(row_ends); + free(elem_dgrees); + row_ends = 0; + elem_dgrees = 0; + } + + } + + if (success) { + elem_dgree = fix_elem_dgree; + rsize = fix_rsize; + vrows = false; + } else if (!ignore_fail) + throw Exception ("Attempt to fix elem sizes failed as multiple values exist in the fibre object."); + + } + + return elem_dgree; + + } + + + /*! Frees the restriction on row sizes being equal to a single member variable. This excludes the use of some + * functions, such as 'bmatrix()' that require a fixed row size and will also take up an extra sizeof(void*) + * of memory for each element + * + */ + template void Set::free_elem_degree() { + + //Check to see if it is already free if not allocate the vector to hold the individual element sizes + if (!var_elem_degrees()) { + + if (size()) { + + size_t alloc_size = sizeof(size_t) * size(); + if (alloc_size) + row_ends = (size_t*)malloc(alloc_size); + + if (!row_ends) + throw Exception ("Could not allocate memory for variable row sizes (" + str(alloc_size) + " bytes requested)."); + + //Allocate an array to hold the variable element sizes + elem_dgrees = (size_t*)malloc(sizeof(size_t) * size()); + + if (!elem_dgrees) + throw Exception ("Could not allocate memory for variable elem sizes (" + str(sizeof(size_t) * size()) + " bytes requested)."); + + //Set the variable element sizes to the current elemnt size before setting it to zero. + size_t row_start = 0; + for (size_t row_i = 0; row_i < size(); ++row_i) { + row_ends[row_i] = row_start + rsize; + row_start = row_ends[row_i]; + elem_dgrees[row_i] = elem_dgree; + } + + } else { + elem_dgrees = 0; + row_ends = 0; + } + + rsize = 0; + elem_dgree = 0; + vrows = true; + + } + + } + + + + template template void Set::copy_relevant_elem_props(const Base::Set& source) { + + if (size() != source.size()) + throw Exception ("Source and destination set sizes must be equal to copy element props (" + str(source.size()) + " and " + str(size()) + " respectively)."); + + if (source.num_elem_props()) { + + // Declare the variables used within the loop + size_t prop_i = 0; + const char* prp_key; + + while ((prp_key = T::PROPS_LIST[prop_i]) != PROPS_LIST_END) { + + std::vector::const_iterator prop_it = std::find(source.props->begin(), source.props->end(), prp_key); + + if (prop_it != source.props->end()) { + if (!has_prop(prp_key)) + add_elem_prop(prp_key); + + for (size_t elem_i = 0; elem_i < size(); ++elem_i) + operator[](elem_i).prop(prp_key) = source[elem_i].prop(prp_key); + + } + + ++prop_i; + } + + } + + } + + } + + } + +} + + +#endif /* ___bts_fibre_set_icpp_h__ */ diff --git a/src/bts/fibre/base/set.h b/src/bts/fibre/base/set.h new file mode 100644 index 0000000..8717854 --- /dev/null +++ b/src/bts/fibre/base/set.h @@ -0,0 +1,731 @@ +/* + Copyright 2010 Brain Research Institute/National ICT Australia (NICTA), Melbourne, Australia + + Written by Thomas G Close, 5/05/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + +*/ + + +#ifndef __bts_fibre_base_set_h__ +#define __bts_fibre_base_set_h__ + +#include + +#include "math/vector.h" + +#include "bts/math/munkres.h" + +#include "bts/fibre/base/object.h" +#include "bts/coord.h" + +#define BASE_SET_FUNCTIONS(Derived) \ + Derived& resize(size_t size, double fill_value = NAN) \ + { assert(!var_elem_degrees()); Base::Set::resize(size, fill_value, 0, 0); return *this; } \ +\ + Derived& resize(size_t size, const typename Derived::Element& elem) \ + { Base::Set::resize(size,elem); return *this; } \ + + +namespace BTS { + + namespace Fibre { + + namespace Base { + + template class Set : public Object { + + + template friend class Set; + + //Nested classes and typedefs + public: + + typedef T Element; + + template class Tensor; + + + //Public const static members. + public: + + const static Coord FILE_SEPARATOR; + const static char* BASE_INTENSITY_PROP; + + const static std::string PROPS_FILE_PREAMBLE; + + const static std::string BUNDLE_INDEX_EPROP; + + const static std::string NUM_ELEMS_EXT_PROP; + const static std::string ELEM_SIZE_EXT_PROP; + const static std::string ELEM_VSIZE_EXT_PROP; + + protected: + + size_t initial_vsize(size_t size, + size_t* elem_degrees, + size_t elem_row_size, + size_t num_elem_props, + size_t num_props); + + //Protected member variables; + protected: + + bool vrows; /**< A flag that determines whether the row sizes and elem + sizes vary or whether they are determined by the 'rsize' and elem_dgree variablse alone */ + size_t rsize; /**< The vsize of each element if element sizes are fixed. @see Object::vsize()*/ + size_t elem_dgree; /**< The vsize of each element if element sizes are fixed*/ + size_t* row_ends; /**< The end index of each element if element sizes vary. */ + size_t* elem_dgrees; /**< The size of each element if element sizes vary. */ + + + std::vector* elem_props; + + std::map* ext_props; + + std::vector* ext_elem_prop_keys; + std::vector* ext_elem_prop_defaults; + std::vector< std::vector >* ext_elem_prop_values; + + + //Public member functions + public: + + + /*! Initialises an empty fibre base set with a given base_size and variable row sizes + * + * @param row_size The size of the fibre object's elements + * @param size Size of the base fibre object + * @param default_value The default value with which to fill the fibre object + * @param properties A list of properties to be appended to the state vector. + */ + Set ( const std::vector& props, + const std::vector& elem_props, + const std::map& extended_props) + : Object(0, props.size(), props), + vrows(true), + rsize(0), + elem_dgree(0), + row_ends(0), + elem_dgrees(0), + elem_props(new std::vector(elem_props)), + ext_props(0), + ext_elem_prop_keys(0), + ext_elem_prop_defaults(0), + ext_elem_prop_values(0) { + + + if (extended_props.size()) + ext_props = new std::map(extended_props); + + } + + + /*! Initialises a fibre base set with a given base_size and fixed row sizes. + * + * @param row_size The size of the fibre object's elements + * @param size Size of the base fibre object + * @param default_value The default value with which to fill the fibre object + * @param properties A list of properties to be appended to the state vector. + */ + Set ( size_t size, + size_t elem_degree, + size_t elem_vsize, + const std::vector& props, + const std::vector& elem_props, + const std::map& extended_props = std::map()) + : Object(size, size * elem_vsize + props.size(), props), + vrows(false), + rsize(elem_vsize), + elem_dgree(elem_degree), + row_ends(0), + elem_dgrees(0), + elem_props(new std::vector(elem_props)), + ext_props(0), ext_elem_prop_keys(0), ext_elem_prop_defaults(0), ext_elem_prop_values(0) { + + assert((elem_vsize - elem_props.size()) % 3 == 0); + + if (extended_props.size()) + ext_props = new std::map(extended_props); + + } + + + /*! Initialises a fibre base set from a view onto a larger set or tensor with fixed row sizes + * + * @param size Size of the new set + * @param elem_degree Fixed size of the elements of the set + * @param elem_row_size Row size of the elements of the set + * @param view View on to the fibre objects that will form the set + * @param props Pointer to the set properties + * @param elem_props Pointer to the element properties + */ + explicit Set (size_t size, + size_t elem_degree, + size_t elem_vsize, + const MR::Math::Vector::View& view, + std::vector* props, + std::vector* elem_props) + : Object(size, view, props), + vrows(false), + rsize(elem_vsize), + elem_dgree(elem_degree), + row_ends(0), + elem_dgrees(0), + elem_props(elem_props), + ext_props(0), ext_elem_prop_keys(0), ext_elem_prop_defaults(0), ext_elem_prop_values(0) { + + assert(size * elem_vsize + props->size() == view.size()); + assert((elem_vsize - elem_props->size()) % 3 == 0); + + } + + + /*! Initialises a fibre base set from a view onto a larger set or tensor with variable row sizes + * + * @param size Size of the new set + * @param elem_degrees Variable row sizes of the elements of the set + * @param elem_row_size Row size of the elements of the set + * @param view View on to the fibre objects that will form the set + * @param props Pointer to the set properties + * @param elem_props Pointer to the element properties + */ + explicit Set (size_t size, + size_t* element_sizes, + size_t* element_ends, + const MR::Math::Vector::View& view, + std::vector* props, + std::vector* elem_props) + : Object(size, view, props), + vrows(true), + rsize(0), + elem_dgree(0), + row_ends (size ? (size_t*)malloc(sizeof(size_t) * size) : 0), + elem_dgrees(size ? (size_t*)malloc(sizeof(size_t) * size) : 0), + elem_props(elem_props), + ext_props(0), ext_elem_prop_keys(0), ext_elem_prop_defaults(0), ext_elem_prop_values(0) { + + assert(element_ends[size-1] == view.size()); + + if (size) { + + if (!row_ends) + throw Exception("Failed to allocate array for row_ends (" + str(sizeof(size_t) * size) + " bytes requested)."); + + if (!elem_dgrees) + throw Exception ("Failed to allocate array for elem_dgrees (" + str(sizeof(size_t) * size) + " bytes requested)."); + + memcpy (row_ends, element_ends, sizeof(size_t) * size); + memcpy (elem_dgrees, element_sizes, sizeof(size_t) * size); + + } + + } + + + Set (const Set& set); + + + ~Set () { + + if (this->GSLVector::owner) { + delete elem_props; + + if (ext_props) delete ext_props; + if (ext_elem_prop_keys) delete ext_elem_prop_keys; + if (ext_elem_prop_defaults) delete ext_elem_prop_defaults; + if (ext_elem_prop_values) delete ext_elem_prop_values; + + } + + if (row_ends) + free(row_ends); + + if (elem_dgrees) + free(elem_dgrees); + + } + + + Set& operator= (const Set& set); + + + void reset(size_t num_elems, + size_t elem_degree, + size_t elem_row_size, + const std::vector& props, + const std::vector& elem_props, + double default_value = NAN); + + + void reset(const std::vector& props, + const std::vector& elem_props, + double fill_value = NAN); + + + T operator[] (size_t idx) + { return T(elem_degree(idx), sub(row_start(idx), row_end(idx)), elem_props); } + + + const T operator[] (size_t idx) const + { return T(elem_degree(idx), sub(row_start(idx),row_end(idx)), elem_props); } + + + T elem(size_t idx) + { return operator[](idx); } + + + const T elem(size_t idx) const + { return operator[](idx); } + + + double base_intensity() const + { return has_prop(BASE_INTENSITY_PROP) ? prop(BASE_INTENSITY_PROP) : 1.0; } + + + + /*! Checks to see if the (intrinsic) element properties match between two fibre set objects, i.e. whether they have the same + * property keys. Is used before some mathematical operations + * + * @param props the props to match to + * @return true if fibre object matches the properties exactly. + */ + bool elem_props_match(const std::vector* props) const; + + + /*! Checks to see if the (intrinsic) element properties match between two fibre set objects, i.e. whether they have the same + * property keys. Is used before some mathematical operations + * + * @param props the props to match to + * @return true if fibre object matches the properties exactly. + */ + bool props_match(const std::vector* properties, + const std::vector* elem_properties) const + { return Object::props_match(properties) && elem_props_match(elem_properties); } + + + bool props_match(const Set& set) const + { return props_match(set.props, set.elem_props); } + + + void add_base_intensity(double base_intens = 1.0) + { add_prop(BASE_INTENSITY_PROP, base_intens); } + + + void set_base_intensity(double base_intens) + { prop(BASE_INTENSITY_PROP) = base_intens; } + + + void remove_base_intensity() + { remove_prop(BASE_INTENSITY_PROP); } + + + bool has_var_base_intensity() const + { return has_prop(BASE_INTENSITY_PROP); } + + + double& var_base_intensity() + { assert(has_var_base_intensity()); return prop(BASE_INTENSITY_PROP); } + + + //! Returns either the fixed elem size if present or the variable element size if that is present. + size_t elem_degree(size_t idx) const + { return elem_dgree ? elem_dgree : (elem_dgrees ? elem_dgrees[idx] : 0); } + + + size_t elem_degree() const + { assert(!var_elem_degrees()); return elem_dgree; } + + + void elem_resize(size_t new_elem_degree, size_t new_elem_vsize, double default_value); + + + T push_back(const T& elem); + + + T push_back(const T& elem, const std::map& elem_properties_row) + { T new_elem = push_back(elem); set_extend_elem_prop_row(elem_properties_row, size()-1, true); return new_elem; } + + + /*! Erase the element at the given index + * + * @param index The index of the element to erase + */ + void erase(size_t index); + + /*! Inserts an object at the given index + * + * @param index + */ + T insert(const T& element, size_t index); + + + void append(const Set& set) + { for (size_t elem_i = 0; elem_i < set.size(); ++elem_i)push_back(set[elem_i], set.get_extend_elem_prop_row(elem_i)); } + + + Set& clear(); + + Set& clear(const std::vector& properties, const std::vector& elem_properties); + + double distance(const Set& reference, double strands_per_acs = 0.0, bool add_extra = false) const; + + /*! Returns the indices of current set in 'matched_indices' that form the closest match with the reference set. + * + */ + double distance(const Set& reference, + std::vector& matched_indices, double strands_per_acs = 0.0, bool add_extra = false) const; + + //TODO: create another overload that allows a custom similarity matrix to be passed but doesn't need to pass the munkres algorithm. + double distance(const Set& reference, + std::vector& indices, + BTS::Math::Munkres&munkres_algorithm, + MR::Math::Matrix& similarity, + double strands_per_acs = 0.0, + bool add_extra = false) const; + + + Set& smallest_distance_set(const Set& reference, Set& smallest) const; + + + MR::Math::Matrix similarity_matrix(const Set& reference, double strands_per_acs = 0.0) const + { MR::Math::Matrix matrix(this->size(), reference.size()); similarity_matrix(reference, matrix, strands_per_acs); return matrix; } + + + void similarity_matrix(const Set& reference, MR::Math::Matrix& similarity, double strands_per_acs = 0.0) const; + + // Methods to get and manipulate element properties. + + + bool has_extend_prop(const std::string& key) + { return ext_props && ext_props->count(key); } + + std::string get_extend_prop(const std::string& key) + { return (ext_props && ext_props->count(key)) ? (*ext_props)[key] : throw Exception ("'" + key + "' key was not found in extended properties."); } + + std::map get_extend_props() const + { return ext_props ? *ext_props : std::map(); } + + + std::vector extend_prop_keys() const; + + + void set_extend_props(const std::map& extended_props); + + + void set_extend_prop(const std::string& prop, const std::string& value); + + + size_t num_extend_elem_props() const + { return ext_elem_prop_keys ? ext_elem_prop_keys->size() : 0; } + + + std::vector extend_elem_prop_keys() const; + + + /*! Return a copy of the element property pointers */ + std::vector elem_prop_keys() const; + + + void add_extend_elem_prop(const std::string& key, const std::string& default_value); + + + template void add_extend_elem_props(const Set& set); + + + void clear_extend_elem_props(); + + + void remove_extend_elem_prop(const std::string& key); + + + template void copy_relevant_elem_props(const Base::Set& set); + + + void set_extend_elem_prop(std::string key, std::string value, size_t elem_index); + + + std::string get_extend_elem_prop(std::string key, size_t elem_index) const; + + + template U get_extend_elem_prop(std::string key, size_t elem_index) const + { return this->get_extend_elem_prop(key, elem_index); } + + + bool has_extend_elem_prop(const std::string& key) const; + + + std::map get_extend_elem_prop_row(size_t index) const; + + + void set_extend_elem_prop_row(const std::map& properties, size_t row_index, bool ignore_missing = false); + + + template inline void copy_extend_elem_prop_row(const Set& set, size_t elem_index, size_t this_index) + { this->set_extend_elem_prop_row(set.get_extend_elem_prop_row(elem_index), this_index, true); } + + + template inline void copy_extend_elem_prop_row(const Set& set, size_t elem_index) + { this->copy_extend_elem_prop_row(set, elem_index, elem_index); } + + + template inline void copy_extend_elem_props(const Set& set); + + + template inline void append_extend_elem_props(const Set& set); + + + Set& permute(Set& permuted, const std::vector& indices) const; + + + Set& select(Set& new_set, std::vector& indices) const; + + + void load(const std::string& location); + + + void save(const std::string& location) const; + + + void reset_bundle_indices(); + + +// protected: + + template void load_tpl(const std::string& location, V& reader); + + + template void save_tpl(const std::string& location, V& writer) const; + +// protected: + + size_t key_index(const std::string& key) const; + + + void init_extend_elem_props(); + + + static void check_good(std::ifstream& in) + { if (!in.good()) throw Exception ("Could not read from properties file."); } + + + static void read_props_preamble(std::ifstream& in); + + + void add_extend_elem_prop_row(const std::vector& values_row); + + + void add_extend_elem_prop_row(const std::map& properties); + + + std::vector parse_extend_elem_props_line(const std::string& line); + + + std::vector read_extend_elem_prop_header(std::ifstream& file_in); + + + void load_extend_elem_props(std::string location); + + + void save_extend_elem_props(std::string location); + + + + //! Returns the number of elem_properties the object has. + size_t num_elem_props() const + { return elem_props->size(); } + + + /*! Adds a new element property to the object. + * Can only be used if the object is not part of a larger object (eg. a set) + * + * @param[in] name Pointer to the element property string (NB: comparisons are performed on the pointer itself not its + * contents so must be consitent application wide. It is implemented as a c-string instead of + * an enum so for input/output purposes only) + * @param[in] value The value assigned to the element property + */ + void add_elem_prop(const char* const name, double value = NAN, bool ignore_present=true); + + + /*! Adds a new element property to the object. + * Can only be used if the object is not part of a larger object (eg. a set) + * + * @param[in] name Pointer to the element property string (NB: comparisons are performed on the pointer itself not its + * contents so must be consitent application wide. It is implemented as a c-string instead of + * an enum so for input/output purposes only) + */ + bool has_elem_prop(const char* name) const + { for (size_t elem_prop_i = 0; elem_prop_i < num_elem_props(); ++elem_prop_i) { if (name == elem_props->operator[](elem_prop_i)) return true; } return false; } + + + /*! Adds a new element property to the object. + * Can only be used if the object is not part of a larger object (eg. a set) + * + * @param[in] name The element property name + * @param[in] ignore_missing Set to true if it doesn't matter whether the element property is present + */ + void remove_elem_prop(const char* const name, bool ignore_missing = true); + + + //! Removes all elem_properties. + void clear_elem_props(); + + + /*! Copy all element properties from @arg set to the current set + * + * @param set + */ + template void copy_elem_props(const Set& set); + + + /*! Returns the index of the given element property relative the other elem_properties + * + * @param name + * @return index of element property for the given objecct + */ + size_t elem_prop_index(const char* const name) const; + + + /*! Access the element property at the given index for const object. + * + * @param index of element property + * @return reference of corresponding element property + */ + const char* elem_prop_key(size_t index) const + { return elem_props->operator[](index); } + + + std::vector& insert_elem_prop_keys(std::vector& header) const; + + + /*! Attempts to fix the row size to a single member variable (stored in 'rsize') instead of many row sizes + * (stored in 'row_ends'). This allows the use of some functions, such as 'bmatrix()' that require a fixed + * row size. If the number of rows are variable it will throw an exception unless the 'ignore_fail' flag is set. + * + * @param ignore_fail Ignore failure to fix the row size (eg. for use in load functions) + * @return Fixed row size + */ + size_t freeze_elem_degree(bool ignore_fail = false); + + + /*! Frees the restriction on row sizes being equal to a single member variable. This excludes the use of some + * functions, such as 'bmatrix()' that require a fixed row size and will also take up an extra sizeof(void*) + * of memory for each element + * + */ + void free_elem_degree(); + + + /*! Resize the number of @see Triple objects in the fibre object (does not effect the properties) + * + * @param size The number of @see Triple objects in the new fibre object + * @param fill_value The value assigned to the any empty values. + * @param new_elem_degree The size() of the new element if the row size is variable (otherwise it is not required and will be ignored). + * @param new_elem_vsize The vsize() of the new element if the row size is variable (otherwise it is not required and will be ignored). + */ + void resize(size_t size, double fill_value = NAN, size_t new_elem_degree = 0, size_t new_vsize = 0); + + + void resize(size_t size, const T& elem); + + + //! Return a MR::Math::Matrix window to the underlying state vector interpreted as a matrix (without properties). + MR::Math::Matrix bmatrix() + { assert(!var_elem_degrees()); return MR::Math::Matrix(data, size(), rsize, stride()); } + + + + /*! Used in SetReader to load up the element without the properties which are set afterwards + * + * @param elem The element to push to the back of the set. + * @param without_props Flag to to not push back the properties of the element, which are loaded separately in the reader. + * @return + */ + T push_back(const T& elem, bool without_props); + + protected: + + + /*! Returns the row size for the given row index. If the row size is fixed it is simply returned otherwise the + * variable row size is looked up. + * + * @param row_index Index of the row to be looked up + * @return The size of the specified row + */ + size_t row_size(size_t row_index) const + { return !var_elem_degrees() ? rsize : (row_ends ? (!row_index ? row_ends[0] : row_ends[row_index] - row_ends[row_index -1]) : 0); } + + + /*! Returns the start index for the given row. If 'rsize' is defined then it is simply the row index x the row + * size ('rsize'). If 'row_ends' is defined then the index of the previous end is returned. + * + * @param row_index Index of the row to be looked up + * @return The start index of the specified row + */ + size_t row_start(size_t row_index) const + { return !var_elem_degrees() ? row_index * rsize : (row_ends ? (row_index ? row_ends[row_index-1] : 0) : 0); } + + + /*! Returns the end index for the given row. If 'rsize' is defined then it is simply the row index x the row size ('rsize') + * + * @param row_index Index of the row to be looked up + * @return The end index of the specified row + */ + size_t row_end(size_t row_index) const + { return !var_elem_degrees() ? (row_index + 1) * rsize : ( row_ends ? row_ends[row_index] : 0); } + + + + /*! Test whether the object has variable row sizes or not + * + * @return True if row size is variable + */ + bool var_elem_degrees() const + { return vrows; } + + + /*! Used in constructors called in-turn from Set constructors to calculate the row ends from variable element + * sizes and a fixed elem_row_size + * + * @param elem_degrees + * @param elem_row_size + */ + void calculate_row_ends(size_t* elem_degrees, size_t elem_row_size, + size_t num_elem_props) { + + size_t row_start = 0; + + for (size_t row_i = 0; row_i < size(); ++row_i) + row_ends[row_i] = row_start + elem_degrees[row_i] * elem_row_size + num_elem_props; + + } + + }; + + template std::ostream& operator<< (std::ostream& stream, const Set& set); + + typedef std::map Properties; + + } + + } + +} + +#include "bts/fibre/base/set.cpp.h" + +#endif diff --git a/src/bts/fibre/base/set/tensor.h b/src/bts/fibre/base/set/tensor.h new file mode 100644 index 0000000..5dc49c4 --- /dev/null +++ b/src/bts/fibre/base/set/tensor.h @@ -0,0 +1,160 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, 11/08/2010. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + +#ifndef __bts_fibre_set_tensor_h__ +#define __bts_fibre_set_tensor_h__ + +#include "bts/fibre/base/set.h" + + +// +//namespace BTS { +// +// namespace Fibre { +// +// namespace Base { +// +// template template class Set::Tensor_tpl : public std::map::Intrinsic_tpl { +// +// public: +// +// typedef typename U::template Tensor_tpl Element; +// typedef Set ColumnClass; +// typedef typename std::vector< typename U::template Tensor_tpl >::iterator iterator; +// typedef typename std::vector< typename U::template Tensor_tpl >::const_iterator const_iterator; +// +// public: +// +// typename T::Set base_intensity; +// +// //Protected member variables; +// protected: +// +// std::vector elems; +// +// //Public member functions +// public: +// +// Tensor_tpl () { init(); } +// +// Tensor_tpl(const Set& default_value); +// +// Tensor_tpl(const Tensor_tpl& t) +// : base_intensity(t.base_intensity), elems(t.elems) { init(); } +// +// ~Tensor_tpl() {} +// +// Tensor_tpl& operator= (const Tensor_tpl& t) +// { base_intensity = t.base_intensity; elems = t.elems; return *this; } +// +// Element& operator[] (int idx) +// { return (elems[idx]); } +// +// const Element& operator[] (int idx) const +// { return (elems[idx]); } +// +// iterator begin() { return elems.begin(); } +// const_iterator begin() const { return elems.begin(); } +// +// iterator end() { return elems.end(); } +// const_iterator end() const { return elems.end(); } +// +// +// Tensor_tpl& operator+= (const Tensor_tpl& tensor) +// { base_intensity += tensor.base_intensity; for (size_t elem_i = 0; elem_i < size(); elem_i++) operator[](elem_i) += tensor[elem_i]; return *this; } +// +// Tensor_tpl& operator-= (const Tensor_tpl& tensor) +// { base_intensity -= tensor.base_intensity; for (size_t elem_i = 0; elem_i < size(); elem_i++) operator[](elem_i) -= tensor[elem_i]; return *this; } +// +// Tensor_tpl& operator*= (const Tensor_tpl& tensor) +// { base_intensity *= tensor.base_intensity; for (size_t elem_i = 0; elem_i < size(); elem_i++) operator[](elem_i) *= tensor[elem_i]; return *this; } +// +// Tensor_tpl& operator*= (double c) +// { base_intensity *= c; for (size_t elem_i = 0; elem_i < size(); elem_i++) operator[](elem_i) *= c; return *this; } +// +// Tensor_tpl& operator/= (const Tensor_tpl& tensor) +// { base_intensity /= tensor.base_intensity; for (size_t elem_i = 0; elem_i < size(); elem_i++) operator[](elem_i) /= tensor[elem_i]; return *this; } +// +// Tensor_tpl& operator/= (double c) +// { base_intensity /= c; for (size_t elem_i = 0; elem_i < size(); elem_i++) operator[](elem_i) /= c; return *this; } +// +// Tensor_tpl operator+ (const Tensor_tpl& t) const +// { Tensor_tpl answer (*this); answer += t; return answer; } +// +// Tensor_tpl operator- (const Tensor_tpl& t) const +// { Tensor_tpl answer (*this); answer -= t; return answer; } +// +// Tensor_tpl operator* (const Tensor_tpl& t) const +// { Tensor_tpl answer (*this); answer *= t; return answer; } +// +// Tensor_tpl operator* (double c) const +// { Tensor_tpl answer (*this); answer *= c; return answer; } +// +// Tensor_tpl operator/ (const Tensor_tpl& t) const +// { Tensor_tpl answer (*this); answer /= t; return answer; } +// +// Tensor_tpl operator/ (double c) const +// { Tensor_tpl answer (*this); answer /= c; return answer; } +// +// Tensor_tpl& zero() +// { base_intensity.zero(); for (iterator it = begin(); it != end(); it++) it->zero(); return *this; } +// +// Tensor_tpl& invalidate() +// { base_intensity.invalidate(); for (iterator it = begin(); it != end(); it++) it->invalidate(); return *this; } +// +// size_t size() const +// { return elems.size(); } +// +// void push_back(const Element& elem) +// { elems.push_back(elem); } +// +// void clear() +// { base_intensity.clear(); elems.clear(); } +// +// +// Set get_diagonal() const; +// +// +// void set_diagonal(const Set& diagonal); +// +// +// protected: +// +// void init() { +// +// if (Fibre::Object::include_intrinsic_intensities) +// this->intrinsic_props["base_intensity"] = &base_intensity; +// else +// base_intensity.set(1.0); +// +// } +// +// +// }; +// +// } +// +// } +// +//} + +#endif /* __bts_fibre_set_tensor_h__ */ diff --git a/src/bts/fibre/base/set_reader.cpp.h b/src/bts/fibre/base/set_reader.cpp.h new file mode 100644 index 0000000..174c268 --- /dev/null +++ b/src/bts/fibre/base/set_reader.cpp.h @@ -0,0 +1,184 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, Jul 26, 2010. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + +#ifndef __bts_fibre_setreader_cpp_h__ +#define __bts_fibre_setreader_cpp_h__ + +namespace BTS { + + namespace Fibre { + + namespace Base { + + template void SetReader::open (const std::string& location) { + + + Reader::open(location); + + std::string elem_properties_location = location + "xx"; + + if (File::is_file(elem_properties_location)) { + + elem_in.open(elem_properties_location.c_str()); + + elem_prop_hdr = Reader::read_props_header(elem_in); + ext_elem_prp_keys = elem_prop_hdr; + elem_prp_keys = Object::extract_props(ext_elem_prp_keys); + + elem_begin = elem_in.tellg(); + + } else { + + elem_prop_hdr.clear(); + ext_elem_prp_keys.clear(); + elem_prp_keys.clear(); + + elem_begin = 0; + + } + + } + + + template void SetReader::rewind() { + + Reader::rewind(); + + if (elem_begin) + elem_in.seekg(elem_begin); + + } + + + template bool SetReader::next (T& set) { + + std::map properties; + + set.reset(this->prp_keys, elem_prp_keys); + + if (Reader::next_basic(set)) { + + //Set 'set-wide' properties + if (this->prop_hdr.size()) { + std::string line; + + if (!std::getline(this->prop_in, line)) + throw Exception ("No corresponding line found in extended properties file."); + + properties = parse_props_line(this->prop_hdr, line); + + set.extract_and_set_props(properties); + set.set_extend_props(properties); + + } + + //Set element properties. + set.clear_extend_elem_props(); + + if (elem_prop_hdr.size()) { + + for (std::vector::iterator prop_it = ext_elem_prp_keys.begin(); prop_it != ext_elem_prp_keys.end(); ++prop_it) + set.add_extend_elem_prop(*prop_it, ""); + + std::string line; + + if (!std::getline(elem_in, line)) + throw Exception ("No corresponding row found in set properties file."); + + size_t elem_index = 0; + + while (!is_row_seperator(line)) { + + if (elem_index >= set.size()) + throw Exception ("Loaded properties contain more rows than elements in the set"); + + std::map elem_prop_row = Reader::parse_props_line(elem_prop_hdr, line); + + //FIXME: Needs to be implemented + std::map ext_elem_prop_row = set[elem_index].extract_and_set_props(elem_prop_row); + + set.set_extend_elem_prop_row(ext_elem_prop_row, elem_index); + + ++elem_index; + + if (!std::getline(elem_in, line)) + throw Exception ("Set properties row is incomplete."); + } + + } + + } else + return false; + + return true; + + } + + + template bool SetReader::is_row_seperator(const std::string& line) { + + bool is_seperator = false; + + if (line.size() > 12) + is_seperator = !strcmp(line.substr(0,8).c_str(), "--- END ") && !strcmp(line.substr(line.size()-4, 4).c_str(), " ---"); + + return is_seperator; + + } + + + template Coord SetTextReader::read_coord () { + + Coord coord; + + if (!this->in.good()) + throw Exception ("Corrupted fibre object file '" + this->file_location +"'."); + + std::string next_value; + + for (int dim_i = 0; dim_i < 3; dim_i++) { + + this->in >> next_value; + + if (next_value == "nan") + coord[dim_i] = NAN; + else if (next_value == "inf") + coord[dim_i] = INFINITY; + else if (next_value == "-inf") + coord[dim_i] = -INFINITY; + else if (strspn(next_value.c_str(),"-e0.123456789") == next_value.size()) + coord[dim_i] = to(next_value); + else + dim_i--; //If next_value is not a number empty skip. (this is mainly for the start of the file which has some funny bits). + + } + + return coord; + } + + } + + } + +} + +#endif /* __bts_fibre_set_reader_cpp_h__ */ diff --git a/src/bts/fibre/base/set_reader.h b/src/bts/fibre/base/set_reader.h new file mode 100644 index 0000000..6812106 --- /dev/null +++ b/src/bts/fibre/base/set_reader.h @@ -0,0 +1,128 @@ +/* + Copyright 2010 Brain Research Institute/National ICT Australia (NICTA), Melbourne, Australia + + Written by Thomas G Close, 5/05/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + +*/ + +#ifndef __bts_fibre_setreader_h__ +#define __bts_fibre_setreader_h__ + +#include +#include +#include + +#include "bts/fibre/base/set.h" +#include "bts/fibre/base/reader.h" + + +namespace BTS { + + namespace Fibre { + + namespace Base { + + template class SetReader : public Reader { + + + // Protected member fields. + protected: + + std::vector elem_prop_hdr; + std::vector elem_prp_keys; + std::vector ext_elem_prp_keys; + + std::ifstream elem_in; + off64_t elem_begin; + + // Public methods and constructors. + public: + + SetReader () {} + + SetReader (const std::string& location) + { open(location); } + + ~SetReader() + { close(); } + + void open (const std::string& location); + + + void rewind(); + + + bool next(T& fibre); + + + bool next(T& fibre, std::map& properties) + { if (next(fibre)) { properties = fibre.get_extend_props(); return true; } else return false; } + + + void close() + { Base::Reader::close(); elem_in.close(); elem_prop_hdr.clear(); } + + + std::vector extend_elem_prop_keys() const + { return ext_elem_prp_keys; } + + + std::vector elem_prop_keys() const + { return elem_prp_keys; } + + + std::vector elem_header() const + { return elem_prop_hdr; } + + protected: + + + static bool is_row_seperator(const std::string& line); + + + }; + + + + template class SetTextReader : public SetReader { + + //Public static variables, nested classes and typedefs + public: + + SetTextReader () {} + + SetTextReader (const std::string& location) + : Base::SetReader(location) {} + + Coord read_coord (); + + }; + + + } + + } + + +} + +#include "bts/fibre/base/set_reader.cpp.h" + + + +#endif diff --git a/src/bts/fibre/base/set_writer.cpp.h b/src/bts/fibre/base/set_writer.cpp.h new file mode 100644 index 0000000..182c959 --- /dev/null +++ b/src/bts/fibre/base/set_writer.cpp.h @@ -0,0 +1,119 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, Jul 26, 2010. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + +#ifndef __bts_fibre_setwriter_cpp_h__ +#define __bts_fibre_setwriter_cpp_h__ + +#include "bts/fibre/base/set.h" + +namespace BTS { + + namespace Fibre { + + namespace Base { + + + template void SetWriter::create (const std::string& location, + const std::vector& props, + const std::vector& elem_props, + const std::vector extend_prop_keys, + const std::vector extend_elem_prop_keys, + const std::map& file_props) { + + std::vector elem_header; + + //Add the elem props into the elem header first (doesn't really need to be first but I like it that way when I read the files manually) + for (size_t prop_i = 0; prop_i < elem_props.size(); ++prop_i) + elem_header.push_back(elem_props[prop_i]); + + //Insert the extended properties into the set and elem headers. + elem_header.insert(elem_header.end(), extend_elem_prop_keys.begin(), extend_elem_prop_keys.end()); + + Writer::create(location, props, extend_prop_keys, file_props); + + elem_prop_hdr = elem_header; + + std::string set_properties_location = location + "xx"; + + if (elem_prop_hdr.size()) { + + ext_elem_out.open((set_properties_location).c_str()); + + Writer::write_props_header(ext_elem_out, elem_prop_hdr); + + } else if (File::exists(set_properties_location)) + File::remove(set_properties_location); + + + } + + + template void SetWriter::append (const T& set) { + + + Base::Writer::append(set, set.get_extend_props()); + + for (size_t elem_i = 0; elem_i < set.size(); elem_i++) { + + std::map properties_row = set.get_extend_elem_prop_row(elem_i); // + + set[elem_i].insert_props(properties_row); + + write_properties_row(this->elem_prop_hdr, properties_row, this->ext_elem_out); + + } + + this->ext_elem_out << row_seperator(this->count) << std::endl; + + + } + + + template void SetWriter::append (const T& set, std::map& properties) { + + T new_set (set); + + std::map extend_props = new_set.get_extend_props(); + + for (std::map::iterator prop_it = extend_props.begin(); prop_it != extend_props.end(); ++prop_it) + new_set.set_extend_prop(prop_it->first, prop_it->second); + + append(new_set); + + } + + + template void SetTextWriter::write (const Coord& coord) { + + this->out << "\n" << coord[X] << " " << coord[Y] << " " << coord[Z]; + this->out.flush(); + + } + + } + + } + + +} + +#endif /* __bts_fibre_set_writer_cpp_h__ */ diff --git a/src/bts/fibre/base/set_writer.h b/src/bts/fibre/base/set_writer.h new file mode 100644 index 0000000..344d1da --- /dev/null +++ b/src/bts/fibre/base/set_writer.h @@ -0,0 +1,202 @@ +/* + Copyright 2010 Brain Research Institute/National ICT Australia (NICTA), Melbourne, Australia + + Written by Thomas G Close, 5/05/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + +*/ + + +#ifndef __bts_fibre_setwriter_h__ +#define __bts_fibre_setwriter_h__ + +#include + +#include "bts/fibre/base/set.h" +#include "bts/fibre/base/writer.h" +#include "bts/fibre/base/set_reader.h" + + +namespace BTS { + + namespace Fibre { + + namespace Base { + + template class SetWriter : public Fibre::Base::Writer { + + // Nested classes and typedefs + public: + + // Protected member fields. + protected: + + std::vector elem_prop_hdr; + + std::ofstream ext_elem_out; + + // Public methods and constructors. + public: + + SetWriter() {} + + + template SetWriter (const std::string& location, + const U& set_or_reader, + const std::map& file_props = std::map()) + { create (location, set_or_reader, file_props); } + + + template SetWriter (const std::string& location, + const U& set_or_reader, + const std::vector& extend_prop_keys, + const std::map& file_props = std::map()) + { create( location, set_or_reader, extend_prop_keys, file_props); } + + + template SetWriter( const std::string& location, + const U& set_or_reader, + const std::vector& extend_prop_keys, + const std::vector& extend_elem_prop_keys, + const std::map& file_props = std::map()) + { create( location, set_or_reader, extend_prop_keys, extend_elem_prop_keys, file_props); } + + + virtual ~SetWriter() + { close(); } + + + template void create (const std::string& location, + const U& set_or_reader, + const std::map& file_props = std::map()) { + create( location, + Object::select_props(set_or_reader.prop_keys()), + Object::select_props(set_or_reader.elem_prop_keys()), + set_or_reader.extend_prop_keys(), + set_or_reader.extend_elem_prop_keys(), + file_props); + } + + + template void create (const std::string& location, + const U& set_or_reader, + const std::vector& extend_prop_keys, + const std::map& file_props = std::map()) { + create( location, + Object::select_props(set_or_reader.prop_keys()), + Object::select_props(set_or_reader.elem_prop_keys()), + extend_prop_keys, + set_or_reader.extend_elem_prop_keys(), + file_props); + } + + + template void create (const std::string& location, + const U& set_or_reader, + const std::vector& extend_prop_keys, + const std::vector& extend_elem_prop_keys, + const std::map& file_props = std::map()) { + create( location, + Object::select_props(set_or_reader.prop_keys()), + Object::select_props(set_or_reader.elem_prop_keys()), + extend_prop_keys, + extend_elem_prop_keys, + file_props); + } + + + + void append (const T& set); + + //Not recommended as it involves a copy only included to make a template function work. + void append (const T& set, std::map& properties); + + void close () + { Fibre::Base::Writer::close(); ext_elem_out.close(); } + + // Protected methods and constructors + protected: + + + void create ( const std::string& location, + const std::vector& props, + const std::vector& elem_props, + const std::vector extend_prop_keys = std::vector(), + const std::vector extend_elem_prop_keys = std::vector(), + const std::map& file_props = std::map()); + + static std::string row_seperator(size_t count) + { return "--- END " + str(count) + " ---"; } + + }; + + + + //TODO: Make use of DWI::Tractography::Writers template to Remove this text writer. + template class SetTextWriter : public SetWriter { + + //Public static variables, nested classes and typedefs + + public: + + SetTextWriter() {} + + + template SetTextWriter (const std::string& location, + const U& set_or_reader, + const std::map& file_props = std::map()) + : SetWriter(location, set_or_reader, file_props) {} + + + template SetTextWriter (const std::string& location, + const U& set_or_reader, + const std::vector& extend_prop_keys, + const std::map& file_props = std::map()) + : SetWriter(location, set_or_reader, extend_prop_keys, file_props) {} + + + template SetTextWriter( const std::string& location, + const U& set_or_reader, + const std::vector& extend_prop_keys, + const std::vector& extend_elem_prop_keys, + const std::map& file_props = std::map()) + : SetWriter(location, set_or_reader, extend_prop_keys, extend_elem_prop_keys, file_props) {} + + + void write (const Coord& coord); + + void replace_end_of_file(const Coord& t, off64_t start_pos) {} + + Coord write_first(const Coord& t) + { this->out.seekp((int)this->out.tellp() - 12); write (t); return t; } + + using Writer::write; + + + }; + + + } + + } + +} + +#include "bts/fibre/base/set_writer.cpp.h" + + +#endif diff --git a/src/bts/fibre/base/tensor.cpp.h b/src/bts/fibre/base/tensor.cpp.h new file mode 100644 index 0000000..57c064a --- /dev/null +++ b/src/bts/fibre/base/tensor.cpp.h @@ -0,0 +1,54 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, 31/08/2010. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + +#ifndef /Tractography/src/bts/fibre/tensor.cpp.h +#define + +namespace BTS { + + namespace { + + class { + + //Public static variables, nested classes and typedefs + public: + + + //Protected member variables + protected: + + + //Public member functions + public: + + + //Protected member functions + protected: + + + }; + + } + +} + +#endif /* */ \ No newline at end of file diff --git a/src/bts/fibre/base/tensor.h b/src/bts/fibre/base/tensor.h new file mode 100644 index 0000000..96bfa3a --- /dev/null +++ b/src/bts/fibre/base/tensor.h @@ -0,0 +1,168 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, 31/08/2010. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + +#ifndef __bts_fibre_base_tensor_h__ +#define __bts_fibre_base_tensor_h__ + +#include "math/matrix.h" + +namespace BTS { + + namespace Fibre { + + namespace Base { + + template class TensorWriter; + + template class Tensor : public MR::Math::Matrix { + + //Public nested classes and typedefs + public: + + typedef T RowType; + typedef TensorWriter Writer; + + //Protected member variables + protected: + + T tmpl; // Template object on which the tensor is based. + + //Public member functions + public: + + Tensor() {} + + Tensor(const T& fibre_template) + : MR::Math::Matrix(fibre_template.vsize(), fibre_template.vsize()), tmpl (fibre_template) { tmpl.zero(); } + + + Tensor (const T& fibre_template, const MR::Math::Matrix::View& view) + : MR::Math::Matrix(view), tmpl(fibre_template) { tmpl.zero(); } + + + Tensor(const Tensor& t) + : MR::Math::Matrix(t), tmpl(t.tmpl) {} + + + Tensor& operator=(const Tensor& t) + { MR::Math::Matrix::operator=(t); tmpl = t.tmpl; return *this; } + + Tensor& operator=(const MR::Math::Matrix& m) + { assert(m.rows() == vsize()); assert(m.columns() == vsize()); MR::Math::Matrix::operator=(m); return *this; } + + Tensor& operator=(double c) + { MR::Math::Matrix::operator=(c); return *this; } + + + Tensor& reset(const T& fibre_template) { + tmpl = fibre_template; + tmpl.zero(); + MR::Math::Matrix::resize(tmpl.vsize(), tmpl.vsize()); + zero(); + return *this; + } + + + Tensor& zero() + { MR::Math::Matrix::operator=(0.0); return *this; } + + + Tensor& invalidate() + { MR::Math::Matrix::operator=(NAN); return *this; } + + + T get_template() const + { return tmpl; } + + + double vsize() const + { return tmpl.vsize(); } + + + Tensor& operator+= (double c) + { MR::Math::Matrix::operator+=(c); return *this; } + + + Tensor& operator-= (double c) + { MR::Math::Matrix::operator-=(c); return *this; } + + + Tensor& operator*= (double c) + { MR::Math::Matrix::operator*=(c); return *this; } + + + Tensor& operator/= (double c) + { MR::Math::Matrix::operator/=(c); return *this; } + + + Tensor operator+ (double c) const + { Tensor answer (*this); answer += c; return answer;} + + + Tensor operator- (double c) const + { Tensor answer (*this); answer -= c; return answer;} + + + Tensor operator* (double c) const + { Tensor answer (*this); answer *= c; return answer;} + + + Tensor operator/ (double c) const + { Tensor answer (*this); answer /= c; return answer;} + + + Tensor& operator+= (const Tensor& t) + { MR::Math::Matrix::operator+=(t); return *this; } + + + Tensor& operator-= (const Tensor& t) + { MR::Math::Matrix::operator+=(t); return *this; } + + + Tensor operator+ (const Tensor& t) const + { Tensor answer (*this); answer += t; return answer;} + + + Tensor operator- (const Tensor& t) const + { Tensor answer (*this); answer -= t; return answer;} + + + using MR::Math::Matrix::operator+=; + + + }; + + + template Tensor operator+ (double c, const Tensor& t) + { return t + c; } + + template Tensor operator* (double c, const Tensor& t) + { return t * c; } + + } + + } + +} + + +#endif /* __bts_fibre_base_tensor_h__ */ diff --git a/src/bts/fibre/base/tensor/writer2.cpp.h b/src/bts/fibre/base/tensor/writer2.cpp.h new file mode 100644 index 0000000..c2ade46 --- /dev/null +++ b/src/bts/fibre/base/tensor/writer2.cpp.h @@ -0,0 +1,74 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, 10/08/2010. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + +#ifndef __bts_tensor_writer2_cpp_h__ +#define __bts_tensor_writer2_cpp_h__ + + + +#include "bts/fibre/tensor/writer2.h" + +namespace BTS { + + namespace Fibre { + + namespace Tensor { + + template const std::string Writer2::HEADER_PREAMBLE = "%%% Keys %%%:"; + + + template void Writer2::create (const std::string& location, const T& template_value) { + + header = Unzipper::header(template_value); + template_length = Unzipper::size(template_value); + + out.open(location.c_str()); + + out << HEADER_PREAMBLE; + + for (std::vector::iterator key_it = header.begin(); key_it != header.end(); ++key_it) + out << *key_it << " "; + + out << std::endl; + + } + + + template void Writer2::append(const MR::Math::Matrix& tensor) { + + if (template_length != tensor.rows()) + throw Exception ("Length of tensor matrix (" + str(tensor.rows()) + ") did not match size of template value vector (" + str(template_length) + ")."); + + out << tensor; + + out.flush(); + + } + + + } + + } + +} + +#endif /* __bts_tensor_writer2_cpp_h__ */ diff --git a/src/bts/fibre/base/tensor/writer2.h b/src/bts/fibre/base/tensor/writer2.h new file mode 100644 index 0000000..f583833 --- /dev/null +++ b/src/bts/fibre/base/tensor/writer2.h @@ -0,0 +1,79 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, 10/08/2010. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + +#ifndef __bts_fibre_tensor_writer2_h__ +#define __bts_fibre_tensor_writer2_h__ + +namespace BTS { + + namespace Fibre { + + namespace Tensor { + + template class Writer2 { + + //Public static variables, nested classes and typedefs + public: + + static const std::string HEADER_PREAMBLE; + + //Protected member variables + protected: + + std::vector header; + size_t template_length; + std::ofstream out; + + //Public member functions + public: + + Writer2() {} + + Writer2(const std::string& location, const T& template_value = T()) + { create(location, template_value); } + + Writer2(const std::string& location, size_t size) + { create(location, size); } + + ~Writer2() + { close(); } + + void close() + { out.close(); } + + void create (const std::string& location, size_t size) + { create(location, T(size)); } + + void create (const std::string& location, const T& template_value); + + void append(const MR::Math::Matrix& tensor); + + + }; + + } + + } + +} + +#endif /* __bts_fibre_tensor_writer2_h__ */ diff --git a/src/bts/fibre/base/tensor_writer.cpp.h b/src/bts/fibre/base/tensor_writer.cpp.h new file mode 100644 index 0000000..d5d1ff8 --- /dev/null +++ b/src/bts/fibre/base/tensor_writer.cpp.h @@ -0,0 +1,149 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, 10/08/2010. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + +#ifndef __bts_fibre_base_tensorwriter_cpp_h__ +#define __bts_fibre_base_tensorwriter_cpp_h__ + +#include "bts/fibre/base/tensor_writer.h" + +namespace BTS { + + namespace Fibre { + + namespace Base { + + template const std::string TensorWriter::HEADER_PREAMBLE = "%%% Keys %%%:"; + + + template void TensorWriter::create (const std::string& location, const typename T::RowType& template_value) { + + hdr = header(template_value); + template_length = template_value.vsize(); + + out.open(location.c_str()); + + out << HEADER_PREAMBLE; + + for (std::vector::iterator key_it = hdr.begin(); key_it != hdr.end(); ++key_it) + out << *key_it << " "; + + out << std::endl; + + } + + + template void TensorWriter::append(const T& tensor) { + + if (template_length != tensor.rows()) + throw Exception ("Number of rows in tensor matrix (" + str(tensor.rows()) + ") did not match size of template (" + str(template_length) + ")."); + + if (template_length != tensor.columns()) + throw Exception ("Number of columns in tensor matrix (" + str(tensor.columns()) + ") did not match size of template (" + str(template_length) + ")."); + + out << (MR::Math::Matrix&)tensor; + + } + + + + + template std::vector TensorWriter::header(const typename T::RowType& tmplate) { + + std::vector headr; + + header_element(tmplate, headr, ""); + + return headr; + + } + + + template void TensorWriter::header_element( const Strand& strand, + std::vector& header, + const std::string& prefix) { + + for (size_t prop_i = 0; prop_i < strand.num_props(); ++prop_i) + header.push_back(prefix + strand.prop_key(prop_i) + ">"); + + for(uint degree_i = 0; degree_i < strand.degree(); degree_i++) + header_element(strand[degree_i], header, prefix + "degree" + str(degree_i) + ">"); + + } + + + template void TensorWriter::header_element( const Tractlet& tractlet, + std::vector& header, + const std::string& prefix) { + + + for (size_t prop_i = 0; prop_i < tractlet.num_props(); ++prop_i) + header.push_back(prefix + tractlet.prop_key(prop_i) + ">"); + + for (uint ax_i = 0; ax_i < 3; ax_i++) + header_element(tractlet[ax_i], header, prefix + "axis" + str(ax_i) + ">"); + + + } + + + template void TensorWriter::header_element(const Tractlet::Set& set, + std::vector& header, + const std::string& prefix) { + + for (size_t prop_i = 0; prop_i < set.num_props(); ++prop_i) + header.push_back(prefix + set.prop_key(prop_i) + ">"); + + for (uint elem_i = 0; elem_i < set.size(); elem_i++) + header_element(set[elem_i], header, prefix + "tractlet" + str(elem_i) + ">"); + + } + + + template void TensorWriter::header_element(const Strand::Set& set, + std::vector& header, + const std::string& prefix) { + + for (size_t prop_i = 0; prop_i < set.num_props(); ++prop_i) + header.push_back(prefix + set.prop_key(prop_i) + ">"); + + for (uint elem_i = 0; elem_i < set.size(); elem_i++) + header_element(set[elem_i], header, prefix + "strand" + str(elem_i) + ">"); + + } + + + template void TensorWriter::header_element(const Coord& element, + std::vector& header, + const std::string& prefix) { + + for(uint dim_i = 0; dim_i < 3; dim_i++) + header.push_back(prefix + "dim" + str(dim_i) + ">"); + + } + + } + + } + +} + +#endif /* __bts_fibre_base_tensorwriter_cpp_h__ */ diff --git a/src/bts/fibre/base/tensor_writer.h b/src/bts/fibre/base/tensor_writer.h new file mode 100644 index 0000000..fef5fe4 --- /dev/null +++ b/src/bts/fibre/base/tensor_writer.h @@ -0,0 +1,93 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, 10/08/2010. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + +#ifndef __bts_fibre_base_tensorwriter_h__ +#define __bts_fibre_base_tensorwriter_h__ + +#include "bts/fibre/strand.h" +#include "bts/fibre/tractlet.h" + +namespace BTS { + + namespace Fibre { + + namespace Base { + + template class TensorWriter { + + //Public static variables, nested classes and typedefs + public: + + static const std::string HEADER_PREAMBLE; + + //Protected member variables + protected: + + std::vector hdr; + size_t template_length; + std::ofstream out; + + public: + + static std::vector header(const typename T::RowType& tmplate); + + static void header_element(const Strand& tmplate, std::vector& header, const std::string& prefix); + static void header_element(const Tractlet& tmplate, std::vector& header, const std::string& prefix); + static void header_element(const Strand::Set& tmplate, std::vector& header, const std::string& prefix); + static void header_element(const Tractlet::Set& tmplate, std::vector& header, const std::string& prefix); + static void header_element(const Coord& tmplate, std::vector& header, const std::string& prefix); + + //Public member functions + public: + + TensorWriter() {} + + TensorWriter(const std::string& location, const typename T::RowType& template_value = typename T::RowType()) + { create(location, template_value); } + + TensorWriter(const std::string& location, size_t size) + { create(location, size); } + + ~TensorWriter() + { close(); } + + void close() + { out.close(); } + + void create (const std::string& location, size_t size) + { create(location, T(size)); } + + void create (const std::string& location, const typename T::RowType& template_value); + + void append(const T& tensor); + + + }; + + } + + } + +} + + +#endif /* __bts_fibre_base_tensorwriter_h__ */ diff --git a/src/bts/fibre/base/writer.cpp.h b/src/bts/fibre/base/writer.cpp.h new file mode 100644 index 0000000..9bdaefe --- /dev/null +++ b/src/bts/fibre/base/writer.cpp.h @@ -0,0 +1,341 @@ +/* + Copyright 2010 Brain Research Institute/National ICT Australia (NICTA), Melbourne, Australia + + Written by Thomas G Close, 04/06/2010. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + +*/ + +#ifndef __bts_fibre_base_writer_cpp_h__ +#define __bts_fibre_base_writer_cpp_h__ + +#include "mrtrix.h" +#include "bts/version.h" + +namespace BTS { + + namespace Fibre { + + namespace Base { + + template void Writer::create(const std::string& location, + const std::vector& prop_keys, + const std::vector extend_prop_keys, + std::map file_props) { + + + //Combine prop keys and extended prop keys into one header vector. + std::vector prop_header; + + for (size_t prop_i = 0; prop_i < prop_keys.size(); ++prop_i) + prop_header.push_back(prop_keys[prop_i]); + + prop_header.insert(prop_header.end(), extend_prop_keys.begin(), extend_prop_keys.end()); + + file_props["software version"] = version_number_string(); + file_props["datetime"] = current_datetime(); + + out.open (location.c_str(), std::ios::out | std::ios::binary); + if (!out) throw Exception ("error creating tracks file \"" + location + "\": " + strerror (errno)); + + out << "mrtrix tracks\nEND\n"; + for (std::map::const_iterator i = file_props.begin(); i != file_props.end(); ++i) + out << i->first << ": " << i->second << "\n"; + + out << "datatype: " << dtype.specifier() << "\n"; + int64_t data_offset = int64_t(out.tellp()) + 65; + out << "file: . " << data_offset << "\n"; + out << "count: "; + count_offset = out.tellp(); + out << "\nEND\n"; + out.seekp (0); + out << "mrtrix tracks "; + out.seekp (data_offset); + write (Reader::END_OF_DATA); + + prop_hdr = prop_header; + + std::string props_row_location = location + "x"; + + if (prop_hdr.size()) { + + ext_out.open((props_row_location).c_str()); + + write_props_header(ext_out, prop_hdr); + + } else if (File::exists(props_row_location)) + + File::remove(props_row_location); + + this->count = this->total_count = 0; + + } + + + + template void Writer::append (const T& fibre_object, std::map properties_row) { + + // Record position of current END_OF_DATA marker, so it can be replaced as the last step, thus ensuring + // that the subsequent fibre object is completely written before the END_OF_DATA marker is updated. + off64_t start_pos = this->out.tellp(); + + // Holds the Triple that will replace the END_OF_DATA marker in the final step + Coord first_coord; + + if (fibre_object.size()) { + + // Writes the first fibre object minus the first coord, which is returned to replace the END_OF_DATA marker in the final step. + first_coord = write_first(fibre_object[0]); + + // Write the remaining fibre objects to the file + for (size_t fibre_i = 1; fibre_i < fibre_object.size(); fibre_i++) + write (fibre_object[fibre_i]); + + // Write the seperator sequence which denotes the end of the fibre object. + write (T::FILE_SEPARATOR); + + } else + // If the fibre_object is of size 0, the first coord will be simply the file seperator. + first_coord = T::FILE_SEPARATOR; + + // Write the new END_OF_DATA marker at the new end of the file. + write (Reader::END_OF_DATA); + + this->out.flush(); + + // Now that the rest of the object is completely written replace the END_OF_DATA marker with the first element to complete write. + replace_end_of_file (first_coord, start_pos); + + // Add extended row properties to accompanying text file. + append_extend_elem_props_row (fibre_object, properties_row); + + // Update the fibre object count. + increment_count(); + + + } + + + // 'write' and 'write_first' work by recursion. To use this fibre the fibre objects are only required to implement the 'operator[] + // ()' and have a const static Coord field called FILE_SEPARATOR. The recursion stops when the operator[]() returns a Coord. + template template inline void Writer::write(const U& fibre_object) { + + for (size_t fibre_i = 0; fibre_i < fibre_object.size(); fibre_i++) + write(fibre_object[fibre_i]); + + write (U::FILE_SEPARATOR); + + } + + + template template inline Coord Writer::write_first(const U& fibre_object) { + + Coord first_coord; + + if (fibre_object.size()) { + + first_coord = write_first(fibre_object[0]); + + for (size_t fibre_i = 1; fibre_i < fibre_object.size(); fibre_i++) + write(fibre_object[fibre_i]); + + write (U::FILE_SEPARATOR); + + } else + + first_coord = U::FILE_SEPARATOR; + + return first_coord; + + } + + + template void Writer::write(const Coord& t) { + + using namespace MR::ByteOrder; + + if (this->dtype == MR::DataType::Float64LE) { + + double x[3]; + + x[0] = MR::ByteOrder::LE(t[0]); + x[1] = MR::ByteOrder::LE(t[1]); + x[2] = MR::ByteOrder::LE(t[2]); + + this->out.write ((const char*) &x[0], 3*sizeof(double)); + + } else if (this->dtype == MR::DataType::Float64BE) { + + double x[3]; + + x[0] = MR::ByteOrder::BE(t[0]); + x[1] = MR::ByteOrder::BE(t[1]); + x[2] = MR::ByteOrder::BE(t[2]); + + this->out.write ((const char*) &x[0], 3*sizeof(double)); + + } else if (this->dtype == MR::DataType::Float32LE) { + + float x[3]; + + x[0] = MR::ByteOrder::LE(t[0]); + x[1] = MR::ByteOrder::LE(t[1]); + x[2] = MR::ByteOrder::LE(t[2]); + + this->out.write ((const char*) &x[0], 3*sizeof(float)); + + } else if (this->dtype == MR::DataType::Float32BE) { + + float x[3]; + + x[0] = MR::ByteOrder::BE(t[0]); + x[1] = MR::ByteOrder::BE(t[1]); + x[2] = MR::ByteOrder::BE(t[2]); + + this->out.write ((const char*) &x[0], 3*sizeof(float)); + + } else + throw Exception ("Unsupported dataype '" + str(this->dtype.specifier()) + "'."); + + + + } + + + //NB:: that the first coord is saved until last before overwriting the previous END_OF_DATA marker. + // This specialization of the template function write_first is the termination of a recursion + template Coord Writer::write_first(const Coord& t) { + + return t; + + } + + + template void Writer::update_count() { + + off64_t current_pos = this->out.tellp(); + + this->out.seekp (this->count_offset); + this->out << this->count << "\ntotal_count: " << this->total_count << "\nEND\n"; + + this->out.seekp(current_pos); + + } + + + template void Writer::replace_end_of_file(const Coord& t, + off64_t start_pos) { + + off64_t current = this->out.tellp(); + this->out.seekp(start_pos - sizeof_coord); + write(t); + this->out.seekp(current); + + } + + + template void Writer::check_properties_row(const std::map& properties_row) { + + if (properties_row.size() != this->prop_hdr.size()) { + + //Generate list of header for error message. + std::vector header; + for (std::map::const_iterator key_it = properties_row.begin(); key_it != properties_row.end(); key_it++) + header.push_back(key_it->first); + + //Throw Exception + throw Exception ("Supplied row properties (" + str (header) + + ") does not match the number of supplied header (" + str(prop_hdr) + "\")."); + } + + } + + + template void Writer::append_extend_elem_props_row (const T& fibre_object, + std::map& properties_row) { + fibre_object.insert_props(properties_row); + + write_properties_row(this->prop_hdr, properties_row, this->ext_out); + + } + + + template void Writer::append_extend_elem_props_row (std::map& properties_row) { + + write_properties_row(this->prop_hdr, properties_row, this->ext_out); + + } + + + template void Writer::write_properties_row(const std::vector& properties_header, + std::map& properties_row, + std::ofstream& fout) { + + for (std::vector::const_iterator hdr_it = properties_header.begin(); hdr_it != properties_header.end(); hdr_it++) { + + if (!properties_row.count(*hdr_it)) + throw Exception ("Did not find value corresponding to property '" + *hdr_it + "'."); + + fout << properties_row[*hdr_it] << '\t'; + + } + + fout << std::endl; + + } + + + template void Writer::init() { + + if (this->dtype == MR::DataType::Float64LE || this->dtype == MR::DataType::Float64BE) + sizeof_coord = 3 * sizeof(double); + else if (this->dtype == MR::DataType::Float32LE || this->dtype == MR::DataType::Float32BE) + sizeof_coord = 3 * sizeof(float); + else + throw Exception ("Unsupported dataype '" + str(this->dtype.specifier()) + "'."); + + + } + + + template void Writer::write_props_header(std::ofstream& out, const std::vector& header) { + + out << Reader::PROP_FILE_PREAMBLE; + + for (std::vector::const_iterator key_it = header.begin(); key_it != header.end(); key_it++) + out << *key_it << '\t'; + + out << std::endl; + + } + + + template void TextWriter::write (const Coord& coord) { + + this->out << "\n" << coord[X] << " " << coord[Y] << " " << coord[Z]; + this->out.flush(); + + } + + + } + + } + +} + +#endif /* __bts_fibre_writer_icpp__ */ diff --git a/src/bts/fibre/base/writer.h b/src/bts/fibre/base/writer.h new file mode 100644 index 0000000..4ca2b31 --- /dev/null +++ b/src/bts/fibre/base/writer.h @@ -0,0 +1,242 @@ +/* + Copyright 2010 Brain Research Institute/National ICT Australia (NICTA), Melbourne, Australia + + Written by Thomas G Close, 5/05/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + +*/ + +#ifndef __bts_fibre_base_writer_forward_h__ +#define __bts_fibre_base_writer_forward_h__ + +namespace BTS { + + namespace Fibre { + + namespace Base { + + template class Writer; + + } + + } + +} +#include "data_type.h" +#include "get_set.h" + +#include "bts/coord.h" + +#include "bts/file.h" + +#include "bts/fibre/properties/extended.h" +#include "bts/fibre/base/reader.h" + +namespace BTS { + + namespace Fibre { + + namespace Base { + + template class Writer { + + public: + + static void write_props_header(std::ofstream& out, const std::vector& header); + + public: + + size_t count, total_count; + + // Protected member fields. + protected: + + + std::ofstream out; + MR::DataType dtype; + int64_t count_offset; + + std::vector prop_hdr; + std::ofstream ext_out; + + size_t sizeof_coord; + + // Public methods and constructors + public: + + Writer() { init(); } + + template Writer (const std::string& location, + const U& template_or_reader, + std::map file_props = std::map()) + { init(); create(location, template_or_reader, file_props); } + + + template Writer (const std::string& location, + const U& template_or_reader, + const std::vector extend_prop_keys, + std::map file_props = std::map()) + { init(); create(location, template_or_reader, extend_prop_keys, file_props); } + + + template Writer (const std::string& location, + const std::vector& prop_keys, + const std::vector extend_prop_keys, + std::map file_props = std::map()) + { init(); create(location, prop_keys, extend_prop_keys, file_props); } + + + virtual ~Writer() + { close(); } + + + template void create (const std::string& location, + const U& template_or_reader, + std::map file_props = std::map()) + { create(location, Object::select_props(template_or_reader.prop_keys()), std::vector(), file_props); } + + + template void create (const std::string& location, + const U& template_or_reader, + const std::vector extend_prop_keys, + std::map file_props = std::map()) + { create(location, Object::select_props(template_or_reader.prop_keys()), std::vector(), file_props); } + + + void append (const T& fibre_object, std::map properties_row = std::map()); + + + void close () { + out.seekp (count_offset); + out << count << "\ntotal_count: " << total_count << "\nEND\n"; + out.close(); + ext_out.close(); + } + + + std::ofstream& get_out_stream() { return this->out; } + + off64_t get_count_offset() { return this->count_offset; } + + size_t get_count() { return this->count; } + + size_t get_total_count() { return this->total_count; } + + void override_count(size_t count) {this->count = count; } + + void override_total_count(size_t count) {this->total_count = count; } + + // Protected methods and constructors + protected: + +#ifdef FAST_READWRITE //Will inline writing file to avoid overhead call. However, this will remove the ability to write to text files (usually only used for debugging though). + void write (const Coord& coord); +#else + virtual void write (const Coord& coord); +#endif + +#ifdef FAST_READWRITE //Will inline writing file to avoid overhead call. However, this will remove the ability to write to text files (usually only used for debugging though). + Coord write_first (const Coord& coord); +#else + virtual Coord write_first (const Coord& coord); +#endif + + template void write (const U& fibre_object); + + template Coord write_first(const U& fibre_object); + + void increment_count() + { ++this->count; ++this->total_count; update_count(); } + + void append_file_seperator(); + + void update_count(); + + void check_properties_row(const std::map& properties_row); + + void append_extend_elem_props_row(std::map& properties_row); + + void append_extend_elem_props_row(const T& fibre_object, std::map& properties_row); + + static void write_properties_row( const std::vector& key_list, + std::map& properties_row, + std::ofstream& fout); + +#ifdef FAST_WRITE //Will inline writing file to avoid overhead call. However, this will remove the ability to write to text files. + void replace_end_of_file(const Coord& t, off64_t start_pos); +#else + virtual void replace_end_of_file(const Coord& t, off64_t start_pos); +#endif + + void init(); + + void create (const std::string& location, + const std::vector& prop_keys, + const std::vector extend_prop_keys, + std::map file_props); + + + friend class Set; + + }; + + + template class TextWriter : public Fibre::Base::Writer { + + //Public static variables, nested classes and typedefs + public: + + + TextWriter() {} + + template TextWriter (const std::string& location, + const U& template_or_reader, + std::map file_props = std::map()) + : Writer(location, template_or_reader, file_props) {} + + + template TextWriter (const std::string& location, + const U& template_or_reader, + const std::vector extend_prop_keys, + std::map file_props = std::map()) + : Writer(location, template_or_reader, extend_prop_keys, file_props) {} + + + void write (const Coord& coord); + + void replace_end_of_file(const Coord& c, off64_t start_pos) {} + + Coord write_first(const Coord& c) + { this->out.seekp((int)this->out.tellp() - 12); write (c); return c; } + + using Fibre::Base::Writer::write; + + + }; + + + } + + } + +} + +#include "bts/fibre/base/writer.cpp.h" + +#endif /* __bts_fibre_base_writer_h__ */ + + diff --git a/src/bts/fibre/properties/extended.cpp b/src/bts/fibre/properties/extended.cpp new file mode 100644 index 0000000..8d4a36d --- /dev/null +++ b/src/bts/fibre/properties/extended.cpp @@ -0,0 +1,322 @@ +/* + Copyright 2010 Brain Research Institute/National ICT Australia (NICTA), Melbourne, Australia + + Written by Thomas G Close, 04/06/2010. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + +*/ + + +//#include "bts/fibre/properties/extended.h" +// +//namespace BTS { +// +// namespace Fibre { +// +// const std::string Properties::Extended::FILE_PREAMBLE = "%%% Extended Properties File %%% - keys: "; +// +// +// void Properties::Extended::add_extend_elem_prop (const std::string& key, const std::string& default_value) { +// +// //If key is not already present. +// if (!key_index.count(key)) { +// +// key_index[key] = header.size(); +// header.push_back(key); +// default_values.push_back(default_value); +// +// values.push_back ( std::vector(num_rows(), default_value) ); +// +// } else +// default_values[key_index[key]] = default_value; +// +// } +// +// +// void Properties::Extended::add_extend_elem_props (const std::vector& header, const std::vector& default_values) { +// +// if (header.size() != default_values.size()) +// throw Exception ("Number of header (" + str(header.size()) + ") and default values (" + str(default_values.size()) + ") do not match"); +// +// for (size_t key_i = 0; key_i < header.size(); key_i++) +// add_extend_elem_prop(header[key_i], default_values[key_i]); +// +// } +// +// +// void Properties::Extended::remove_extend_elem_prop (const std::string& key) { +// +// if (key_index.count(key)) { +// +// size_t index = key_index[key]; +// +// header.erase(header.begin() + index); +// default_values.erase(default_values.begin() + index); +// values.erase(values.begin() + index); +// key_index.erase(key); +// +// } +// +// } +// +// +// std::string Properties::Extended::get_extend_elem_prop(std::string key, size_t row_index) const { +// +// check_key(key); +// check_row_index(row_index); +// +// size_t key_i = key_index.find(key)->second; +// +// //Can't use operator[] for key_index since 'this' is const. NB: Key is guaranteed to exist in 'key_index' from the 'check_key()' function. +// std::string value = values[key_i][row_index]; +// +// //FIXME: Doesn't need to be here just for debugging. +// std::string value_out = value + ""; +// +// return value_out; +// +// } +// +// +// void Properties::Extended::set_extend_elem_prop(std::string key, std::string value, size_t row_index) { +// +// check_key(key); +// check_row_index(row_index); +// +// values[key_index[key]][row_index] = value; +// +// } +// +// +// std::vector Properties::Extended::parse_line(const std::string& line) { +// +// std::istringstream line_stream(line); +// +// std::string value; +// std::vector values_row; +// +// while(std::getline(line_stream, value, '\t')) +// values_row.push_back(value); +// +// return values_row; +// +// } +// +// +// std::string Properties::Extended::make_line(const std::vector& values) { +// +// std::string line; +// +// std::ostringstream line_stream; +// +// for (std::vector::const_iterator it = values.begin(); it != values.end(); ++it) +// line_stream << it->c_str() << '\t'; +// +// line_stream << std::endl; +// +// return line_stream.str(); +// +// } +// +// +// +// void Properties::Extended::read_props_preamble(std::ifstream& file_in) { +// +// check_good(file_in); +// +// char file_intro[FILE_PREAMBLE.size()+2]; +// +// file_in.get(file_intro, FILE_PREAMBLE.size()+1); +// +// if (strcmp(file_intro, FILE_PREAMBLE.c_str())) +// throw Exception ("Required file intro '" + FILE_PREAMBLE + "' was not found at start of extended properties file (found '" + std::string(file_intro) +"' instead)."); +// +// } +// +// +// std::vector Properties::Extended::read_props_header(std::ifstream& file_in) { +// +// read_props_preamble(file_in); +// +// check_good(file_in); +// +// std::vector header; +// +// std::string key_line; +// +// if (!std::getline(file_in, key_line)) +// throw Exception ("No header found in extended properties file."); +// +// std::istringstream line_stream(key_line); +// +// std::string key; +// +// header.clear(); +// +// while(std::getline(line_stream, key, '\t')) +// header.push_back(key); +// +// return header; +// +// } +// +// +// void Properties::Extended::write_header(std::ofstream& out, const Header& header) { +// +// out << FILE_PREAMBLE; +// +// for (std::vector::const_iterator key_it = header.begin(); key_it != header.end(); key_it++) +// out << *key_it << '\t'; +// +// out << std::endl; +// +// } +// +// +// void Properties::Extended::load(std::string location) { +// +// clear(); +// +// std::ifstream in; +// in.open(location.c_str()); +// this->file_location = location; +// +// header = read_props_header(in); +// +// for (size_t key_i = 0; key_i < header.size(); key_i++) +// key_index[header[key_i]] = key_i; +// +// std::string line; +// +// while (std::getline(in, line)) +// add_row(parse_line(line)); +// +// +// file_location.clear(); +// +// +// } +// +// +// void Properties::Extended::save(std::string location) { +// +// std::ofstream out; +// +// out.open(location.c_str()); +// +// write_header(out, header); +// +// for (size_t row_i = 0; row_i < num_rows(); row_i++) { +// +// for (size_t key_i = 0; key_i < num_extend_elem_props(); key_i++) +// +// out << values[key_i][row_i] << '\t'; +// +// out << std::endl; +// +// } +// +// } +// +// +// Properties Properties::Extended::get_row(size_t row_index) const { +// +// Properties properties; +// +// for (size_t key_i = 0; key_i < header.size(); key_i++) { +// +// properties[header[key_i]] = values[key_i][row_index]; +// +// } +// +// return properties; +// +// } +// +// +// void Properties::Extended::add_row(const std::vector& values_row) { +// +// check_row_size(values_row); +// +// for (size_t key_i = 0; key_i < num_extend_elem_props(); key_i++) +// this->values[key_i].push_back(values_row[key_i]); +// +// nrows++; +// +// } +// +// +// void Properties::Extended::add_row(const Properties& properties) { +// +// std::vector row(header.size()); +// +// for (size_t key_i = 0; key_i < header.size(); key_i++) { +// +// Properties::const_iterator key_it = properties.find(header[key_i]); +// +// if (key_it == properties.end()) +// throw Exception ("Property '" + header[key_i] + "' not found in added properties row."); +// +// //Can't use operator[] for properties since properties are const. +// row[key_i] = key_it->second; +// +// } +// +// +// for (size_t key_i = 0; key_i < num_extend_elem_props(); key_i++) +// this->values[key_i].push_back(row[key_i]); +// +// nrows++; +// +// } +// +// +// void Properties::Extended::extend_rows(size_t new_num_rows) { +// +// for (size_t key_i = 0; key_i < num_extend_elem_props(); key_i++) { +// for (size_t row_count = num_rows(); row_count <= new_num_rows; row_count++) +// values[key_i].push_back(default_values[key_i]); +// } +// +// } +// +// +// void Properties::Extended::set_row(const Properties& properties, size_t row_index) { +// +// std::vector row(header.size()); +// +// for (size_t key_i = 0; key_i < header.size(); key_i++) { +// +// Properties::const_iterator key_it = properties.find(header[key_i]); +// +// if (key_it == properties.end()) +// throw Exception ("Property '" + header[key_i] + "' not found in added properties row."); +// +// //Can't use operator[] for properties since it is constant. +// row[key_i] = key_it->second; +// +// } +// +// for (size_t key_i = 0; key_i < num_extend_elem_props(); key_i++) +// this->values[key_i][row_index] = row[key_i]; +// +// } +// +// } +// +//} + diff --git a/src/bts/fibre/properties/extended.h b/src/bts/fibre/properties/extended.h new file mode 100644 index 0000000..a22f5d6 --- /dev/null +++ b/src/bts/fibre/properties/extended.h @@ -0,0 +1,210 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + +// +//#ifndef __bts_fibre_properties_extended_h__ +//#define __bts_fibre_properties_extended_h__ +// +//#include +//#include +//#include +//#include +// +//#include "bts/common.h" +// +//#include "bts/fibre/properties.h" +//#include "bts/fibre/properties/header.h" +// +//namespace BTS { +// +// namespace Fibre { +// +// class Properties::Extended { +// +// protected: +// +// Header header; +// std::vector default_values; +// std::vector< std::vector > values; +// +// //Used to locate the index of the property. +// std::map key_index; +// +// size_t nrows; +// +// //Used to temporarily store the file location for the printing of error messages. +// std::string file_location; +// +// public: +// +// const static std::string FILE_PREAMBLE; +// +// Extended() +// : nrows(0) {} +// +// +// Extended(const Extended& ep) +// : header(ep.header), default_values(ep.default_values), values(ep.values), key_index(ep.key_index), nrows(ep.nrows) {} +// +// +// Extended& operator= (const Extended& ep) +// { header = ep.header; default_values = ep.default_values; values = ep.values; key_index = ep.key_index; nrows = ep.nrows; return *this; } +// +// +// Extended& append(const Extended& ep) { +// +// if (!num_extend_elem_props()) +// this->operator=(ep); +// +// else { +// +// size_t num_props = num_extend_elem_props(); +// +// header.insert(header.end(), ep.header.begin(), ep.header.end()); +// default_values.insert(default_values.end(), ep.default_values.begin(), ep.default_values.end()); +// values.insert(values.end(), ep.values.begin(), ep.values.end()); +// +// for (size_t key_i = 0; key_i < ep.num_extend_elem_props(); key_i++) +// key_index[ep.header[key_i]] = num_props + key_i; +// +// } +// +// return *this; +// +// } +// +// size_t num_rows() const +// { return nrows; } +// +// +// size_t num_extend_elem_props() const +// { return header.size(); } +// +// +// void clear() +// { header.clear(); default_values.clear(); values.clear(); key_index.clear(); nrows = 0; } +// +// +// Header get_header() const +// { return header; } +// +// +// std::vector get_default_values () const +// { return default_values; } +// +// +// void add_extend_elem_prop (const std::string& key, const std::string& default_value); +// +// +// void add_extend_elem_props (const Header& header, const std::vector& default_values); +// +// +// void remove_extend_elem_prop(const std::string& key); +// +// +// std::string get_extend_elem_prop(std::string key, size_t row_index) const; +// +// +// template U get_extend_elem_prop(std::string key, size_t row_index) const +// { return to(get_extend_elem_prop(key,row_index)); } +// +// +// Properties get_row(size_t row_index) const; +// +// +// void set_extend_elem_prop(std::string key, std::string value, size_t row_index); +// +// +// void set_row(const Properties& properties, size_t row_index); +// +// +// bool has_extend_elem_prop(const std::string& key) const +// { return key_index.count(key); } +// +// +// void add_row() +// { for (size_t key_i = 0; key_i < num_extend_elem_props(); key_i++) values[key_i].push_back(default_values[key_i]); nrows++; } +// +// void erase_row(size_t index) +// { for (size_t key_i = 0; key_i < num_extend_elem_props(); key_i++) values[key_i].erase(values[key_i].begin() + index); } +// +// +// void add_row(const Properties& properties); +// +// +// void extend_rows(size_t num_rows); +// +// +// void load(std::string location); +// +// +// void save(std::string location); +// +// +// static std::vector parse_line(const std::string& line); +// +// +// static std::string make_line(const std::vector& values); +// +// +// static Header read_props_header(std::ifstream& line); +// +// +// static void write_header(std::ofstream& out, const Header& header); +// +// +// +// protected: +// +// void check_key (const std::string& key) const +// { if (!key_index.count(key)) throw Exception ("Property '" + key + "' was not found."); } +// +// +// void check_row_index (size_t row_index) const +// { if (row_index >= num_rows()) throw Exception ("Properties row index '" + str(row_index) + "' out of range (" + str(num_rows()) + ")."); } +// +// +// void check_row_size(const std::vector& row) +// { if (row.size() >= num_extend_elem_props()) throw Exception ("Size of new row (" + str(row.size()) + ") does not match number of properties (" + str(num_extend_elem_props()) +")."); } +// +// +// static void check_good(std::ifstream& in) +// { if (!in.good()) throw Exception ("Could not read from properties file."); } +// +// +// static void read_props_preamble(std::ifstream& in); +// +// +// void add_row(const std::vector& values_row); +// +// +// +// }; +// +// +// +// } +//} +// +//#include "bts/fibre/properties/header.h" +// +//#endif /* __bts_fibre_properties_extended_h__ */ diff --git a/src/bts/fibre/properties/header.cpp.h b/src/bts/fibre/properties/header.cpp.h new file mode 100644 index 0000000..10e1c1e --- /dev/null +++ b/src/bts/fibre/properties/header.cpp.h @@ -0,0 +1,52 @@ +/* + Copyright 2010 Brain Research Institute/National ICT Australia (NICTA), Melbourne, Australia + + Written by Thomas G Close, 07/06/2010. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + +*/ +// +//#ifndef __bts_fibre_properties_header_cpp_h__ +//#define __bts_fibre_properties_header_cpp_h__ +// +//#include "bts/fibre/properties/header.h" +// +//namespace BTS { +// +// namespace Fibre { +// +// inline bool std::vector::remove_key(const std::string& key) { +// +// std::vector::iterator key_it = std::find(begin(), end(), key); +// +// bool found; +// +// if (key_it == end()) +// found = false; +// else { +// erase(key_it); +// found = true; +// } +// +// return found; +// +// } +// +// } +//} +// +//#endif diff --git a/src/bts/fibre/properties/header.h b/src/bts/fibre/properties/header.h new file mode 100644 index 0000000..2473947 --- /dev/null +++ b/src/bts/fibre/properties/header.h @@ -0,0 +1,59 @@ +/* + Copyright 2010 Brain Research Institute/National ICT Australia (NICTA), Melbourne, Australia + + Written by Thomas G Close, 04/06/2010. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + +*/ +// +//#ifndef __bts_fibre_properties_header_h__ +//#define __bts_fibre_properties_header_h__ +// +//#include "bts/fibre/properties/extended.h" +// +//namespace BTS { +// +// namespace Fibre { +// +// class std::vector : public std::vector { +// +// +// //Public member functions +// public: +// +// Header() {} +// +// Header(const std::vector& header) : std::vector(header) {} +// +// ~Header() {} +// +// Header& operator=(const std::vector& header) +// { std::vector::operator=(header); return *this; } +// +// +//// //Protected member functions +//// protected: +// +// bool remove_key(const std::string& key); +// +// }; +// +// +// } +//} +// +//#endif /* __bts_fibre_properties_header_h__ */ diff --git a/src/bts/fibre/strand.cpp b/src/bts/fibre/strand.cpp new file mode 100644 index 0000000..b10233a --- /dev/null +++ b/src/bts/fibre/strand.cpp @@ -0,0 +1,753 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, 07/08/2010. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + +#include "math/matrix.h" +#include "math/least_squares.h" + +#include "bts/math/odr.h" +#include "bts/fibre/track.h" +#include "bts/fibre/tractlet.h" +#include "bts/fibre/strand/section.h" + +namespace BTS { + + namespace Fibre { + + const Coord Strand::FILE_SEPARATOR = Triple (NAN, NAN, NAN); + + const char* Strand::PROPS_LIST[] = { Object::ACS_SQRT_PROP, PROPS_LIST_END }; + + const std::string Strand::FILE_EXTENSION = "str"; + const size_t Strand::DEFAULT_DEGREE = 3; + + + std::map< size_t, std::map< size_t, MR::Math::Matrix > > Strand::position_matrices; + std::map< size_t, std::map< size_t, MR::Math::Matrix > > Strand::position_matrices_w_endpoints; + std::map< size_t, std::map< size_t, MR::Math::Matrix > > Strand::tangent_matrices; + std::map< size_t, std::map< size_t, MR::Math::Matrix > > Strand::inverse_position_matrices; + std::map< size_t, std::map< size_t, MR::Math::Matrix > > Strand::tangent_matrices_w_endpoints; + std::map< size_t, std::map< size_t, MR::Math::Matrix > > Strand::inverse_position_matrices_w_endpoints; + + const double MERGE_FUDGE_FACTOR = 1.2; + + + Strand::Strand(const Track& t, size_t degree) + : Base::Object (degree, (size_t)3, select_props(*t.props)) { + + size_t effective_degree = degree; + + if (t.num_points() < degree) + effective_degree = t.num_points(); + + const MR::Math::Matrix& inverse_position_matrix = Strand::inverse_position_matrix(t.num_points(), effective_degree); + + for (size_t degree_i = 0; degree_i < effective_degree; ++degree_i) + operator[](degree_i) = t.left_product(inverse_position_matrix.row(degree_i)); + + for (size_t degree_i = effective_degree; degree_i < degree; ++degree_i) + operator[](degree_i).zero(); + + for (size_t prop_i = 0; prop_i < num_props(); ++prop_i) + prop(prop_i) = t.prop(prop_key(prop_i)); + + } + + + Strand::Strand(const Track& t, size_t degree, const std::vector& timeline) + : Base::Object (degree, (size_t)3, select_props(*t.props)) { + + size_t effective_degree = degree; + + if (t.num_points() < degree) + effective_degree = t.num_points(); + + MR::Math::Matrix inverse_position_matrix = Strand::create_inverse_position_matrix(timeline, effective_degree); + + for (size_t degree_i = 0; degree_i < effective_degree; degree_i++) + operator[](degree_i) = t.left_product(inverse_position_matrix.row(degree_i)); + + for (size_t degree_i = effective_degree; degree_i < degree; ++degree_i) + operator[](degree_i).zero(); + + for (size_t prop_i = 0; prop_i < num_props(); ++prop_i) + prop(prop_i) = t.prop(prop_key(prop_i)); + + } + + + + //Projects extends or trims the strand so that its endpoints lie on the sphere. + void Strand::project_to_sphere(double sphere_radius) { + + Track tck = this->to_track(this->degree()); + + + tck[0].normalise(); + tck[0] *= sphere_radius; + tck[tck.size() - 1].normalise(); + tck[tck.size() - 1] *= sphere_radius; + + *this = tck.to_strand(this->degree()); + + + } + + + + Track Strand::to_track(size_t num_points, bool include_endpoints) const { + return Track(*this, num_points, include_endpoints); + } + + Track Strand::to_tangents(size_t num_points, bool include_endpoints) const { + + if (num_points == 0) + throw Exception ("'num_points' option is required for conversion to tracks."); + + Track tck(num_points); + const MR::Math::Matrix& position_matrix = Strand::tangent_matrix(num_points, degree()); + + for (size_t point_i = 0; point_i < num_points; point_i++) + tck[point_i] = left_product(position_matrix.row(point_i)); + + return tck; + + } + + //! Flips the strand so that runs in the opposite direction but the path taken is the same. + Strand Strand::flip() const { + + Strand s(*this); + + for (size_t degree_i = 1; degree_i < degree(); degree_i += 2) + s[degree_i] = - operator[](degree_i); + + return s; + + } + + + Strand& Strand::operator+= (const Strand& s) { + + assert(props_match(s)); + + if (size() == s.size()) + + MR::Math::Vector::operator+=(s); + + else if (size() <= s.size()) { + + resize(s.degree(),0.0); + + MR::Math::Vector::operator+=(s); + + } else { + + for (size_t degree_i = 0; degree_i < s.size(); ++degree_i) + operator[](degree_i) += s[degree_i]; + + for (size_t prop_i = 0; prop_i < num_props(); ++prop_i) + prop(prop_i) += s.prop(prop_i); + + } + + return *this; + + } + + + Strand& Strand::operator-= (const Strand& s) { + + assert(props_match(s)); + + if (size() == s.size()) + + MR::Math::Vector::operator-=(s); + + else if (size() <= s.size()) { + + resize(s.degree(),0.0); + + MR::Math::Vector::operator-=(s); + + } else { + + for (size_t degree_i = 0; degree_i < s.size(); ++degree_i) + operator[](degree_i) -= s[degree_i]; + + for (size_t prop_i = 0; prop_i < num_props(); ++prop_i) + prop(prop_i) -= s.prop(prop_i); + + } + + return *this; + + } + + + Strand Strand::outer_product(const MR::Math::Vector& column_vector, const Coord& row) { + + Strand strand(column_vector.size()); + + for (size_t row_i = 0; row_i < column_vector.size(); row_i++) + strand[row_i] = column_vector[row_i] * row; + + return strand; + + } + + + Strand Strand::merge(const Strand& strand, size_t num_sections, size_t new_degree) const { + + std::vector to_merge; + + to_merge.push_back(this); + + to_merge.push_back(&strand); + + return merge(to_merge, num_sections, new_degree); + + } + + + //!Generates, stores and returns position conversion matrices when required. + const MR::Math::Matrix& Strand::position_matrix(size_t num_sections, size_t degree, bool include_endpoints) { + + assert(num_sections != 0); + assert(degree != 0); + + + if (include_endpoints) { + + MR::Math::Matrix& position_matrix = Strand::position_matrices_w_endpoints[num_sections][degree]; + + if (position_matrix.rows()) + return position_matrix; + else + return position_matrix = Strand::create_position_matrix(degree, num_sections, INCLUDE_ENDPOINTS); + //TODO: Change dont_include_endpoints to enum. + + } else { + + MR::Math::Matrix& position_matrix = Strand::position_matrices[num_sections][degree]; + + if (position_matrix.rows()) + return position_matrix; + else + return position_matrix = Strand::create_position_matrix(degree, num_sections, DONT_INCLUDE_ENDPOINTS); + + } + + } + + //!Generates, stores and returns position conversion matrices when required. + const MR::Math::Matrix& Strand::tangent_matrix(size_t num_sections, size_t degree) { + + assert(num_sections != 0); + assert(degree != 0); + + MR::Math::Matrix& tangent_matrix = Strand::tangent_matrices[num_sections][degree]; + + if (tangent_matrix.rows()) + return tangent_matrix; + else + return tangent_matrix = Strand::create_tangent_matrix(degree, num_sections, DONT_INCLUDE_ENDPOINTS); + + } + + + + //!Generates, stores and returns position conversion matrices when required. + const MR::Math::Matrix& Strand::inverse_position_matrix(size_t num_sections, size_t degree) { + + assert(num_sections != 0); + assert(degree != 0); + + MR::Math::Matrix& position_matrix = Strand::inverse_position_matrices[degree][num_sections]; + + if (position_matrix.rows()) + return position_matrix; + else + return position_matrix = Strand::create_inverse_position_matrix(num_sections, degree, DONT_INCLUDE_ENDPOINTS); + + } + + + //!Generates, stores and returns position conversion matrices when required. + const MR::Math::Matrix& Strand::position_matrix_w_endpoints(size_t num_sections, size_t degree) { + + assert(num_sections != 0); + assert(degree != 0); + + MR::Math::Matrix& position_matrix = Strand::position_matrices_w_endpoints[num_sections][degree]; + + if (position_matrix.rows()) + return position_matrix; + else + return position_matrix = Strand::create_position_matrix(degree, num_sections, INCLUDE_ENDPOINTS); + + } + + + //Generates, stores and returns position conversion matrices_w_endpoints when required. + const MR::Math::Matrix& Strand::tangent_matrix_w_endpoints(size_t num_sections, size_t degree) { + + assert(num_sections != 0); + assert(degree != 0); + + MR::Math::Matrix& tangent_matrix = Strand::tangent_matrices_w_endpoints[num_sections][degree]; + + if (tangent_matrix.rows()) + return tangent_matrix; + else + return tangent_matrix = Strand::create_tangent_matrix(degree, num_sections, INCLUDE_ENDPOINTS); + } + + + //Generates, stores and returns position conversion matrices_w_endpoints when required. + const MR::Math::Matrix& Strand::inverse_position_matrix_w_endpoints(size_t num_sections, size_t degree) { + + assert(num_sections != 0); + assert(degree != 0); + + MR::Math::Matrix& position_matrix = Strand::inverse_position_matrices_w_endpoints[degree][num_sections]; + + if (position_matrix.rows()) + return position_matrix; + else + return position_matrix = Strand::create_inverse_position_matrix(num_sections, degree, INCLUDE_ENDPOINTS); + + } + + + void Strand::add_section_gradient(const Strand& strand, const Section& section, const BasicSection& gradient) { + + this->operator+=(outer_product(section.position_coeffs, gradient.position())); + this->operator+= (outer_product(section.tangent_coeffs, gradient.tangent() * section.length_fraction)); + + if (has_var_acs()) + var_acs() += gradient.intensity(); + + } + + + std::vector& Strand::sections(std::vector& sections, size_t num_length_sections, size_t num_width_sections, const Triple& vox_lengths, const Triple& offsets, size_t num_encodings) const { + + sections.resize(num_length_sections, Strand::Section(num_encodings)); + + double length_fraction = 1.0 / num_length_sections; + + const MR::Math::Matrix& position_matrix = Strand::position_matrix(num_length_sections, this->degree()); + const MR::Math::Matrix& tangent_matrix = Strand::tangent_matrix(num_length_sections, this->degree()); + + for (size_t section_i = 0; section_i < num_length_sections; section_i++) { + sections[section_i].set(*this, position_matrix.row(section_i), tangent_matrix.row(section_i), length_fraction); + sections[section_i].normalize(vox_lengths, offsets); + } + + return sections; + + } + + + + + + // Used to convert Strand descriptors to a path of points + MR::Math::Matrix Strand::create_position_matrix(size_t degree, size_t num_sections, bool include_endpoints) { + + if (!degree) + throw Exception("The degree (" + str(degree) + ") cannot be 0."); + + if (!num_sections) + throw Exception("The size of the number of length samples (" + str(num_sections) + ") cannot be 0."); + + MR::Math::Matrix Psi(num_sections, degree); + + double t_incr; + + if (include_endpoints) + t_incr = 1.0 / (double)(num_sections-1); + else + t_incr = 1.0 / (double)(num_sections+1); + + for (size_t row_i = 0; row_i < num_sections; row_i++) { + Psi(row_i, 0) = 1.0; + } + + for (size_t degree_i = 1; degree_i < degree; degree_i++) { + + double t; + if (include_endpoints) + t = 0.0; + else + t = t_incr; + + for (size_t row_i = 0; row_i < num_sections; row_i++) { + + Psi(row_i, degree_i) = M_SQRT2 * cos (degree_i * M_PI * t); + t += t_incr; + } + + } + + return Psi; + + + } + + + // Generate conversion matrix to convert Strand descriptors to path points from arbitrary 'time' points. + MR::Math::Matrix Strand::create_position_matrix(size_t degree, const std::vector& timeline) { + + if (degree == 0 || timeline.size() == 0) + throw Exception("The degree (" + str(degree) + ") or the size of the timeline vector (" + str(timeline.size()) + ") cannot be 0."); + + size_t num_sections = timeline.size(); + + MR::Math::Matrix Psi(num_sections, degree); + + for (size_t row_i = 0; row_i < num_sections; row_i++) { + Psi(row_i, 0) = 1.0; + } + + for (size_t degree_i = 1; degree_i < degree; degree_i++) { + + for (size_t row_i = 0; row_i < num_sections; row_i++) { + Psi(row_i, degree_i) = M_SQRT2 * cos (degree_i * M_PI * timeline[row_i]); + } + + } + + return Psi; + + + + } + + + //Used to convert a path of points to Strand descriptors + MR::Math::Matrix Strand::create_inverse_position_matrix(size_t num_sections, size_t degree, bool include_endpoints) { + + MR::Math::Matrix Psi = Strand::create_position_matrix(degree, num_sections, include_endpoints); + + MR::Math::Matrix inv_Psi(degree, num_sections); + + MR::Math::pinv(inv_Psi, Psi); + + return inv_Psi; + + } + + + MR::Math::Matrix Strand::create_inverse_position_matrix(const std::vector& timeline, size_t degree) { + + MR::Math::Matrix Psi = Strand::create_position_matrix(degree, timeline); + + MR::Math::Matrix inv_Psi(degree, timeline.size()); + + MR::Math::pinv(inv_Psi, Psi); + + return inv_Psi; + + } + + + // Used to get the parameterization gradient at the points along the strand. + MR::Math::Matrix Strand::create_tangent_matrix(size_t degree, size_t num_sections, bool include_endpoints) { + + + MR::Math::Matrix d_Psi(num_sections, degree); + + double t_incr; + + if (include_endpoints) + t_incr = 1.0 / (double)(num_sections-1); + else + t_incr = 1.0 / (double)(num_sections+1); + + + for (size_t row_i = 0; row_i < num_sections; row_i++) { + d_Psi(row_i, 0) = 0.0; + } + + for (size_t degree_i = 1; degree_i < degree; degree_i++) { + + double t; + if (include_endpoints) + t = 0.0; + else + t = t_incr; + + for (size_t row_i = 0; row_i < num_sections; row_i++) { + + d_Psi(row_i, degree_i) = - M_SQRT2 * M_PI * degree_i * sin (degree_i * M_PI * t); + t += t_incr; + } + + } + + return d_Psi; + + + } + + + + // Gets the endpoints of the strand. + std::pair Strand::endpoints() const { + + std::pair endpoints; + + endpoints.first = operator[](0); + endpoints.second = operator[](0); + + for (size_t odd_i = 1; odd_i < degree(); odd_i += 2) { + endpoints.first += operator[](odd_i) * M_SQRT2; + endpoints.second -= operator[](odd_i) * M_SQRT2; + } + + + for (size_t even_i = 2; even_i < degree(); even_i += 2) { + endpoints.first += operator[](even_i) * M_SQRT2; + endpoints.second += operator[](even_i) * M_SQRT2; + } + + + return endpoints; + + } + + + // Get the gradient of the endpoints of the strand. Note that the gradient is the same for X, Y, & Z and each + // dimension is only related to its corresponding fourier coefficient so a vector is sufficient to capture the + // relationships between every Fourier coefficient and the each endpoint. + std::pair< MR::Math::Vector, MR::Math::Vector > Strand::endpoint_coeffs() const { + + std::pair< MR::Math::Vector, MR::Math::Vector > endpoints_gradient (MR::Math::Vector(this->degree()),MR::Math::Vector(this->degree())); + + endpoints_gradient.first[0] = 1.0; + endpoints_gradient.second[0] = 1.0; + + for (size_t odd_i = 1; odd_i < degree(); odd_i += 2) { + endpoints_gradient.first[odd_i] = M_SQRT2; + endpoints_gradient.second[odd_i] = - M_SQRT2; + } + + + for (size_t even_i = 2; even_i < degree(); even_i += 2) { + endpoints_gradient.first[even_i] = M_SQRT2; + endpoints_gradient.second[even_i] = M_SQRT2; + } + + + return endpoints_gradient; + + } + + + // Gets the midpoint of the strand, which is the sum of even vectors. + Coord Strand::midpoint() const { + + Coord midpoint = operator[](0); + + for (size_t degree_i = 2; degree_i < degree(); degree_i += 4) + midpoint -= (double)M_SQRT2 * operator[](degree_i); + + for (size_t degree_i = 4; degree_i < degree(); degree_i += 4) + midpoint += (double)M_SQRT2 * operator[](degree_i); + + return midpoint; + + } + + + // Get the gradient of the midpoint of the strand. Note that the gradient is the same for X, Y, & Z and each + // dimension is only related to its corresponding Fourier coefficient so a vector is sufficient to capture the + // relationships between every Fourier coefficient and the midpoint. + MR::Math::Vector Strand::midpoint_gradient() const { + + MR::Math::Vector gradient (this->degree()); + + gradient.zero(); + + gradient[0] = 1.0; + + for (size_t degree_i = 2; degree_i < this->degree(); degree_i += 4) + gradient[degree_i] = -M_SQRT2; + + for (size_t degree_i = 4; degree_i < this->degree(); degree_i += 4) + gradient[degree_i] = M_SQRT2; + + + return gradient; + } + + + + + + //Gets the squared distance between this strand and the reference strand. Due to the Strand descriptor + //parameterization being orthonormal, by Parseval's theorem it corresponds to the distance between identically-spaced + //trains of path points along each strand. + double Strand::distance(const Strand& reference, bool& flipped) const { + + double dist = MR::Math::sqrt((*this - reference).norm2()); + double flipped_dist = MR::Math::sqrt((*this - reference.flip()).norm2()); + + if (flipped_dist < dist) { + dist = flipped_dist; + flipped = true; + } else + flipped = false; + + return dist; + + } + + + Strand Strand::smallest_distance_set(const Strand& reference) const { + + bool flipped; + + distance(reference,flipped); + + Strand s (*this); + + if (flipped) + s = s.flip(); + + return s; + + } + + + // Join two strands together into one longer strand of degree 'new_degree'. If new_degree = 0 or is not specified it defaults to + // the maximum degree of the strands + 1. + Strand Strand::merge(std::vector& strands, size_t num_points, size_t new_degree) { + + + + std::vector landmarks; + landmarks.reserve(strands.size() * 3); + + size_t max_degree = 0; + + double avg_acs = 0; + + for (size_t strand_i = 0; strand_i < strands.size(); strand_i++) { + + const Strand& strand = *strands[strand_i]; + + std::pair e_points = strand.endpoints(); + + + Track tcks = strand.to_track(num_points, INCLUDE_ENDPOINTS); + + for (size_t tck_i = 0; tck_i < tcks.size(); ++tck_i) + landmarks.push_back(tcks[tck_i]); + + + if (strand.degree() > max_degree) + max_degree = strand.degree(); + + avg_acs += strand.acs(); + } + + avg_acs /= (double)strands.size(); + + if (new_degree == 0) + new_degree = max_degree + strands.size() - 1; + + + // Get the orthogonal-distance regressor line between the path landmarks. + Math::Line odr_line = Math::odr(landmarks); + + Track complete_tck(num_points * strands.size()); + + std::vector timeline; + timeline.reserve(sizeof(double) * num_points * strands.size()); + + + double min_cos_time = INFINITY; + double max_cos_time = -INFINITY; + + for (size_t strand_i = 0; strand_i < strands.size(); strand_i++) { + + Track tck = strands[strand_i]->to_track(num_points, INCLUDE_ENDPOINTS); + + for (size_t point_i = 0; point_i < num_points; point_i++) { + + Coord point = tck[point_i]; + Coord disp = point - odr_line.centre; + double cos_time = odr_line.direction.dot(disp); + + complete_tck[strand_i * num_points + point_i] = point; + timeline.push_back(cos_time); + + if (cos_time > max_cos_time) + max_cos_time = cos_time; + + if (cos_time < min_cos_time) + min_cos_time = cos_time; + + } + + + } + + + double cos_time_range = max_cos_time - min_cos_time; + + for (size_t time_i = 0; time_i < timeline.size(); time_i++) + timeline[time_i] = (MR::Math::cos((timeline[time_i] - min_cos_time) * (M_PI / cos_time_range)) + 1) * 0.5; + + Strand new_strand = complete_tck.to_strand(new_degree, timeline); + + if (strands[0]->has_var_acs()) + new_strand.set_acs(avg_acs); + + new_strand[1] *= MERGE_FUDGE_FACTOR; + + return new_strand; + + } + + + + std::ostream& operator<< (std::ostream& stream, const Strand& strand) { + + stream << std::endl; + + if (strand.has_var_acs()) + stream << "acs: " << strand.acs() << std::endl; + + for (size_t degree_i = 0; degree_i < strand.degree(); degree_i++) { + stream << strand[degree_i] << std::endl; + } + return (stream); + + } + + + } + +} diff --git a/src/bts/fibre/strand.h b/src/bts/fibre/strand.h new file mode 100644 index 0000000..5d4e01f --- /dev/null +++ b/src/bts/fibre/strand.h @@ -0,0 +1,294 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, 07/08/2010. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + + +#ifndef __bts_fibre_strand_h__ +#define __bts_fibre_strand_h__ + +#include "bts/fibre/base/object.h" +#include "bts/coord.h" + + +#include "bts/fibre/base/writer.h" +#include "bts/fibre/base/reader.h" + +namespace BTS { + + namespace Fibre { + + class Strand : public Base::Object { + + //Public nested classes and typedefs + public: + + typedef Coord Element; + + class BasicSection; + class Section; + class Set; + class Tensor; + class Walker; + + typedef Base::Writer Writer; + typedef Base::Reader Reader; + + typedef Base::TextWriter TextWriter; + typedef Base::TextReader TextReader; + + friend class Track; + friend class Tractlet; + friend class Set; + friend class Base::Set; + friend class Tensor; + friend class Base::Tensor; + + //Public static constants + public: + + const static std::string FILE_EXTENSION; + const static Coord FILE_SEPARATOR; + + const static int INCLUDE_ENDPOINTS = 1; + const static int DONT_INCLUDE_ENDPOINTS = 0; + + const static size_t DEFAULT_DEGREE; + + const static char* PROPS_LIST[]; + + + //Public static variables + public: + + static std::map > > position_matrices; + static std::map > > tangent_matrices; + static std::map > > inverse_position_matrices; + + static std::map > > position_matrices_w_endpoints; + static std::map > > tangent_matrices_w_endpoints; + static std::map > > inverse_position_matrices_w_endpoints; + + //Public static methods. + public: + + // Generate conversion matrix to convert Strand descriptors to path points. + static MR::Math::Matrix create_position_matrix(size_t degree, size_t num_sections, bool include_endpoints = INCLUDE_ENDPOINTS); + // Generate conversion matrix to convert Strand descriptors to path points from arbitrary 'time' points. + static MR::Math::Matrix create_position_matrix(size_t degree, const std::vector& timeline); + // Generate conversion matrix to convert Strand descriptors to the tangents of the strand at the path points. + static MR::Math::Matrix create_tangent_matrix(size_t degree, size_t num_sections, bool include_endpoints = INCLUDE_ENDPOINTS); + static MR::Math::Matrix create_inverse_position_matrix(size_t num_sections, size_t degree, bool include_endpoints = INCLUDE_ENDPOINTS); + static MR::Math::Matrix create_inverse_position_matrix(const std::vector& timeline, size_t degree); + + static const MR::Math::Matrix& position_matrix (size_t num_sections, size_t degree, bool include_endpoints = DONT_INCLUDE_ENDPOINTS); + static const MR::Math::Matrix& tangent_matrix (size_t num_sections, size_t degree); + static const MR::Math::Matrix& inverse_position_matrix (size_t num_sections, size_t degree); + + static const MR::Math::Matrix& position_matrix_w_endpoints (size_t num_sections, size_t degree); + static const MR::Math::Matrix& tangent_matrix_w_endpoints (size_t num_sections, size_t degree); + static const MR::Math::Matrix& inverse_position_matrix_w_endpoints (size_t num_sections, size_t degree); + + static Strand outer_product(const MR::Math::Vector& column_vector, const Coord& coord); + + //Public methods + public: + + Strand (size_t degree = 0, const std::vector& props = std::vector()) + : Base::Object(degree, degree * 3 + props.size(), props) {} + + + Strand (int degree, double default_value, const std::vector& props = std::vector()) + : Base::Object(degree, degree * 3 + props.size(), props) { set(default_value); } + + + Strand (const Strand& s) + : Base::Object(s) {} + + + ~Strand () {} + + + Strand base() + { return Strand(sze, sub(0,bsize()), &EMPTY_PROPS); } + + const Strand base() const + { return Strand(sze, sub(0,bsize()), &EMPTY_PROPS); } + + Strand& operator=(const Strand& strand) + { Base::Object::operator=(strand); return *this; } + + // Strand (int degree, const Coord& default_value, const std::vector& props = std::vector()) + // : Base::Object(degree, (size_t)3, props) { set(default_value); } + + + Strand(const Track& t, size_t degree); + + + Strand(const Track& t, size_t degree, const std::vector& timeline); + + + protected: + + /*! Used by Base::Set::operator[]() to initiate a from a section of a larger state vector or + * by Base::Tensor::row/column() for a slice of the tensor matrix + * + * @param degree Degree of the strand + * @param view The view onto the larger vector or matrix + * @param props The properties stored in the set or tensor + */ + Strand(size_t degree, const MR::Math::Vector::View& view, std::vector* props) + : Base::Object(degree, view, props) {} + + + public: + + + size_t degree() const + { return size(); }; + + + double acs() const + { return has_prop(ACS_SQRT_PROP) ? MR::Math::pow2(prop(ACS_SQRT_PROP)) : 1.0; /* The ACS is stored in the state vector via its squareroot to prevent it from becoming < 0 */} + + + void add_acs(double acs = 1.0) + { add_prop(ACS_SQRT_PROP, acs); } + + + void set_acs(double acs) + { assert(acs >= 0); prop(ACS_SQRT_PROP) = MR::Math::sqrt(acs); } + + + void remove_acs() + { remove_prop(ACS_SQRT_PROP); } + + + bool has_var_acs() const + { return has_prop(ACS_SQRT_PROP); } + + + double& var_acs() + { assert(has_var_acs()); return prop(ACS_SQRT_PROP); } + + + BASE_GENERAL_FUNCTIONS(Strand); + + + BASE_MULT_DIVIDE_FUNCTIONS(Strand); + + + //Conversion methods. + Track to_track(size_t num_points, bool include_endpoints = DONT_INCLUDE_ENDPOINTS) const; + + Track to_tangents(size_t num_points, bool include_endpoints = DONT_INCLUDE_ENDPOINTS) const; + + + //Projects extends or trims the strand so that its endpoints lie on the sphere. + void project_to_sphere(double sphere_radius); + + + //! Flips the strand so that runs in the opposite direction but the path taken is the same. + Strand flip() const; + + + Strand& operator+=(const Strand& s); + + + Strand& operator-=(const Strand& s); + + + Strand operator+(const Strand& s) const + { Strand answer(*this); answer += s; return answer; } + + + Strand operator-(const Strand& s) const + { Strand answer(*this); answer -= s; return answer; } + + + Tractlet to_tractlet(double width) const; + + + /*!Split strand in to many 'Strand::Sections'. Note num_width_sections is ignored and is only included to get a template + * function to work.*/ + std::vector
& sections(std::vector
& sections, size_t num_length_sections, size_t num_width_sections = 0, const Triple& vox_lengths = Triple::Ones, const Triple& offsets = Triple::Zeros, size_t num_encodings = 0) const; + + //Calculates the contribution of the section gradient back to the original strand's gradient. + void add_section_gradient( const Strand& strand, + const Section& section, + const BasicSection& gradient); + + // Get the endpoints of the strand. + std::pair endpoints() const; + + + /*! Get the gradient of the endpoints of the strand. Note that the gradient is the same for X, Y, & Z and each + * dimension is only related to its corresponding fourier coefficient so a vector is sufficient to capture the + * relationships between every Fourier coefficient and the each endpoint. */ + std::pair< MR::Math::Vector, MR::Math::Vector > endpoint_coeffs() const; + + // Gets the point at the top of the 'arc', which is just the sum of even vectors. + Coord midpoint() const; + + /*! Get the gradient of the midpoint of the strand. Note that the gradient is the same for X, Y, & Z and each + * dimension is only related to its corresponding fourier coefficient so a vector is sufficient to capture the + * relationships between every Fourier coefficient and the midpoint.*/ + MR::Math::Vector midpoint_gradient() const; + + + //FIXME: Need to sort out the names of these functions. + double distance(const Strand& reference, bool& flipped) const; + + + double distance(const Strand& reference, double dummy = 0) const + { bool flipped; return distance(reference, flipped); } + + + Strand smallest_distance_set(const Strand& reference) const; + + + // Join two strands together into one longer strand of degree 'new_degree'. If new_degree = 0 or is not specified it defaults to + // the maximum degree of the strands + 1. + static Strand merge(std::vector& strands, size_t num_sections, size_t new_degree = 0); + + + Strand merge(const Strand& strand, size_t num_sections, size_t new_degree = 0) const; + + + //! Return a MR::Math::Matrix window to the underlying state vector interpreted as a matrix (without properties). + MR::Math::Matrix bmatrix() + { return Base::Object::bmatrix(3); } + + + std::vector cross_sectional_areas(size_t num_points) + { throw Exception ("Should not be used, just added to debug template function with tractlets."); } + + }; + + + std::ostream& operator<< (std::ostream& stream, const Strand& strand); + + } + +} + +#undef LOOP + +#endif /* __bts_fibre_strand_h__ */ diff --git a/src/bts/fibre/strand/basic_section.cpp b/src/bts/fibre/strand/basic_section.cpp new file mode 100644 index 0000000..c8f9f99 --- /dev/null +++ b/src/bts/fibre/strand/basic_section.cpp @@ -0,0 +1,51 @@ +/* + * Copyright 2010 Brain Research Institute/National ICT Australia (NICTA), Melbourne, Australia + * + * Written by Thomas G Close, 5/05/09. + * + * This file is part of Bayesian Tractlet Sampling (BTS). + * + * BTS 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. + * + * BTS 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 BTS. If not, see . + * + */ + + +#include "bts/fibre/strand.h" +#include "bts/fibre/strand/basic_section.h" + + + +namespace BTS { + + namespace Fibre { + + + const char* Strand::BasicSection::INTENSITY_PROP = "intensity"; + const char* Strand::BasicSection::PROPS_LIST[] = { Strand::BasicSection::INTENSITY_PROP, PROPS_LIST_END}; + const std::vector Strand::BasicSection::PROPS (&(PROPS_LIST[0]), &(PROPS_LIST[1])); + + std::ostream& operator<< (std::ostream& stream , const BTS::Fibre::Strand::BasicSection& seg) { + + stream << "position: " << seg.position() << std::endl; + stream << "tangent: " << seg.tangent() << std::endl; + stream << "intensity: " << seg.intensity() << std::endl; + + + return (stream); + + } + + } + +} diff --git a/src/bts/fibre/strand/basic_section.h b/src/bts/fibre/strand/basic_section.h new file mode 100644 index 0000000..267474e --- /dev/null +++ b/src/bts/fibre/strand/basic_section.h @@ -0,0 +1,196 @@ +/* + Copyright 2010 Brain Research Institute/National ICT Australia (NICTA), Melbourne, Australia + + Written by Thomas G Close, 5/05/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + +*/ + + + +#ifndef __bts_fibre_strand_basicsection_h__ +#define __bts_fibre_strand_basicsection_h__ + +#include +#include +#include + +#include "bts/triple.h" + +#include "bts/fibre/base/object.h" +#include "bts/fibre/strand.h" + +namespace BTS { + + namespace Fibre { + + class Strand::BasicSection : public Base::Object { + + public: + + class Tensor; + friend class Tensor; + + typedef Coord Element; + typedef Fibre::Base::Reader Reader; + typedef Fibre::Base::Writer Writer; + + protected: + + const static char* INTENSITY_PROP; + const static std::vector PROPS; + + public: + const static char* PROPS_LIST[]; + + const static std::string FILE_EXTENSION; + const static Coord FILE_SEPARATOR; + + //Public member functions. + public: + + BasicSection() + : Base::Object((size_t)2, (size_t)6 + PROPS.size(), PROPS) { Base::Object::set(NAN); } + + BasicSection(const MR::Math::Vector::View& view, std::vector* props) + : Base::Object((size_t)2, view, props) { assert(view.size()==7); } + + BasicSection(const Strand& strand, + const MR::Math::Vector::View& position_coeffs, + const MR::Math::Vector::View& tangent_coeffs, + double length_fraction) + : Base::Object((size_t)2, (size_t)3, PROPS) + + { Base::Object::set(NAN); set(strand,position_coeffs,tangent_coeffs,length_fraction); } + + // Used in derived classes + protected: + + BasicSection(size_t size, const std::vector& props) + : Base::Object(size, size * 3 + props.size(), props) { set(NAN); } + + BasicSection(size_t size, const MR::Math::Vector::View& view, std::vector* props) + : Base::Object(size, view, props) {} + + public: + + + BasicSection& set(const Strand& strand, + const MR::Math::Vector::View& position_coeffs, + const MR::Math::Vector::View& tangent_coeffs, + double length_fraction) + + { + + this->intensity() = strand.acs(); + position() = strand.left_product(position_coeffs); + tangent() = strand.left_product(tangent_coeffs) * length_fraction; + return *this; + } + + using Base::Object::set; + + virtual ~BasicSection() {} + + Coord position() + { return Coord(MR::Math::Vector::sub(0,3)); } + + Coord position() const + { return Coord(MR::Math::Vector::sub(0,3)); } + + Coord tangent() + { return Coord(MR::Math::Vector::sub(3,6)); } + + Coord tangent() const + { return Coord(MR::Math::Vector::sub(3,6)); } + + double& position(size_t idx) + { return MR::Math::Vector::operator[](idx); } + + const double& position(size_t idx) const + { return MR::Math::Vector::operator[](idx); } + + double& tangent(size_t idx) + { return MR::Math::Vector::operator[](idx + 3); } + + const double& tangent(size_t idx) const + { return MR::Math::Vector::operator[](idx + 3); } + + + double& intensity() + { return prop(INTENSITY_PROP);} + + const double& intensity() const + { return prop(INTENSITY_PROP); } + + + BASE_GENERAL_FUNCTIONS(BasicSection); + + BASE_MULT_DIVIDE_FUNCTIONS(BasicSection); + + BASE_ADD_SUBTRACT_FUNCTIONS(BasicSection); + + + double length() const { return tangent().norm(); } + + + void normalize(const Triple& vox_lengths, const Triple& offsets); + + + void unnormalize_gradient(const Triple& vox_lengths); + + MR::Math::Vector vector() const; + + void from_vector(const MR::Math::Vector& vector); + + + friend std::ostream& operator<< (std::ostream& stream , const Strand::BasicSection& seg); + + + // End generic functions. + }; + + + inline Strand::BasicSection operator* (double scalar, const Strand::BasicSection& section) + { return section * scalar; } + + + std::ostream& operator<< (std::ostream& stream , const Strand::BasicSection& seg); + + + + inline void Strand::BasicSection::normalize(const Triple& vox_lengths, const Triple& offsets) { + + position() -= offsets; + + position() /= vox_lengths; + + } + + + inline void Strand::BasicSection::unnormalize_gradient(const Triple& vox_lengths) { + + position() /= vox_lengths; + + } + + + } + +} + +#endif diff --git a/src/bts/fibre/strand/basic_section/tensor.cpp b/src/bts/fibre/strand/basic_section/tensor.cpp new file mode 100644 index 0000000..7ecc662 --- /dev/null +++ b/src/bts/fibre/strand/basic_section/tensor.cpp @@ -0,0 +1,49 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, Aug 16, 2010. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + +#include "bts/fibre/strand/basic_section/tensor.h" + +namespace BTS { + + namespace Fibre { + + void Strand::BasicSection::Tensor::unnormalise_hessian(const Triple& vox_lengths) { + + Triple vox_lengths2 (MR::Math::pow2(vox_lengths[X]), MR::Math::pow2(vox_lengths[Y]),MR::Math::pow2(vox_lengths[Z])); + + position(X).position() /= vox_lengths2; + position(Y).position() /= vox_lengths2; + position(Z).position() /= vox_lengths2; + + position(X).tangent() /= vox_lengths[X]; + position(Y).tangent() /= vox_lengths[Y]; + position(Z).tangent() /= vox_lengths[Z]; + + tangent(X).position() /= vox_lengths; + tangent(Y).position() /= vox_lengths; + tangent(Z).position() /= vox_lengths; + + } + + } + +} diff --git a/src/bts/fibre/strand/basic_section/tensor.cpp.h b/src/bts/fibre/strand/basic_section/tensor.cpp.h new file mode 100644 index 0000000..6c882b3 --- /dev/null +++ b/src/bts/fibre/strand/basic_section/tensor.cpp.h @@ -0,0 +1,120 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, Aug 16, 2010. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ +// +//#ifndef __bts_fibre_strand_section_tensor_cpp_h__ +//#define __bts_fibre_strand_section_tensor_cpp_h__ +// +//namespace BTS { +// +// namespace Fibre { +// +// +// template std::ostream& operator<< (std::ostream& stream , const Strand::BasicSection::Tensor_tpl& seg) { +// +// stream << "Intensity: " << seg.intensity << std::endl; +// stream << "Position: " << seg.position << std::endl; +// stream << "Tangent: " << seg.tangent << std::endl; +// +// return stream; +// +// } +// +// +// +// inline Strand::BasicSection::Tensor::Tensor (const Strand::Section& section) { +// +// position[X] = section; +// position[Y] = section; +// position[Z] = section; +// +// tangent[X] = section; +// tangent[Y] = section; +// tangent[Z] = section; +// +// intensity = section; +// +// init(); +// +// } +// +// +// +// inline Coord::Tensor Strand::BasicSection::Tensor::position_hessian() const { +// +// Coord::Tensor pos_hess; +// +// pos_hess[X] = position[X].position; +// pos_hess[Y] = position[Y].position; +// pos_hess[Z] = position[Z].position; +// +// return pos_hess; +// +// } +// +// inline Coord::Tensor Strand::BasicSection::Tensor::tangent_hessian() const { +// +// Coord::Tensor tan_hess; +// +// tan_hess[X] = tangent[X].tangent; +// tan_hess[Y] = tangent[Y].tangent; +// tan_hess[Z] = tangent[Z].tangent; +// +// return tan_hess; +// +// } +// +// inline Coord::Tensor Strand::BasicSection::Tensor::cross_hessian() const { +// +// Coord::Tensor cross_hess; +// +// cross_hess[X] = position[X].tangent; +// cross_hess[Y] = position[Y].tangent; +// cross_hess[Z] = position[Z].tangent; +// +// return cross_hess; +// +// } +// +// +// inline void Strand::BasicSection::Tensor::unnormalise_hessian(const Triple& vox_lengths) { +// +// Triple vox_lengths2 (MR::Math::pow2(vox_lengths[X]), MR::Math::pow2(vox_lengths[Y]),MR::Math::pow2(vox_lengths[Z])); +// +// position[X].position /= vox_lengths2; +// position[Y].position /= vox_lengths2; +// position[Z].position /= vox_lengths2; +// +// position[X].tangent /= vox_lengths[X]; +// position[Y].tangent /= vox_lengths[Y]; +// position[Z].tangent /= vox_lengths[Z]; +// +// tangent[X].position /= vox_lengths; +// tangent[Y].position /= vox_lengths; +// tangent[Z].position /= vox_lengths; +// +// } +// +// } +// +//} +// +//#endif /* __bts_fibre_strand_section_tensor_cpp_h__ */ diff --git a/src/bts/fibre/strand/basic_section/tensor.h b/src/bts/fibre/strand/basic_section/tensor.h new file mode 100644 index 0000000..ae18e70 --- /dev/null +++ b/src/bts/fibre/strand/basic_section/tensor.h @@ -0,0 +1,97 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, 07/08/2010. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + + */ +// +#ifndef __bts_fibre_strand_section_tensor_h__ +#define __bts_fibre_strand_section_tensor_h__ + +#include "bts/fibre/strand/basic_section.h" + +#include "bts/fibre/base/tensor.h" +#include "bts/coord/tensor.h" + +namespace BTS { + + namespace Fibre { + + class Strand::BasicSection::Tensor : public Base::Tensor { + + + public: + + Tensor() + : Base::Tensor(Strand::BasicSection()) {} + + Tensor(const MR::Math::Matrix::View& view) + : Base::Tensor(Strand::BasicSection(), view) { assert(view.rows() == 7); assert(view.columns() == 7); } + + Strand::BasicSection position(size_t dim_i) + { return Strand::BasicSection(row(dim_i), tmpl.props); } + + const Strand::BasicSection position(size_t dim_i) const + { return Strand::BasicSection(row(dim_i), tmpl.props); } + + Strand::BasicSection tangent(size_t dim_i) + { return Strand::BasicSection(row(dim_i + 3), tmpl.props); } + + const Strand::BasicSection tangent(size_t dim_i) const + { return Strand::BasicSection(row(dim_i + 3), tmpl.props); } + + Strand::BasicSection intensity() + { return Strand::BasicSection(row(6), tmpl.props); } + + const Strand::BasicSection intensity() const + { return Strand::BasicSection(row(6), tmpl.props); } + + Coord::Tensor position() + { return Coord::Tensor(sub((size_t)0,(size_t)2,(size_t)0,(size_t)2)); } + + const Coord::Tensor position() const + { return Coord::Tensor(sub((size_t)0,(size_t)2,(size_t)0,(size_t)2)); } + + Coord::Tensor tangent() + { return Coord::Tensor(sub((size_t)3,(size_t)5,(size_t)3,(size_t)5)); } + + const Coord::Tensor tangent() const + { return Coord::Tensor(sub((size_t)3,(size_t)5,(size_t)3,(size_t)5)); } + + + Coord::Tensor position_tangent() + { return Coord::Tensor(sub((size_t)0,(size_t)2,(size_t)3,(size_t)5)); } + + const Coord::Tensor position_tangent() const + { return Coord::Tensor(sub((size_t)0,(size_t)2,(size_t)3,(size_t)5)); } + + + Coord::Tensor tangent_position() + { return Coord::Tensor(sub((size_t)3,(size_t)5,(size_t)0,(size_t)2)); } + + const Coord::Tensor tangent_position() const + { return Coord::Tensor(sub((size_t)3,(size_t)5,(size_t)0,(size_t)2)); } + + void unnormalise_hessian(const Triple& vox_lengths); + }; + + } + +} + +#endif /* __bts_fibre_strand_section_tensor_h__ */ diff --git a/src/bts/fibre/strand/section.cpp b/src/bts/fibre/strand/section.cpp new file mode 100644 index 0000000..f0257cd --- /dev/null +++ b/src/bts/fibre/strand/section.cpp @@ -0,0 +1,40 @@ +/* + * Copyright 2010 Brain Research Institute/National ICT Australia (NICTA), Melbourne, Australia + * + * Written by Thomas G Close, 5/05/09. + * + * This file is part of Bayesian Tractlet Sampling (BTS). + * + * BTS 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. + * + * BTS 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 BTS. If not, see . + * + */ + + + +#include "bts/fibre/strand.h" +#include "bts/fibre/strand/section.h" + + + +namespace BTS { + + namespace Fibre { + + const std::string Strand::Section::FILE_EXTENSION = "ssc"; + const Coord Strand::Section::FILE_SEPARATOR = Coord (-INFINITY, NAN, NAN); + + + } + +} diff --git a/src/bts/fibre/strand/section.h b/src/bts/fibre/strand/section.h new file mode 100644 index 0000000..f2337ac --- /dev/null +++ b/src/bts/fibre/strand/section.h @@ -0,0 +1,233 @@ +/* + Copyright 2010 Brain Research Institute/National ICT Australia (NICTA), Melbourne, Australia + + Written by Thomas G Close, 5/05/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + +*/ + + + +#ifndef __bts_fibre_strand_section_h__ +#define __bts_fibre_strand_section_h__ + +#include "bts/fibre/strand.h" + +#include +#include +#include + +#include "bts/fibre/base/writer.h" +#include "bts/fibre/base/reader.h" + +//#include "bts/image/observed/buffer.h" + + + +#include "bts/fibre/strand/basic_section.h" +#include "bts/fibre/strand/basic_section/tensor.h" +#include "bts/fibre/base/tensor.h" +#include "bts/coord/tensor.h" + + +namespace BTS { + + namespace Fibre { + + class Strand::Section : public Strand::BasicSection { + + public: + + typedef Coord Element; + + typedef Fibre::Base::Reader
Reader; + typedef Fibre::Base::Writer
Writer; + + //Public static members and typedefs + public: + + const static std::string FILE_EXTENSION; + const static Coord FILE_SEPARATOR; + + + // Public member variables. + public: + + //References used when working backwards to create the gradient. + MR::Math::Vector position_coeffs; + MR::Math::Vector tangent_coeffs; + double length_fraction; + + std::vector precalc_weightings; + std::vector precalc_weight_gradients; + std::vector precalc_weight_hessians; + + double precalc_interpolation; + BasicSection precalc_interp_gradient; + BasicSection::Tensor precalc_interp_hessian; + + const Strand* parent; + + public: + + Section(size_t init_precalc_size = 0) + : length_fraction(NAN), + precalc_weightings(init_precalc_size), + precalc_weight_gradients(init_precalc_size), + precalc_weight_hessians(init_precalc_size) {} + + + //TODO: Look into this, this is not the most efficient way to do this but will have to do until image generation + // is reworked. + Section(const Strand& strand, + const MR::Math::Vector::View& position_coeffs, + const MR::Math::Vector::View& tangent_coeffs, + double length_fraction, + size_t init_precalc_size = 0) + + : BasicSection(strand, + position_coeffs, + tangent_coeffs, + length_fraction), + precalc_weightings(init_precalc_size), + precalc_weight_gradients(init_precalc_size), + precalc_weight_hessians(init_precalc_size) + + { set(strand,position_coeffs,tangent_coeffs,length_fraction); } + + + void set(const Strand& strand, + const MR::Math::Vector::View& position_coeffs, + const MR::Math::Vector::View& tangent_coeffs, + double length_fraction) + + { + + BasicSection::set(strand, position_coeffs, tangent_coeffs, length_fraction); + + this->position_coeffs = position_coeffs; + this->tangent_coeffs = tangent_coeffs; + this->length_fraction = length_fraction; + + this->parent = &strand; + } + + + Section(const Section& s) + : BasicSection(s), + position_coeffs(s.position_coeffs), + tangent_coeffs(s.tangent_coeffs), + length_fraction(s.length_fraction), + precalc_weightings(s.precalc_weightings), + precalc_weight_gradients(s.precalc_weight_gradients), + precalc_weight_hessians(s.precalc_weight_hessians), + precalc_interpolation(s.precalc_interpolation), + precalc_interp_gradient(s.precalc_interp_gradient), + precalc_interp_hessian(s.precalc_interp_hessian), + parent(s.parent) {} + + + // Used in derived classes + protected: + + Section(size_t size, const std::vector& props, size_t init_precalc_size) + : BasicSection(size, props), + length_fraction(NAN), + precalc_weightings(init_precalc_size), + precalc_weight_gradients(init_precalc_size), + precalc_weight_hessians(init_precalc_size) {} + + Section(size_t size, const MR::Math::Vector::View& view, std::vector* props) + : BasicSection(size, view, props) {} + + public: + + Section& operator= (const Section& s) { + BasicSection::operator=(s); + length_fraction = s.length_fraction; + position_coeffs = s.position_coeffs; + tangent_coeffs = s.tangent_coeffs; + precalc_weightings = s.precalc_weightings; + precalc_weight_gradients = s.precalc_weight_gradients; + precalc_weight_hessians = s.precalc_weight_hessians; + precalc_interpolation = s.precalc_interpolation; + precalc_interp_gradient = s.precalc_interp_gradient; + precalc_interp_hessian = s.precalc_interp_hessian; + parent = s.parent; + return *this; + } + + + virtual ~Section() {} + + protected: + + Section(double intensity, + const MR::Math::Vector::View& position_coeffs, + const MR::Math::Vector::View& tangent_coeffs, + double length_fraction) { + + set(intensity, position_coeffs, tangent_coeffs, length_fraction); + } + + + void set( double intensity, + const MR::Math::Vector::View& position_coeffs, + const MR::Math::Vector::View& tangent_coeffs, + double length_fraction) { + + this->intensity() = intensity; + this->position_coeffs = position_coeffs; + this->tangent_coeffs = tangent_coeffs; + this->length_fraction = length_fraction; + this->parent = 0; + } + + + public: + + BASE_GENERAL_FUNCTIONS(Section); + + BASE_MULT_DIVIDE_FUNCTIONS(Section); + + BASE_ADD_SUBTRACT_FUNCTIONS(Section); + + //---------------------------------------------------------------// + // Generic Functions (NB: Can be removed in production versions) // + //---------------------------------------------------------------// + + // The following generic functions are used in 'Fibre::Base::Writer/Reader' and 'Analysis::GradientTester', + // which are in turn used in 'test_gradient.cpp' to check gradient calculations. Can be removed in production version. + + +// typedef Fibre::Base::Reader Reader; +// typedef Fibre::Base::Writer Writer; + + + }; + + + } + +} + + + + + + +#endif diff --git a/src/bts/fibre/strand/set.cpp b/src/bts/fibre/strand/set.cpp new file mode 100644 index 0000000..7e5be2a --- /dev/null +++ b/src/bts/fibre/strand/set.cpp @@ -0,0 +1,794 @@ +/* + Copyright 2010 Brain Research Institute/National ICT Australia (NICTA), Melbourne, Australia + + Written by Thomas G Close, 5/05/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + +*/ + + +#include + +#include "bts/fibre/strand/set.h" +//#include "bts/fibre/strand/set/permutation.h" + +#include "bts/fibre/strand.h" + + +#include "bts/fibre/track.h" +#include "bts/fibre/track/set.h" + +#include "bts/fibre/tractlet.h" +#include "bts/fibre/tractlet/set.h" + + +#include "bts/math/munkres.h" +#include "bts/math/svd.h" +#include "bts/math/common.h" + + + +#include "bts/fibre/properties/extended.h" + +#include "bts/fibre/base/reader.cpp.h" +#include "bts/fibre/base/writer.cpp.h" + +#include "phantom/shared/strand_collection.h" + + +namespace BTS { + + namespace Fibre { + + const std::string Strand::Set::FILE_EXTENSION = "sst"; + const char* Strand::Set::PROPS_LIST[] = { Base::Set::BASE_INTENSITY_PROP, PROPS_LIST_END }; + + + const double Strand::Set::MAX_ACCUM_RDL = 0.1; + const double Strand::Set::MIN_ACCUM_RDL = 0.1; + const double Strand::Set::TEMP_REDUC_FACTOR = 0.95; + const double Strand::Set::INIT_PROB_ACCEPTANCE = 0.5; + + const std::string Strand::Set::ORIGINAL_NUM_POINTS_PROP = "loaded_num_points"; + const std::string Strand::Set::ORIGINAL_NUM_TRACTLETS_PROP = "loaded_num_tractlets"; + + + size_t MAX_ITERATIONS = 1000; + + + + Strand::Set::Set (const Track::Set& tcks, size_t degree) + : Base::Set(tcks.size(), + degree, + 3 * degree + select_props(*tcks.elem_props).size(), + select_props(*tcks.props), + select_props(*tcks.elem_props), + (tcks.ext_props ? *tcks.ext_props : std::map())) { + + for (size_t tck_i = 0; tck_i < size(); tck_i++) { + + size_t strand_degree = degree; + + if (!degree) { + if (has_extend_elem_prop(Track::Set::ORIGINAL_DEGREE_PROP)) + strand_degree = get_extend_elem_prop(Track::Set::ORIGINAL_DEGREE_PROP, tck_i); + else + throw Exception ("Degree must be supplied (and cannot be 0) for conversion from tracks to strands."); + } + + operator[](tck_i) = Strand(tcks[tck_i], strand_degree); //tcks[tck_i].to_strand(strand_degree); + + } + + for (size_t prop_i = 0; prop_i < num_props(); ++prop_i) + prop(prop_i) = tcks.prop(prop_key(prop_i)); + + copy_extend_elem_props(tcks); + + } + + + + Strand::Set::Set(const Tractlet::Set& set, size_t num_samples) + : Fibre::Base::Set(select_props(*set.props), select_props(*set.elem_props), set.get_extend_props()) { + + add_extend_elem_prop(BUNDLE_INDEX_EPROP, "-1"); + + for (size_t tractlet_i = 0; tractlet_i < set.size(); tractlet_i++) { + + Set new_strands (set[tractlet_i], num_samples); + + if (new_strands.size()) { + + size_t old_size = size(); + + resize(size() + new_strands.size(), new_strands[0]); + + for (size_t strand_i = 0; strand_i < new_strands.size(); strand_i++) { + operator[](strand_i + old_size) = new_strands[strand_i]; + set_extend_elem_prop(BUNDLE_INDEX_EPROP, str(tractlet_i), strand_i + old_size); + } + } + } + + for (size_t prop_i = 0; prop_i < num_props(); ++prop_i) + prop(prop_i) = set.prop(prop_key(prop_i)); + + + if (!set.var_elem_degrees()) + freeze_elem_degree(); + + } + + + Strand::Set::Set(const Tractlet::Set& set, double strands_per_vol) + : Fibre::Base::Set(select_props(*set.props), select_props(*set.elem_props), set.get_extend_props()) { + + add_extend_elem_prop(BUNDLE_INDEX_EPROP, "-1"); + + for (size_t tract_i = 0; tract_i < set.size(); tract_i++) { + + std::string bundle_index = set.has_extend_elem_prop(BUNDLE_INDEX_EPROP) ? set.get_extend_elem_prop(BUNDLE_INDEX_EPROP, tract_i) : str(tract_i); + + std::map prop_row; + prop_row[BUNDLE_INDEX_EPROP] = bundle_index; + + Set new_strands (set[tract_i], strands_per_vol); + + for (size_t new_strand_i = 0; new_strand_i < new_strands.size(); ++new_strand_i) + push_back(new_strands[new_strand_i], prop_row); + + } + + for (size_t prop_i = 0; prop_i < num_props(); ++prop_i) + prop(prop_i) = set.prop(prop_key(prop_i)); + + if (!set.var_elem_degrees()) + freeze_elem_degree(); //Attempt to freeze element size but ignore if fails. + + } + + + Strand::Set::Set(const Tractlet& tractlet, size_t num_width_sections) + : Fibre::Base::Set(std::vector(), select_props(*tractlet.props), std::map()) { + + from_tractlet(tractlet, num_width_sections); + + } + + + Strand::Set::Set(const Tractlet& tractlet, double strands_per_acs) + : Fibre::Base::Set(std::vector(), select_props(*tractlet.props), std::map()) { + + double num_strands = strands_per_acs * tractlet.acs(); + + size_t num_width_sections = (size_t)MR::Math::round(MR::Math::sqrt(num_strands * 4.0 / M_PI)); + + from_tractlet(tractlet, num_width_sections); + + } + + + void Strand::Set::from_tractlet (const Tractlet& tractlet, size_t num_width_sections) { + + double width_fraction = 1.0 / (double)num_width_sections; + + size_t count = 0; + + // Loop across cross-section of tractlet. Loop each perturbation axis from a 'width_fraction' from -1 to a width_fraction + // from +1, in intervals of 2*width_fraction's. It is performed this way because each strand is to represent the + // tractlet +- a width_fraction radius about it. + for (double ax1_frac = (-1.0 + width_fraction); ax1_frac < 1.0; ax1_frac += 2.0 * width_fraction) { + + for (double ax2_frac = (-1.0 + width_fraction); ax2_frac < 1.0; ax2_frac += 2.0 * width_fraction) { + + //Include section if coord consisting of the combined fractions along each perturbation axes lies within the + // unit circle minus a half a width_fraction. This will give the resulting cross-sections an elliptical + // shape (or circular if axes are equal). + if (MR::Math::pow2(ax1_frac) + MR::Math::pow2(ax2_frac) <= (1.0 - width_fraction /2.0)) { + + Strand strand (tractlet[0] + tractlet[1] * ax1_frac + tractlet[2] * ax2_frac); + strand.copy_props(tractlet); + + push_back(strand); + + ++count; + } + + } + + // Normalise the ACS property of the generated strands by the number generated + if (has_elem_prop(ACS_SQRT_PROP)) + for (size_t strand_i = 0; strand_i < size(); ++strand_i) + operator[](strand_i).set_acs(tractlet.acs() / (double)count); + + } + + freeze_elem_degree(); //Freeze element size + + } + + + Track::Set Strand::Set::to_tracks(size_t num_points) const { + + return Track::Set(*this, num_points); + + } + + + Tractlet::Set Strand::Set::to_tractlets () const { + + return Tractlet::Set(*this); + + } + + + + Tractlet::Set Strand::Set::to_tractlets (double width) const { + + return Tractlet::Set(*this, width); + + } + + + Tractlet::Set Strand::Set::to_tractlets(size_t num_tractlets, const std::string& cluster_save_location) const { + + return Tractlet::Set(*this, num_tractlets,cluster_save_location); + + } + + + + + + Strand Strand::Set::centroid() const { + + Fibre::Strand centroid(0); + + for (size_t strand_i = 0; strand_i < size(); ++strand_i) + centroid += operator[](strand_i); + + centroid /= (double)size(); + + return centroid; + + } + + + //TODO: fix up distance and flip functions to avoid unecessary copies of data. + Strand::Set Strand::Set::shortest_span() const { + + Strand::Set strands(*this); + + if (size()) { + + Fibre::Strand centroid; + + centroid = strands[0]; + + size_t num_iterations = 0; + + double distance = -1.0; + + std::vector flip_pattern(size()); + + while (num_iterations < MAX_ITERATIONS) { + + double new_distance = 0; + + for (size_t strand_i = 0; strand_i < size(); ++strand_i) + new_distance += strands[strand_i].distance(centroid,(bool&)flip_pattern[strand_i]); + + if (new_distance == distance) + break; + else + distance = new_distance; + + centroid.zero(); + + for (size_t strand_i = 0; strand_i < size(); ++strand_i) + if (flip_pattern[strand_i]) + centroid += strands[strand_i].flip(); + else + centroid += strands[strand_i]; + + centroid /= (double)size(); + + ++num_iterations; + } + + if (num_iterations == MAX_ITERATIONS) + throw Exception ("Could not find shortest span of strand set."); + + strands = strands.flip(flip_pattern); + + } + + return strands; + + } + + Strand::Set Strand::Set::flip(const std::vector& to_flip) const { + + if (to_flip.size() != size()) + throw Exception ("Size of 'to_flip' vector (" + str(to_flip.size()) + ") does not match that of strand set (" + str(size()) + ")."); + + Strand::Set flipped (*this); + + for (size_t strand_i = 0; strand_i < size(); ++strand_i) + if (to_flip[strand_i]) + flipped[strand_i] = operator[](strand_i).flip(); + + return flipped; + + } + + + + + Strand::Set Strand::Set::peel(double distance, size_t num_length_sections, bool to_cube) const { + + Strand::Set include; + + include.set_extend_prop("peel_distance", str(distance)); + + if (to_cube) + include.set_extend_prop("peel_shape", "cube"); + else + include.set_extend_prop("peel_shape", "sphere"); + + + include.add_extend_elem_props(*this); + + for (size_t strand_i = 0; strand_i < size(); ++strand_i) { + + Track tck = operator[](strand_i).to_track(num_length_sections); + + bool in_roi = false; + + for (size_t point_i = 0; point_i < tck.num_points(); point_i++) { + + if (to_cube) { + if ((abs(tck[point_i][X]) <= distance) && (abs(tck[point_i][Y]) <= distance) && (abs(tck[point_i][Z]) <= distance)) { + in_roi = true; + break; + } + } else + if (tck[point_i].norm() <= distance) { + in_roi = true; + break; + } + + } + + if (in_roi) + include.push_back(operator[](strand_i), get_extend_elem_prop_row(strand_i)); + + } + + include.copy_props(*this); + include.copy_relevant_elem_props(*this); + + return include; + } + + + Strand::Set& Strand::Set::cluster(size_t num_clusters) { + + if (num_clusters > size()) + throw Exception ("New number of clusters (" + str(num_clusters) + ") must be less than or equal to original number of strands (" + str(size()) + ")"); + + + KMterm term( NUM_STAGES, 0, 0, 0, // run for 100 stages + MAX_ACCUM_RDL, // min consec RDL + MIN_ACCUM_RDL, // min accum RDL + MAX_RUN_STAGES, // max run stages + INIT_PROB_ACCEPTANCE, // init. prob. of acceptance + TEMP_RUN_LENGTH, // temp. run length + TEMP_REDUC_FACTOR); // temp. reduction factor + + + //-------------------------// + // k-means cluster strands + //-------------------------// + + size_t degree = operator[](0).degree(); + + int ptDim = degree * 3; // dimension + + KMdata dataPts(ptDim, size()); // allocate data storage + + for (size_t strand_i = 0; strand_i < size(); strand_i++) { + for (size_t degree_i = 0; degree_i < operator[](strand_i).degree(); degree_i++) { + dataPts[strand_i][degree_i * 3 + X] = operator[](strand_i)[degree_i][X]; + dataPts[strand_i][degree_i * 3 + Y] = operator[](strand_i)[degree_i][Y]; + dataPts[strand_i][degree_i * 3 + Z] = operator[](strand_i)[degree_i][Z]; + } + } + + + + dataPts.buildKcTree(); // build filtering structure + + KMfilterCenters ctrs(num_clusters, dataPts); // allocate centers + + KMlocalHybrid kmHybrid(ctrs, term); // Hybrid heuristic + ctrs = kmHybrid.execute(); + + //--------------------------// + // Get cluster information + //--------------------------// + + + KMctrIdxArray closeCtr = new KMctrIdx[dataPts.getNPts()]; + double* sqDist = new double[dataPts.getNPts()]; + ctrs.getAssignments(closeCtr, sqDist); + + if (!has_extend_elem_prop(Track::BUNDLE_INDEX_EPROP)) + add_extend_elem_prop(Track::BUNDLE_INDEX_EPROP, "-1"); + + for (size_t strand_i = 0; strand_i < size(); ++strand_i) + set_extend_elem_prop(Track::BUNDLE_INDEX_EPROP, str(closeCtr[strand_i]), strand_i); + + return *this; + + } + + + + + + Strand::Set Strand::Set::reduce_number(size_t new_num_strands) { + + if (new_num_strands == this->size()) + return *this; + + if (new_num_strands < 1) + throw Exception ("New number of strands must be greater than zero"); + + if (new_num_strands > this->size()) + throw Exception ("New number of strands (" + str(new_num_strands) + ") must be less than original number of strands (" + str(this->size()) + ")"); + + + KMterm term( NUM_STAGES, 0, 0, 0, // run for 100 stages + MAX_ACCUM_RDL, // min consec RDL + MIN_ACCUM_RDL, // min accum RDL + MAX_RUN_STAGES, // max run stages + INIT_PROB_ACCEPTANCE, // init. prob. of acceptance + TEMP_RUN_LENGTH, // temp. run length + TEMP_REDUC_FACTOR); // temp. reduction factor + + + //-------------------------// + // k-means cluster strands + //-------------------------// + + size_t degree = operator[](0).degree(); + + int ptDim = degree * 3; // dimension + + KMdata dataPts(ptDim, size()); // allocate data storage + + for (size_t strand_i = 0; strand_i < size(); strand_i++) { + for (size_t degree_i = 0; degree_i < operator[](strand_i).degree(); degree_i++) { + dataPts[strand_i][degree_i * 3 + X] = operator[](strand_i)[degree_i][X]; + dataPts[strand_i][degree_i * 3 + Y] = operator[](strand_i)[degree_i][Y]; + dataPts[strand_i][degree_i * 3 + Z] = operator[](strand_i)[degree_i][Z]; + } + } + + + + dataPts.buildKcTree(); // build filtering structure + + KMfilterCenters ctrs(new_num_strands, dataPts); // allocate centers + + KMlocalHybrid kmHybrid(ctrs, term); // Hybrid heuristic + ctrs = kmHybrid.execute(); + +// //--------------------------// +// // Get cluster information +// //--------------------------// +// +// +// KMctrIdxArray closeCtr = new KMctrIdx[dataPts.getNPts()]; +// double* sqDist = new double[dataPts.getNPts()]; +// ctrs.getAssignments(closeCtr, sqDist); + + + //-----------------------------------// + // Save centre points as new strands + //-----------------------------------// + + Strand::Set output_strands; + + for (size_t ctr_i = 0; ctr_i < new_num_strands; ctr_i++) { + + Strand strand(degree); + + for (size_t degree_i = 0; degree_i < operator[](0).degree(); degree_i++) { + for (size_t dim_i = 0; dim_i < 3; dim_i++) + strand[degree_i][dim_i] = ctrs[ctr_i][degree_i * 3 + dim_i]; + } + + output_strands.push_back(strand); + + } + + output_strands.copy_props(*this); + output_strands.copy_relevant_elem_props(*this); + + return output_strands; + + } + + + std::vector Strand::Set::bundle(size_t bundle_index) const { + + if (!this->has_extend_elem_prop(Track::BUNDLE_INDEX_EPROP)) + throw Exception ("Bundle index property (" + Track::BUNDLE_INDEX_EPROP + ") not set on strand set."); + + std::vector bundle; + + for (size_t strand_i = 0; strand_i < size(); strand_i++) { + + if (get_extend_elem_prop(Track::BUNDLE_INDEX_EPROP, strand_i) == bundle_index) + bundle.push_back(strand_i); + + } + + return bundle; + + } + + size_t Strand::Set::max_degree() const { + + size_t max_degree = 0; + + for (size_t strand_i = 0; strand_i < size(); ++strand_i) + if (operator[](strand_i).degree() > max_degree) + max_degree = operator[](strand_i).degree(); + + return max_degree; + + } + + + Strand::Set Strand::Set::bundle_backbones() const { + + + if (!this->has_extend_elem_prop(Track::BUNDLE_INDEX_EPROP)) + throw Exception ("Bundle index property (" + Track::BUNDLE_INDEX_EPROP + ") not set on strand set."); + + + Strand::Set backbones; + backbones.add_extend_elem_prop(Track::BUNDLE_INDEX_EPROP,"-1"); + + std::vector bundle_indices = this->bundle_indices(); + + for (size_t bundle_i = 0; bundle_i < bundle_indices.size(); ++bundle_i) { + + std::vector bundle = this->bundle(bundle_indices[bundle_i]); + + Fibre::Strand backbone; + + for (size_t strand_i = 0; strand_i < bundle.size(); ++strand_i) + backbone += operator[](bundle[strand_i]); + + backbone /= (double)bundle.size(); + + std::map properties_row; + properties_row[Track::BUNDLE_INDEX_EPROP] = str(operator[](bundle_indices[bundle_i])); + + backbones.push_back(backbone, properties_row); + + + } + + backbones.copy_props(*this); + backbones.copy_relevant_elem_props(*this); + + return backbones; + + } + + + std::vector Strand::Set::bundle_indices() const { + + if (!this->has_extend_elem_prop(Track::BUNDLE_INDEX_EPROP)) + throw Exception ("Bundle index property (" + Track::BUNDLE_INDEX_EPROP + ") not set on strand set."); + + std::vector bundle_indices; + + for (size_t strand_i = 0; strand_i < size(); ++strand_i) { + size_t bundle_i = get_extend_elem_prop(Track::BUNDLE_INDEX_EPROP, strand_i); + + if (find(bundle_indices.begin(), bundle_indices.end(), bundle_i) == bundle_indices.end()) + bundle_indices.push_back(bundle_i); + + } + + return bundle_indices; + + } + + + void Strand::Set::project_to_sphere(double sphere_radius) { + + for (size_t strand_i = 0; strand_i < size(); ++strand_i) + operator[](strand_i).project_to_sphere(sphere_radius); + + } + + + + void Strand::Set::load(const std::string& location, size_t degree, double strands_per_acs) { + + this->clear(); + + if (File::has_or_txt_extension(location)) { + + Base::Set::load(location); + + } else if (File::has_or_txt_extension(location)) { + + if (degree < 1) + throw Exception(" '-degree' parameter is required for implicit conversion from track set ('" + location + "')."); + + Track::Set tcks (location); + + operator=(tcks.to_strands(degree)); + + this->add_extend_elem_prop(ORIGINAL_NUM_POINTS_PROP, "0"); + + for (size_t tck_i = 0; tck_i < tcks.size(); tck_i++) + this->set_extend_elem_prop(ORIGINAL_NUM_POINTS_PROP, str(tcks[tck_i].num_points()), tck_i); + + } else if (File::has_or_txt_extension(location)) { + + if (strands_per_acs <= 0.0) + throw Exception(" '-strands_per_acs' parameter is required for implicit conversion from tractlet set ('" + location + "')."); + + Tractlet::Set tractlets (location); + + set_extend_prop(ORIGINAL_NUM_TRACTLETS_PROP, str(tractlets.size())); + + operator=(tractlets.to_strands(strands_per_acs)); + + } else + throw Exception("The extension of file \"" + location + "\" is not a recognised type (\"" + Strand::FILE_EXTENSION + "\" or \"" + Track::FILE_EXTENSION + "\")."); + + } + + + Strand::Set Strand::Set::permute(const std::vector& indices) const { + + if (var_elem_degrees()) + throw Exception ("'permute' is currently not implemented for variable element size sets."); + + Set permuted_set (size(), degree(), *props, *elem_props); + + this->Fibre::Base::Set::permute(permuted_set, indices); + + return permuted_set; + + } + + + void Strand::Set::save(const std::string& location, size_t num_points, size_t num_tractlets) const { + + + if (File::has_or_txt_extension(location)) { + + //Remove ORIGINAL_NUM_POINTS_PROP property if it exists as it is no longer relevant. + if (this->has_extend_elem_prop(ORIGINAL_NUM_POINTS_PROP)) { + + Set strands = *this; + + strands.remove_extend_elem_prop(ORIGINAL_NUM_POINTS_PROP); + + strands.save(location); + + } else + + Base::Set::save(location); + + } else if (File::has_or_txt_extension(location)) { + + Track::Set tcks; + + if (num_points != 0) + + tcks = this->to_tracks(num_points); + + else if (this->has_extend_elem_prop(ORIGINAL_NUM_POINTS_PROP)) { + + for (size_t strand_i = 0; strand_i < this->size(); strand_i++) { + + size_t loaded_num_points = get_extend_elem_prop(ORIGINAL_NUM_POINTS_PROP, strand_i); + tcks.push_back(this->operator[](strand_i).to_track(loaded_num_points), this->get_extend_elem_prop_row(strand_i)); + + } + + } else + throw Exception(" \"-num_points\" parameter is required for implicit conversion to track set ('" + location + "')."); + + tcks.remove_extend_elem_prop(ORIGINAL_NUM_POINTS_PROP); + + tcks.save(location); + + } else if (File::has_or_txt_extension(location)) { + + Tractlet::Set tcts; + + std::map properties = get_extend_props(); + + std::map::const_iterator num_tract_it = properties.find(ORIGINAL_NUM_TRACTLETS_PROP); + + if (num_tractlets) + tcts = this->to_tractlets(num_tractlets, File::strip_extension(location) + ".clustered.str"); + else if (num_tract_it != properties.end()) + tcts = this->to_tractlets(to(num_tract_it->second)); + else if (has_extend_elem_prop(Track::BUNDLE_INDEX_EPROP)) + tcts = this->to_tractlets(); + else + throw Exception(" '-num_tractlets' is required for implicit conversion to tractlet set ('" + location + "') if '" + Track::BUNDLE_INDEX_EPROP + "' is not present."); + + tcts.save(location); + + } else + throw Exception("The extension of file \"" + location + "\" is not a recognised type (\"" + Strand::FILE_EXTENSION + "\" or \"" + Track::FILE_EXTENSION + "\")."); + + } + + + std::string Strand::Set::matlab_str() const { + + std::stringstream ss; + + ss << "{ 'b_intens', " << base_intensity() << ", "; + + for (size_t strand_i = 0; strand_i < size(); strand_i++) { + + ss << "{ 'acs', " << operator[](strand_i).acs() << ", ["; + + for (size_t degree_i = 0; degree_i < operator[](strand_i).size(); degree_i++) { + + for (size_t dim_i = 0; dim_i < 3; dim_i++) + ss << operator[](strand_i)[degree_i][dim_i] << " "; + + if (degree_i != 2) + ss << "; "; + + } + + ss << "] }"; + + if (strand_i != (size() -1)) + ss << ", "; + + } + + ss << " }"; + + return ss.str(); + + } + + } + +} diff --git a/src/bts/fibre/strand/set.h b/src/bts/fibre/strand/set.h new file mode 100644 index 0000000..98e1084 --- /dev/null +++ b/src/bts/fibre/strand/set.h @@ -0,0 +1,293 @@ +/* + Copyright 2010 Brain Research Institute/National ICT Australia (NICTA), Melbourne, Australia + + Written by Thomas G Close, 5/05/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + +*/ + + +#include "bts/fibre/track.h" + +#ifndef __bts_fibre_strand_set_h__ +#define __bts_fibre_strand_set_h__ + + +#include "bts/common.h" +#include "bts/file.h" + +#include "bts/fibre/strand.h" +#include "bts/fibre/strand/section.h" +#include "bts/fibre/base/set.h" +#include "bts/fibre/tractlet.h" +#include "bts/math/munkres.h" + +#include "bts/fibre/base/set_reader.h" +#include "bts/fibre/base/set_writer.h" + +#include "k_means/KMlocal.h" // k-means algorithms + + +namespace BTS { + + namespace Fibre { + + class Strand::Set : public Fibre::Base::Set { + + //Public Nested classes and typedefs + public: + + class Walker; + class Momentum; + typedef Base::Tensor Tensor; + typedef Base::SetReader Reader; + typedef Base::SetWriter Writer; + + typedef Base::SetTextReader TextReader; + typedef Base::SetTextWriter TextWriter; + + friend class Object; + friend class Track::Set; + friend class Tractlet::Set; + friend class Base::Tensor; + friend class Base::SetReader; + friend class Base::SetWriter; + + typedef Strand Element; + + + //Public static members + public: + + const static std::string FILE_EXTENSION; + const static std::string ORIGINAL_NUM_POINTS_PROP; + const static std::string ORIGINAL_NUM_TRACTLETS_PROP; + + + // Clustering parameters used in reduce_number. + + const static size_t NUM_STAGES = 100; // run for 100 stages + const static double MAX_ACCUM_RDL; // min consec RDL + const static double MIN_ACCUM_RDL; // min accum RDL + const static int MAX_RUN_STAGES = 3; // max run stages + const static double INIT_PROB_ACCEPTANCE; // init. prob. OF ACCEPTance + const static int TEMP_RUN_LENGTH = 10; // temp. RUN LENGTH + const static double TEMP_REDUC_FACTOR; // temp. reduction factor + + protected: + + const static char* PROPS_LIST[]; + + + //Public static functions + public: + + //Do nothing, no characteristic properties in Strand::Set class. + static std::vector& append_characteristic_property_keys(std::vector& header) { return header; } + + //Public member functions + public: + + //TODO: Make the properties of these constructors protected, add all Fibre objects to the 'friends' list of each other, and add constructors with flags to determine whether certain properties are included. + + /*! Initialises a strand set with variable strand sizes, without properties or element properties + * + * @param extended_props The extended properties of the set + */ + Set (const std::map& extended_props = std::map()) + : Fibre::Base::Set(std::vector(), std::vector(), extended_props) {} + + + /*! Initialises a strand set with variable strand sizes, with properties element propertiess + * + * @param props The set properties + * @param elem_props The element properties + * @param extended_props The extended properties of the set + */ + Set (const std::vector& props, const std::vector& elem_props, const std::map& extended_props = std::map()) + : Fibre::Base::Set(props, elem_props, extended_props) {} + + + /*! Initialises a strand set of a preset size with strand degree, without properties or element properties + * + * @param size Size of the strand set + * @param degree The (fixed) degree of the the strands in the strand set (can be freed using the 'free_elem_degree()' function) + * @param extended_props The extended properties of the set + */ + Set (size_t size, size_t degree, const std::map& extended_props = std::map()) + : Fibre::Base::Set(size, degree, degree * 3, std::vector(), std::vector(), extended_props) {} + + + /*! Initialises a strand set of a preset size with strand degree, with properties and element properties + * + * @param size Size of the strand set + * @param props The set properties + * @param elem_props The element properties + * @param degree The (fixed) degree of the the strands in the strand set (can be freed using the 'free_elem_degree()' function) + * @param extended_props The extended properties of the set + */ + Set (size_t size, size_t degree, const std::vector& props, const std::vector& elem_props, const std::map& extended_props = std::map()) + : Fibre::Base::Set(size, degree, degree * 3 + elem_props.size(), props, elem_props, extended_props) {} + + + Set (std::string file_location, size_t degree = 0, double strands_per_width = -1.0) + : Fibre::Base::Set(std::vector(), std::vector(), std::map()) + { load(file_location, degree, strands_per_width);} + + + Set (std::string file_location, double strands_per_width) + : Fibre::Base::Set(std::vector(), std::vector(), std::map()) + { load(file_location, strands_per_width);} + + + //TODO: Switch this around the other way, so that the to_strands function calls this constructor. + Set (const Track::Set& tcks, size_t degree = 0); + + + Set (const Tractlet::Set& set, size_t num_samples); + + + Set (const Tractlet::Set& set, double strands_per_vol); + + + Set (const Tractlet& set, size_t num_samples); + + + Set (const Tractlet& set, double strands_per_vol); + + + // Set (size_t num_strands, const std::map& properties = std::map()) + // : Fibre::Base::Set(num_strands, properties, 1.0) {} + // + // Set (size_t num_strands, double base_intensity, const std::map& properties = std::map()) + // : Fibre::Base::Set(num_strands, properties, base_intensity) {} + // + // Set (size_t num_strands, size_t degree, double base_intensity = 1.0, const std::map& properties = std::map()) + // : Fibre::Base::Set(num_strands, degree, properties, base_intensity) {} + // + // Set (size_t num_strands, const Strand& default_value, double base_intensity = 1.0, const std::map& properties = std::map()) + // : Fibre::Base::Set(num_strands, default_value, properties, base_intensity) {} + + + Set (const Set& s_set) + : Fibre::Base::Set(s_set) {} + + + BASE_GENERAL_FUNCTIONS(Set); + + BASE_SET_FUNCTIONS(Set); + + Track::Set to_tracks (size_t num_points) const; + + //!Uses Track::BUNDLE_INDEX property to group strands into bundles and convert the bundles into tractlets. + Tractlet::Set to_tractlets() const; + + //!First clusters strands into bundles then converts the bundles into tractlets. + //!NB:If num_tractlets argument is less than zero reverts back to to_tractlets() function. \arg num_tractlets number of tractlets to cluster + Tractlet::Set to_tractlets (size_t num_tractlets, const std::string& cluster_save_location = "") const; + + //!Creates a new tractlet for each strand \arg width width of the created tractlets. + Tractlet::Set to_tractlets (double width) const; + + + Strand::Set& cluster(size_t num_clusters); + +// Permutation default_permutation(); + + Set permute(const std::vector& indices) const; + + Set smallest_distance_set(const Set& reference) const + { Set smallest; this->Fibre::Base::Set::smallest_distance_set(reference, smallest); return smallest; } + + Set shortest_span() const; + + Set flip(const std::vector& to_flip) const; + + Strand centroid() const; + + Set peel(double distance, size_t num_length_sections, bool to_cube = false) const; + + Set reduce_number(size_t new_num); + + std::vector bundle(size_t index) const; + + Set bundle_backbones() const; + + std::vector bundle_indices() const; + + void project_to_sphere(double sphere_radius); + + size_t max_degree() const; + + size_t degree() const + { if (var_elem_degrees()) throw Exception ("Strand set has variable rows, so its 'degree' is undefined"); return elem_dgree; } + + + void load(const std::string& path, size_t degree = 0, double strands_per_width = -1.0); + + void load(const std::string& path, double strands_per_width) + { load(path, 0, strands_per_width); } + + void save(const std::string& path, size_t num_sections = 0, size_t num_tractlets = 0) const; + + + Set& operator+= (const Set& set) { Fibre::Base::Set::operator+=(set); return *this; } + Set& operator-= (const Set& set) { Fibre::Base::Set::operator-=(set); return *this; } + + Set& operator*= (const Set& set) { Fibre::Base::Set::operator*=(set); return *this; } + Set& operator*= (double c) { Fibre::Base::Set::operator*=(c); return *this; } + + Set& operator/= (const Set& set) { Fibre::Base::Set::operator/=(set); return *this; } + Set& operator/= (double c) { Fibre::Base::Set::operator/=(c); return *this; } + + Set operator+ (const Set& set) const { Set answer (*this); answer += set; return answer; } + Set operator- (const Set& set) const { Set answer (*this); answer -= set; return answer; } + + Set operator* (const Set& set) const { Set answer (*this); answer *= set; return *this; } + Set operator* (double c) const { Set answer (*this); answer *= c; return answer; } + + Set operator/ (const Set& set) const { Set answer (*this); answer /= set; return *this; } + Set operator/ (double c) const { Set answer (*this); answer /= c; return answer; } + + + inline Set& zero() { Fibre::Base::Set::zero();return *this; } + + std::string matlab_str() const; + + void calc_characteristic_properties() {} + + private: + + void from_tractlet(const Tractlet& tractlet, size_t num_width_sections); + + }; + + double distance(Strand::Set& strands, Strand::Set& reference, std::vector& matched_indices); + + double distance(Strand::Set& strands, Strand::Set& reference, std::vector& matched_indices, BTS::Math::Munkres&munkres_algorithm, MR::Math::Matrix& similarity); + + inline Strand::Set operator* (double c, Strand::Set set) + { Strand::Set answer (set); answer *= c; return answer; } + + + } + +} + + +#endif + diff --git a/src/bts/fibre/strand/set/momentum.cpp b/src/bts/fibre/strand/set/momentum.cpp new file mode 100644 index 0000000..5ec8131 --- /dev/null +++ b/src/bts/fibre/strand/set/momentum.cpp @@ -0,0 +1,73 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, Aug 2, 2010. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + +#include "bts/fibre/strand/set/momentum.h" + + + + +namespace BTS { + + namespace Fibre { + + const double Strand::Set::Momentum::STEP_SCALE_DEFAULT = 1.0; + const char* Strand::Set::Momentum::STEP_LOCATION_DEFAULT = "/home/tclose/data/mcmc/hamiltonian/params/stepsizes/default.str"; + + + Strand::Set::Momentum Strand::Set::Momentum::factory( const Set& state, + double step_scale, + const std::string& step_location, + const std::string& weight_location, + MCMC::Proposal::Distribution* const proposal_distribution) { + Fibre::Strand::Set step; + + if (step_location.size()) { + step.load(step_location); + + //If the loaded step only contains one strand use this as the template for the whole set + if (step.size() == 1) { + Fibre::Strand::Set full_step(state.size(), state.degree()); + full_step.copy_props(step); + full_step.copy_elem_props(step); + + for (size_t elem_i = 0; elem_i < state.size(); ++elem_i) + full_step[elem_i] = step[0]; + + step = full_step; + + } + + else if (step.size() != state.size()) + throw Exception ("Loaded step sizes' size (" + str(step.size()) + ") does not match state (" + str(state.size()) + ")."); + + } else { + step = state; + step.set(step_scale); + } + + return Fibre::Strand::Set::Momentum (proposal_distribution, step); + + } + + } + +} diff --git a/src/bts/fibre/strand/set/momentum.h b/src/bts/fibre/strand/set/momentum.h new file mode 100644 index 0000000..f73fc3c --- /dev/null +++ b/src/bts/fibre/strand/set/momentum.h @@ -0,0 +1,90 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, Aug 2, 2010. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + +#ifndef __bts_fibre_strand_set_momentum_h__ +#define __bts_fibre_strand_set_momentum_h__ + +#include "bts/mcmc/proposal/distribution.h" +#include "bts/mcmc/proposal/momentum.h" +#include "bts/fibre/strand/set.h" + +namespace BTS { + + namespace Fibre { + + class Strand::Set::Momentum { + + //Public static variables, nested classes and typedefs + public: + + static const double STEP_SCALE_DEFAULT; + static const char* STEP_LOCATION_DEFAULT; + + protected: + + MCMC::Proposal::Momentum mcmc_momentum; + + //Public static functions + public: + + static Momentum factory( const Set& state, + double step_scale, + const std::string& step_location, + const std::string& weight_location, + MCMC::Proposal::Distribution* const proposal_distribution); + + //Public member functions + public: + + Momentum(MCMC::Proposal::Distribution* const prop_distr = 0) + : mcmc_momentum(prop_distr) {} + + Momentum(MCMC::Proposal::Distribution* const proposal_distribution, + const Set& step_sizes) + + : mcmc_momentum(proposal_distribution, step_sizes) {} + + + void half_update_momentum(const Set& gradient) + { mcmc_momentum.half_update_momentum(gradient); } + + void update_state(Set& state) const + { MR::Math::Vector& state_vector = state; mcmc_momentum.update_state(state_vector); } + + + double predicted_change(const Set& gradient) const + { return mcmc_momentum.predicted_change(gradient); } + + + double log_kinetic_energy() const + { return mcmc_momentum.log_kinetic_energy(); } + + void randomize() + { mcmc_momentum.randomize(); } + + }; + + } + +} + +#endif /* __bts_fibre_strand_set_momentum_h__ */ diff --git a/src/bts/fibre/strand/set/tensor.cpp b/src/bts/fibre/strand/set/tensor.cpp new file mode 100644 index 0000000..48fef41 --- /dev/null +++ b/src/bts/fibre/strand/set/tensor.cpp @@ -0,0 +1,36 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, 08/08/2010. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + +#include "bts/fibre/strand/tensor.h" + +namespace BTS { + + namespace Fibre { + + + + + + } + +} + diff --git a/src/bts/fibre/strand/set/tensor.h b/src/bts/fibre/strand/set/tensor.h new file mode 100644 index 0000000..8d3ff97 --- /dev/null +++ b/src/bts/fibre/strand/set/tensor.h @@ -0,0 +1,237 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, 08/08/2010. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + +//#ifndef __bts_fibre_strand_set_tensor_h__ +//#define __bts_fibre_strand_set_tensor_h__ +// +//#include "bts/fibre/set/tensor.h" +//#include "bts/fibre/strand/set.h" +//#include "bts/fibre/tensor/writer2.h" +// +//namespace BTS { +// +// namespace Fibre { +// +// +//#ifndef STRUCTURED_SET_TENSOR +// class Strand::Set::Tensor : public MR::Math::Matrix { +// +// public: +// +// typedef Fibre::Tensor::Writer2 Writer; +// +// protected: +// +// std::vector fibre_start; +// std::vector fibre_end; +// +// public: +// +// Tensor () {} +// +// Tensor(const Set& default_value) +// : MR::Math::Matrix(default_value.vsize(), default_value.vsize()) { +// +// size_t start = default_value.has_extend_elem_prop("base_intensity"); +// +// for (size_t fibre_i = 0; fibre_i < default_value.size(); fibre_i++) { +// fibre_start.push_back(start); +// fibre_end.push_back(start += default_value[fibre_i].vsize()); +// } +// +// zero(); +// +// } +// +// +// Tensor(const Tensor& t) +// : MR::Math::Matrix(t) {} +// +// Tensor(const MR::Math::Matrix& m) +// : MR::Math::Matrix(m) {} +// +// ~Tensor() {} +// +// +// Tensor& operator= (const Tensor& t) +// { this->MR::Math::Matrix::operator=(t); return *this; } +// +// Tensor& operator= (const MR::Math::Matrix& M) +// { assert(M.rows() == this->rows() && M.columns() == this->columns()); this->MR::Math::Matrix::operator=(M); return *this; } +// +// +// size_t matrix_length() const +// { return this->rows(); } +// +// +// const MR::Math::Matrix& matrix() const +// { return *this; } +// +// Tensor& zero() +// { MR::Math::Matrix::operator=(0.0); return *this; } +// +// Tensor& invalidate() +// { MR::Math::Matrix::operator=(NAN); return *this; } +// +// void from_matrix(const MR::Math::Matrix& matrix) +// { MR::Math::Matrix::operator=(matrix); } +// +// Tensor& operator+= (const MR::Math::Matrix& tensor) +// { MR::Math::Matrix::operator+=(tensor); return *this; } +// +// Tensor& operator-= (const MR::Math::Matrix& tensor) +// { MR::Math::Matrix::operator-=(tensor); return *this; } +// +// Tensor& operator*= (const MR::Math::Matrix& tensor) +// { MR::Math::Matrix::operator*=(tensor); return *this; } +// +// Tensor& operator*= (double c) +// { MR::Math::Matrix::operator*=(c); return *this; } +// +// Tensor& operator/= (const MR::Math::Matrix& tensor) +// { MR::Math::Matrix::operator/=(tensor); return *this; } +// +// Tensor& operator/= (double c) +// { MR::Math::Matrix::operator/=(c); return *this; } +// +// Tensor operator+ (const MR::Math::Matrix& t) const +// { Tensor answer (*this); answer += t; return answer; } +// +// Tensor operator- (const MR::Math::Matrix& t) const +// { Tensor answer (*this); answer -= t; return answer; } +// +// Tensor operator* (const MR::Math::Matrix& t) const +// { Tensor answer (*this); answer *= t; return answer; } +// +// Tensor operator* (double c) const +// { Tensor answer (*this); answer *= c; return answer; } +// +// Tensor operator/ (const MR::Math::Matrix& t) const +// { Tensor answer (*this); answer /= t; return answer; } +// +// Tensor operator/ (double c) const +// { Tensor answer (*this); answer /= c; return answer; } +// +// }; +// +//// std::ostream& operator<<(std::ostream& stream, const Strand::Set::Tensor& tensor) { +//// +//// stream << "base_intensity: " << tensor.base_intensity << std::endl; +//// +//// for (size_t elem_i = 0; elem_i < tensor.size(); elem_i++) +//// stream << tensor[elem_i] << std::endl; +//// +//// return stream; +//// +//// } +// +//#else +// class Strand::Set::Tensor : public Strand::Set::Tensor_tpl { +// +// public: +// +// typedef Fibre::Tensor::Writer Writer; +// +// public: +// +// Tensor () {} +// +// Tensor(const Set& default_value) +// : Tensor_tpl(default_value) {} +// +// Tensor(const Tensor_tpl& t) +// : Tensor_tpl(t) {} +// +// ~Tensor() {} +// +// +// Tensor& operator= (const Tensor_tpl& t) +// { Tensor_tpl::operator=(t); return *this; } +// +// +// size_t matrix_length() const +// { return Flattener< Set >::length(*this); } +// +// +// MR::Math::Matrix matrix() const +// { return Flattener< Set >::flatten(*this); } +// +// +// Tensor from_matrix(const MR::Math::Matrix& matrix) +// { return Flattener< Set >::unflatten(matrix, *this); } +// +// Tensor& operator+= (const Tensor& tensor) +// { Tensor_tpl::operator+=(tensor); return *this; } +// +// Tensor& operator-= (const Tensor& tensor) +// { Tensor_tpl::operator-=(tensor); return *this; } +// +// Tensor& operator*= (const Tensor& tensor) +// { Tensor_tpl::operator*=(tensor); return *this; } +// +// Tensor& operator*= (double c) +// { Tensor_tpl::operator*=(c); return *this; } +// +// Tensor& operator/= (const Tensor& tensor) +// { Tensor_tpl::operator/=(tensor); return *this; } +// +// Tensor& operator/= (double c) +// { Tensor_tpl::operator/=(c); return *this; } +// +// Tensor operator+ (const Tensor& t) const +// { Tensor answer (*this); answer += t; return answer; } +// +// Tensor operator- (const Tensor& t) const +// { Tensor answer (*this); answer -= t; return answer; } +// +// Tensor operator* (const Tensor& t) const +// { Tensor answer (*this); answer *= t; return answer; } +// +// Tensor operator* (double c) const +// { Tensor answer (*this); answer *= c; return answer; } +// +// Tensor operator/ (const Tensor& t) const +// { Tensor answer (*this); answer /= t; return answer; } +// +// Tensor operator/ (double c) const +// { Tensor answer (*this); answer /= c; return answer; } +// +// }; +// +// std::ostream& operator<<(std::ostream& stream, const Strand::Set::Tensor& tensor) { +// +// stream << "base_intensity: " << tensor.base_intensity << std::endl; +// +// for (size_t elem_i = 0; elem_i < tensor.size(); elem_i++) +// stream << tensor[elem_i] << std::endl; +// +// return stream; +// +// } +// +//#endif +// +// } +// +//} +// +//#endif /* __bts_fibre_set_tensor_h__ */ diff --git a/src/bts/fibre/strand/set/walker.cpp b/src/bts/fibre/strand/set/walker.cpp new file mode 100644 index 0000000..b148e9c --- /dev/null +++ b/src/bts/fibre/strand/set/walker.cpp @@ -0,0 +1,95 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, Aug 2, 2010. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + +#include "bts/fibre/strand/set/walker.h" + +namespace BTS { + + namespace Fibre { + + + const char* Strand::Set::Walker::TYPE_DEFAULT = "standard"; + const char* Strand::Set::Walker::STEP_LOCATION_DEFAULT = "/home/tclose/data/mcmc/metropolis/params/walker/scaling.str.txt"; + const double Strand::Set::Walker::STEP_SCALE_DEFAULT = 0.01; + + Strand::Set::Walker* Strand::Set::Walker::factory(const Strand::Set& state, + const std::string& type, + double step_scale, + const std::string& step_location, + MCMC::Proposal::Distribution* distribution, + double base_intensity_scale) { + + + Walker* walker; + + if (type == "standard") { + Fibre::Strand::Set step; + + if (step_location.size()) { + step.load(step_location); + + if (step.size() == 1) { + + Fibre::Strand step_template = step[0]; + + step.resize(state.size()); + + for (size_t tract_i = 0; tract_i < state.size(); ++tract_i) { + + if (state[tract_i].size() > step_template.size()) + throw Exception ("Strand (" + str(tract_i) + ") is larger than step template."); + + step[tract_i] = step_template; + step[tract_i].resize(state[tract_i].size()); + + } + + } else if (step.size() != state.size()) + throw Exception ("Loaded step sizes' size (" + str(step.size()) + ") does not match state (" + str(state.size()) + ")."); + + step *= step_scale; + + } else { + step = state; + step.set(step_scale); + } + + walker = new Walker (distribution, step); + + } else + + throw Exception ("Unrecognised Fibre::Strand::Set::Walker type '" + type + "'."); + + return walker; + + } + + + void Strand::Set::Walker::step(const Strand::Set& current, Strand::Set& proposed, double scalar) { + + MCMC::Proposal::Walker::step(current, proposed, scalar); + + } + + } + +} diff --git a/src/bts/fibre/strand/set/walker.h b/src/bts/fibre/strand/set/walker.h new file mode 100644 index 0000000..417229b --- /dev/null +++ b/src/bts/fibre/strand/set/walker.h @@ -0,0 +1,78 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, Aug 2, 2010. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + +#ifndef __bts_fibre_strand_set_walker_h__ +#define __bts_fibre_strand_set_walker_h__ + +#include "bts/fibre/strand/set.h" +#include "bts/mcmc/proposal/distribution.h" +#include "bts/mcmc/proposal/walker.h" + +namespace BTS { + + namespace Fibre { + + class Strand::Set::Walker : public MCMC::Proposal::Walker { + + //Public nested classes and typedefs + public: + + class Constrained; + class AngleOnly; + + //Public static const members. + public: + + static const char* TYPE_DEFAULT; + static const double STEP_SCALE_DEFAULT; + static const char* STEP_LOCATION_DEFAULT; + + //Public static member functions. + public: + + static Walker* factory(const Set& state, + const std::string& type, + double step_scale, + const std::string& step_location, + MCMC::Proposal::Distribution* distribution, + double base_intensity_scale); + + //Public member functions + public: + + Walker(MCMC::Proposal::Distribution* const proposal_distribution, + const Set& relative_step_sizes) + + : MCMC::Proposal::Walker(proposal_distribution, relative_step_sizes) {} + + virtual ~Walker() {} + + virtual void step(const Set& current, Set& proposed, double scalar = 1.0); + + + }; + + } + +} + +#endif /* __bts_fibre_strand_walker_h__ */ diff --git a/src/bts/fibre/strand/tensor.cpp b/src/bts/fibre/strand/tensor.cpp new file mode 100644 index 0000000..b8fa698 --- /dev/null +++ b/src/bts/fibre/strand/tensor.cpp @@ -0,0 +1,72 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, 17/08/2010. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + + +#include "bts/fibre/strand/basic_section.h" +#include "bts/fibre/strand/section.h" +#include "bts/fibre/strand/tensor.h" +#include "bts/fibre/strand/basic_section/tensor.h" + +namespace BTS { + + namespace Fibre { + + + void Strand::Tensor::add_section_hessian(const Strand& strand, + const Section& section, + const BasicSection& gradient, + const BasicSection::Tensor& hessian) { + + + Fibre::Strand acs_inc = (section.position_coeffs.size(), 0.0); + + + acs_inc.add_section_gradient(strand, section, gradient); + + if (has_var_acs()) { + acs() += acs_inc; + acs().set_acs(0.0); + } + + for (size_t row_degree_i = 0; row_degree_i < degree(); row_degree_i++) + for (size_t row_dim_i = 0; row_dim_i < 3; row_dim_i++) { + for (size_t col_degree_i = 0; col_degree_i < degree(); col_degree_i++) + for (size_t col_dim_i = 0; col_dim_i < 3; col_dim_i++) { + double& elem = operator()(row_degree_i,row_dim_i, col_degree_i,col_dim_i); + elem += section.position_coeffs[row_degree_i] * section.position_coeffs[col_degree_i] * hessian.position(row_dim_i).position(col_dim_i) + + section.position_coeffs[row_degree_i] * section.tangent_coeffs[col_degree_i] * hessian.position(row_dim_i).tangent(col_dim_i) * section.length_fraction + + section.tangent_coeffs[row_degree_i] * section.position_coeffs[col_degree_i] * hessian.tangent(row_dim_i).position(col_dim_i) * section.length_fraction + + section.tangent_coeffs[row_degree_i] * section.tangent_coeffs[col_degree_i] * hessian.tangent(row_dim_i).tangent(col_dim_i) * MR::Math::pow2(section.length_fraction); + + } + + if (has_var_acs()) + row(row_degree_i * 3 + row_dim_i).var_acs() += acs_inc[row_degree_i][row_dim_i]; + } + + } + + + } + +} + diff --git a/src/bts/fibre/strand/tensor.h b/src/bts/fibre/strand/tensor.h new file mode 100644 index 0000000..f24489c --- /dev/null +++ b/src/bts/fibre/strand/tensor.h @@ -0,0 +1,119 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, 07/08/2010. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + +#ifndef __bts_fibre_strand_tensor_h__ +#define __bts_fibre_strand_tensor_h__ + + +#include "bts/fibre/strand.h" +#include "bts/fibre/strand/tensor.h" +#include "bts/fibre/base/tensor.h" +#include "bts/fibre/strand/basic_section/tensor.h" + + + +namespace BTS { + + namespace Fibre { + + class Strand::Tensor : public Base::Tensor { + + + public: + +// typedef Base::Tensor::Writer Writer; + + //Public member functions + public: + + Tensor() {} + + Tensor(const Strand& strand_template) + : Base::Tensor(strand_template) {} + + + Tensor (const Strand& strand_template, const MR::Math::Matrix::View& view) + : Base::Tensor(strand_template, view) {} + + + Tensor(const Tensor& t) + : Base::Tensor(t) {} + + + Tensor& operator=(const Tensor& t) + { Base::Tensor::operator=(t); return *this; } + + Tensor& operator=(const MR::Math::Matrix& m) + { Base::Tensor::operator=(m); return *this; } + + Tensor& operator=(double c) + { Base::Tensor::operator=(c); return *this; } + + size_t degree() const + { return tmpl.degree(); } + + size_t vsize() const + { return tmpl.vsize(); } + + Strand row(size_t idx) + { return Strand(degree(), MR::Math::Matrix::row(idx), tmpl.props); } + + const Strand row(size_t idx) const + { return Strand(degree(), MR::Math::Matrix::row(idx), tmpl.props); } + + Strand column(size_t idx) + { return Strand(degree(), MR::Math::Matrix::column(idx), tmpl.props); } + + const Strand column(size_t idx) const + { return Strand(degree(), MR::Math::Matrix::column(idx), tmpl.props); } + + bool has_var_acs() const + { return tmpl.has_var_acs(); } + + Strand acs() + { assert(has_var_acs()); return Strand(degree(), MR::Math::Matrix::row(vsize() + tmpl.prop_index(Strand::ACS_SQRT_PROP)), tmpl.props); } + + + double& operator()(size_t row_degree_i, size_t row_dim_i, size_t col_degree_i, size_t col_dim_i) + { return MR::Math::Matrix::operator()(row_degree_i * 3 + row_dim_i, col_degree_i * 3 + col_dim_i); } + + + double operator()(size_t row_degree_i, size_t row_dim_i, size_t col_degree_i, size_t col_dim_i) const + { return MR::Math::Matrix::operator()(row_degree_i * 3 + row_dim_i, col_degree_i * 3 + col_dim_i); } + + + Strand operator[](size_t idx) + { return Strand(degree(), MR::Math::Matrix::row(idx), tmpl.props); } + + const Strand operator[](size_t idx) const + { return Strand(degree(), MR::Math::Matrix::row(idx), tmpl.props); } + + void add_section_hessian(const Strand& strand, const Section& section, const BasicSection& gradient, const BasicSection::Tensor& hessian); + + + }; + + } + +} + +#endif /* __bts_fibre_strand_tensor_h__ */ diff --git a/src/bts/fibre/strand/walker.h b/src/bts/fibre/strand/walker.h new file mode 100644 index 0000000..78dc210 --- /dev/null +++ b/src/bts/fibre/strand/walker.h @@ -0,0 +1,56 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, Aug 2, 2010. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + +#ifndef __bts_fibre_strand_walker_h__ +#define __bts_fibre_strand_walker_h__ + +#include "bts/fibre/strand.h" +#include "bts/mcmc/proposal/walker.h" +#include "bts/mcmc/proposal/distribution.h" + +namespace BTS { + + namespace Fibre { + + class Strand::Walker : public MCMC::Proposal::Walker { + + //Public member functions + public: + + Walker(MCMC::Proposal::Distribution* const prop_distr) + : MCMC::Proposal::Walker(prop_distr) {} + + Walker(MCMC::Proposal::Distribution* const proposal_distribution, + const Strand& relative_step_sizes) + + : MCMC::Proposal::Walker(proposal_distribution, relative_step_sizes) {} + + virtual ~Walker() {} + + + }; + + } + +} + +#endif /* __bts_fibre_strand_walker_h__ */ diff --git a/src/bts/fibre/track.cpp b/src/bts/fibre/track.cpp new file mode 100644 index 0000000..d60a806 --- /dev/null +++ b/src/bts/fibre/track.cpp @@ -0,0 +1,106 @@ +/* + Copyright 2010 Brain Research Institute/National ICT Australia (NICTA), Melbourne, Australia + + Written by Thomas G Close, 5/05/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + +*/ + + +#include "bts/fibre/track.h" +#include "bts/fibre/strand.h" +#include "math/matrix.h" +//#include "math/matrix_ops.h" +#include "math/least_squares.h" + + + +namespace BTS { + + namespace Fibre { + + const std::string Track::RADIUS_PROP = "track_radius"; + const std::string Track::BUNDLE_INDEX_EPROP = "bundle_index"; + const std::string Track::RADIUS_PROP_DEFAULT = "0.02"; + + const Coord Track::FILE_SEPARATOR = Triple (NAN, NAN, NAN); + const std::string Track::FILE_EXTENSION = "tck"; + + const char* Track::PROPS_LIST[] = { Object::ACS_SQRT_PROP, PROPS_LIST_END }; + +// const char* Track::INTRINSIC_PROPERTIES[Track::NUM_INTRINSIC_PROPERTIES] = {}; + + + + Track::Track(const Strand& s, size_t num_points, bool include_endpoints) + : Base::Object (num_points, num_points * 3 + s.num_props(), select_props(*s.props)) { + + if (num_points == 0) + throw Exception ("'num_length_sections' option is required for conversion to tracks."); + + const MR::Math::Matrix& position_matrix = Strand::position_matrix(num_points, s.degree(), include_endpoints); + + for (size_t point_i = 0; point_i < num_points; point_i++) + operator[](point_i) = s.left_product(position_matrix.row(point_i)); + + for (size_t prop_i = 0; prop_i < num_props(); ++prop_i) + prop(prop_i) = s.prop(prop_key(prop_i)); + + } + + + Strand Track::to_strand(size_t degree) const { + + return Strand(*this,degree); + + } + + + Strand Track::to_strand(size_t degree, const std::vector& timeline) const { + + return Strand(*this,degree,timeline); + + } + + + Coord Track::left_product(const MR::Math::Vector::View& row_vector) const { + + assert(row_vector.size() >= num_points()); + + Coord product(0,0,0); + + for (size_t point_i = 0; point_i < num_points(); point_i++) + product += operator[](point_i) * row_vector[point_i]; + + return product; + + } + + + std::ostream& operator<< (std::ostream& stream, const Track& tck) { + stream << std::endl; + for (size_t point_i = 0; point_i < tck.num_points(); point_i++) { + stream << tck[point_i] << std::endl; + } + + return (stream); + } + + + } + +} diff --git a/src/bts/fibre/track.h b/src/bts/fibre/track.h new file mode 100644 index 0000000..27a53ed --- /dev/null +++ b/src/bts/fibre/track.h @@ -0,0 +1,174 @@ +/* + Copyright 2010 Brain Research Institute/National ICT Australia (NICTA), Melbourne, Australia + + Written by Thomas G Close, 5/05/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + +*/ + +#ifndef __bts_fibre_track_h__ +#define __bts_fibre_track_h__ + + +#include "bts/common.h" +#include "bts/fibre/base/object.h" +#include "bts/coord.h" + +#include "bts/fibre/base/writer.h" +#include "bts/fibre/base/reader.h" + +namespace BTS { + + namespace Fibre { + + class Track : public Base::Object { + + public: + + typedef Coord Element; + + class Set; + + typedef Base::Reader Reader; + typedef Fibre::Base::Writer Writer; + + typedef Base::TextReader TextReader; + typedef Base::TextWriter TextWriter; + + friend class Object; + friend class Strand; + friend class Tractlet; + friend class Set; + friend class Base::Set; + friend class Base::Reader; + friend class Base::Writer; + + public: + + const static Coord FILE_SEPARATOR; + const static std::string FILE_EXTENSION; + const static std::string RADIUS_PROP; + const static std::string BUNDLE_INDEX_EPROP; + const static std::string RADIUS_PROP_DEFAULT; + + protected: + + const static char* PROPS_LIST[]; + + public: + + const static size_t NUM_LENGTH_SECTIONS_DEFAULT = 100; + + public: + + Track (size_t num_points = 0, const std::vector props = std::vector()) + : Base::Object (num_points, num_points * 3 + props.size(), props) { set(NAN); } + + Track (const Track& t) + : Base::Object(t) {} + + ~Track() {} + + Track& operator=(const Track& t) + { Base::Object::operator=(t); return *this; } + + + Track (const Strand& s, size_t num_points, bool include_endpoints = 0); + + protected: + + /*! Used by Base::Set::operator[]() to initiate a from a section of a larger state vector or + * by Base::Tensor::row/column() for a slice of the tensor matrix + * + * @param num_points The number of points in the track + * @param view The view onto the larger vector or matrix + * @param props The properties stored in the set or tensor + */ + Track(size_t num_points, const MR::Math::Vector::View& view, std::vector* props) + : Base::Object(num_points, view, props) {} + + public: + + BASE_GENERAL_FUNCTIONS(Track); + + BASE_ADD_SUBTRACT_FUNCTIONS(Track); + + BASE_MULT_DIVIDE_FUNCTIONS(Track); + + /*! Used in Base::Set functions that need to differentiate between a tractlets degree and its size, which for + * Strand's and Track's they are equivlaent. + * + * @return The size of the Track + */ + size_t degree() const + { return size(); }; + + double acs() const + { return has_prop(ACS_SQRT_PROP) ? prop(ACS_SQRT_PROP) : 1.0; } + + void add_acs(double acs = 1.0) + { add_prop(ACS_SQRT_PROP, acs); } + + void set_acs(double acs) + { assert(acs >= 0); prop(ACS_SQRT_PROP) = MR::Math::sqrt(acs); } + + void remove_acs() + { remove_prop(ACS_SQRT_PROP); } + + Track base() + { return Track(sze, sub(0,bsize()), &EMPTY_PROPS); } + + const Track base() const + { return Track(sze, sub(0,bsize()), &EMPTY_PROPS); } + + Track& operator+= (const Coord& p) + { for (size_t point_i = 0; point_i < size(); point_i++) operator[](point_i) += p; return *this; } + + Track& operator-= (const Coord& p) + { for (size_t point_i = 0; point_i < size(); point_i++) operator[](point_i) -= p; return *this; } + + Track operator+ (const Coord& p) const + { Track answer(*this); answer += p; return answer; } + + Track operator- (const Coord& p) const + { Track answer(*this); answer -= p; return answer; } + + size_t num_points() const + { return size(); } + + Strand to_strand(size_t degree) const; + + Strand to_strand(size_t degree, const std::vector& timeline) const; + + Coord left_product(const MR::Math::Vector::View& row_vector) const; + + + }; + + + std::ostream& operator<< (std::ostream& stream, const Track& tck); + + } + +} + +#undef LOOP + +#endif + + + diff --git a/src/bts/fibre/track/set.cpp b/src/bts/fibre/track/set.cpp new file mode 100644 index 0000000..6f7620a --- /dev/null +++ b/src/bts/fibre/track/set.cpp @@ -0,0 +1,326 @@ +/* + Copyright 2010 Brain Research Institute/National ICT Australia (NICTA), Melbourne, Australia + + Written by Thomas G Close, 5/05/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + +*/ + +#include "bts/fibre/track/set.h" +#include "bts/fibre/strand/set.h" +#include "bts/fibre/tractlet/set.h" +#include "bts/fibre/track.h" + +#include "bts/fibre/base/reader.cpp.h" +#include "bts/fibre/base/writer.cpp.h" + + +namespace BTS { + + namespace Fibre { + + const std::string Track::Set::FILE_EXTENSION = "kst"; + + const char* Track::Set::PROPS_LIST[] = { Base::Set::BASE_INTENSITY_PROP, PROPS_LIST_END }; + + const std::string Track::Set::ORIGINAL_DEGREE_PROP = "loaded_degree"; + + + Track::Set::Set (const Strand::Set& strands, size_t num_length_sections) + : Base::Set(strands.size(), + num_length_sections, + num_length_sections * 3 + select_props(*strands.elem_props).size(), + select_props(*strands.props), + select_props(*strands.elem_props), + strands.get_extend_props()) { + + from_strands(strands, num_length_sections); + + } + + + Track::Set::Set(const Tractlet::Set& tractlets, size_t num_length_sections, size_t num_width_sections) + : Base::Set(tractlets.size(), + num_length_sections, + num_length_sections * 3 + select_props(*tractlets.elem_props).size(), + select_props(*tractlets.props), + select_props(*tractlets.elem_props), + tractlets.get_extend_props()) { + + + Strand::Set strands (tractlets, num_width_sections); + + resize(strands.size()); + + from_strands(strands, num_length_sections); + + } + + + Track::Set::Set(const Tractlet::Set& tractlets, size_t num_length_sections, double strands_per_acs) + : Base::Set(tractlets.size(), + num_length_sections, + num_length_sections * 3 + select_props(*tractlets.elem_props).size(), + select_props(*tractlets.props), + select_props(*tractlets.elem_props), + tractlets.get_extend_props()) { + + Strand::Set strands (tractlets, strands_per_acs); + + resize(strands.size()); + + from_strands(strands, num_length_sections); + + } + + + void Track::Set::from_strands(const Strand::Set& strands, size_t num_length_sections) { + + // Record the original degree of the strands, just in case the set needs to be converted back into strands again + // afterwards. + add_extend_elem_prop(Track::Set::ORIGINAL_DEGREE_PROP, "0"); + + for (size_t strand_i = 0; strand_i < size(); strand_i++) { + + operator[](strand_i) = Track(strands[strand_i], num_length_sections); + set_extend_elem_prop(Track::Set::ORIGINAL_DEGREE_PROP, str(strands[strand_i].degree()), strand_i); + + } + + for (size_t prop_i = 0; prop_i < num_props(); ++prop_i) + prop(prop_i) = strands.prop(prop_key(prop_i)); + + copy_extend_elem_props(strands); + + + } + + + Strand::Set Track::Set::to_strands(size_t degree) const { + + return Strand::Set(*this, degree); + + } + + + Tractlet::Set Track::Set::to_tractlets (size_t degree) const { + + return Tractlet::Set(*this, degree); + + } + + + Tractlet::Set Track::Set::to_tractlets (size_t degree, size_t num_tractlets) const { + + return Tractlet::Set(*this, degree, num_tractlets); + + } + + + Tractlet::Set Track::Set::to_tractlets (size_t degree, double width) const { + + return Tractlet::Set(*this, degree, width); + + } + + + void Track::Set::remove_short_tracks(size_t min_num_points) { + + for (size_t tck_i = 0; tck_i < this->size(); tck_i++) { + + if (operator[](tck_i).num_points() < min_num_points) { + + std::cout << std::endl << "Erased tck " << tck_i << " as it only had " << operator[](tck_i).num_points() << " control points." << std::endl; + + this->erase(tck_i); + + } + + } + + } + + + void Track::Set::load(const std::string& location, size_t num_points, double strands_per_acs) { + + + this->clear(); + + if (File::has_or_txt_extension(location)) + + this->Base::Set::load(location); + + else if (File::has_or_txt_extension(location)) { + + if (num_points < 1) + throw Exception(" '-num_points' parameter is required for implicit conversion from strand set ('" + location + "')."); + + Strand::Set strands (location); + + operator=(strands.to_tracks(num_points)); + + this->add_extend_elem_prop(ORIGINAL_DEGREE_PROP, "0"); + + for (size_t strand_i = 0; strand_i < strands.size(); strand_i++) + this->set_extend_elem_prop(ORIGINAL_DEGREE_PROP, str(strands[strand_i].degree()), strand_i); + + } else if (File::has_or_txt_extension(location)) { + + if (strands_per_acs <= 0.0) + throw Exception(" '-strands_per_acs' parameter is required for implicit conversion from tractlet set ('" + location + "')."); + + Tractlet::Set tractlets (location); + + operator=(tractlets.to_tracks(num_points, strands_per_acs)); + + this->add_extend_elem_prop(ORIGINAL_DEGREE_PROP, "0"); + + for (size_t tck_i = 0; tck_i < size(); tck_i++) { + + size_t tract_i = to(get_extend_elem_prop(BUNDLE_INDEX_EPROP, tck_i)); + + set_extend_elem_prop(ORIGINAL_DEGREE_PROP, str(tractlets[tract_i].degree()), tck_i); + } + + + } else + throw Exception("The extension of file \"" + location + "\" is not a recognised type (\"" + Track::FILE_EXTENSION + "\" or \"" + Strand::FILE_EXTENSION + "\")."); + + } + + + void Track::Set::save(const std::string& location, size_t degree, size_t num_tractlets) const { + + if (File::has_or_txt_extension(location)) { + + //Remove ORIGINAL_DEGREE_PROP property if it exists as it is no longer relevant. + if (this->has_extend_elem_prop(ORIGINAL_DEGREE_PROP)) { + + Set tcks = *this; + + tcks.remove_extend_elem_prop(ORIGINAL_DEGREE_PROP); + + tcks.Base::Set::save(location); + + } else + + this->Base::Set::save(location); + + + } else if (File::has_or_txt_extension(location)) { + + Strand::Set strands; + + if (degree) + strands = this->to_strands(degree); + + else if (this->has_extend_elem_prop(ORIGINAL_DEGREE_PROP)) { + + for (size_t tck_i = 0; tck_i < this->size(); tck_i++) { + size_t loaded_degree = to(this->get_extend_elem_prop(ORIGINAL_DEGREE_PROP, tck_i)); + strands.push_back(this->operator[](tck_i).to_strand(loaded_degree)); + } + + strands.copy_extend_elem_props(*this); + + } else + throw Exception(" '-degree' is required for implicit conversion to strand set ('" + location + "')."); + + strands.remove_extend_elem_prop(ORIGINAL_DEGREE_PROP); + + strands.save(location); + + } else if (File::has_or_txt_extension(location)) { + + Tractlet::Set tractlets; + + Strand::Set strands; + + if (degree) + strands = this->to_strands(degree); + else if (this->has_extend_elem_prop(ORIGINAL_DEGREE_PROP)) { + for (size_t tck_i = 0; tck_i < this->size(); tck_i++) { + size_t loaded_degree = to(this->get_extend_elem_prop(ORIGINAL_DEGREE_PROP, tck_i)); + strands.push_back(this->operator[](tck_i).to_strand(loaded_degree)); + } + strands.copy_extend_elem_props(*this); + } else + throw Exception(" '-degree' is required for implicit conversion to strand set ('" + location + "')."); + + if (!has_extend_elem_prop(BUNDLE_INDEX_EPROP) && !num_tractlets) + throw Exception(" '-num_tractlets' is required for implicit conversion to tractlet set ('" + location + "') if '" + BUNDLE_INDEX_EPROP + "' is not present."); + + tractlets = strands.to_tractlets(num_tractlets); + tractlets.copy_extend_elem_props(*this); + tractlets.save(location); + + } else + throw Exception("The extension of file \"" + location + "\" is not a recognised type (\"" + Track::FILE_EXTENSION + "\" or \"" + Strand::FILE_EXTENSION + "\")."); + + } + + + Track::Set Track::Set::peel(double distance, bool to_cube) { + + Track::Set include(get_extend_props()); + + include.set_extend_prop("peel_distance",str(distance)); + + if (to_cube) + include.set_extend_prop("peel_shape","cube"); + else + include.set_extend_prop("peel_shape","sphere"); + + include.add_extend_elem_props(*this); + + for (size_t tck_i = 0; tck_i < this->size(); tck_i++) { + + Track tck = operator[](tck_i); + + bool in_roi = false; + + for (size_t point_i = 0; point_i < tck.num_points(); point_i++) { + + if (to_cube) { + if ((abs(tck[point_i][X]) <= distance) && (abs(tck[point_i][Y]) <= distance) && (abs(tck[point_i][Z]) <= distance)) { + in_roi = true; + break; + } + } else + if (tck[point_i].norm() <= distance) { + in_roi = true; + break; + } + + } + + if (in_roi) + include.push_back(tck, this->get_extend_elem_prop_row(tck_i)); + + } + + include.copy_props(*this); + include.copy_relevant_elem_props(*this); + + return include; + } + + + + } + +} diff --git a/src/bts/fibre/track/set.h b/src/bts/fibre/track/set.h new file mode 100644 index 0000000..1db9fb0 --- /dev/null +++ b/src/bts/fibre/track/set.h @@ -0,0 +1,231 @@ +/* + Copyright 2010 Brain Research Institute/National ICT Australia (NICTA), Melbourne, Australia + + Written by Thomas G Close, 5/05/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + +*/ + +#ifndef __bts_fibre_track_set_h__ +#define __bts_fibre_track_set_h__ + + +#include "bts/common.h" + +#include "bts/fibre/strand/set.h" +#include "bts/fibre/track.h" + +#include "bts/fibre/base/set.h" + + + +namespace BTS { + + namespace Fibre { + + class Track::Set : public Base::Set { + + public: + + typedef Base::SetReader Reader; + typedef Base::SetWriter Writer; + + typedef Base::SetTextReader TextReader; + typedef Base::SetTextWriter TextWriter; + + friend class Object; + friend class Strand::Set; + friend class Tractlet::Set; + + friend class Base::SetReader; + friend class Base::SetWriter; + + //Public static constants + public: + + const static std::string FILE_EXTENSION; + + const static std::string ORIGINAL_DEGREE_PROP; + + protected: + + const static char* PROPS_LIST[]; + + //Public methods; + public: + + + /*! Initialises a tractlet set with variable tractlet sizes, without base intensity or tractlet intensities + * + * @param extended_props The extended properties of the set + */ + Set (const std::map& extended_props = std::map()) + : Fibre::Base::Set(std::vector(), std::vector(), extended_props) {} + + + + /*! Initialises a track set with variable strand sizes, with properties element propertiess + * + * @param props The set properties + * @param elem_props The element properties + * @param extended_props The extended properties of the set + */ + Set (const std::vector& props, const std::vector& elem_props, const std::map& extended_props = std::map()) + : Fibre::Base::Set(props, elem_props, extended_props) {} + + + + /*! Initialises a tractlet set of a preset size with tractlet degree + * + * @param size Size of the tractlet set + * @param num_points The (fixed) number of points per track in the set (can be freed using the 'free_elem_degree()' function) + * @param extended_props The extended properties of the set + */ + Set (size_t size, size_t num_points, const std::map& extended_props = std::map()) + : Fibre::Base::Set(size, num_points, num_points * 3, std::vector(), std::vector(), extended_props) {} + + + /*! Initialises a track set of a preset size with strand degree, with properties and element properties + * + * @param size Size of the track set + * @param props The set properties + * @param elem_props The element properties + * @param num_points The (fixed) number of points in the the tracks in the track set (can be freed using the 'free_elem_degree()' function) + * @param extended_props The extended properties of the set + */ + Set (size_t size, size_t num_points, const std::vector& props, const std::vector& elem_props, const std::map& extended_props = std::map()) + : Fibre::Base::Set(size, num_points, num_points * 3 + elem_props.size(), props, elem_props, extended_props) {} + + +// +// Set (const std::map& properties = std::map()) +// : Base::Set(properties) {} +// +// Set (size_t num_tcks, const std::map& properties = std::map()) +// : Base::Set(num_tcks, properties) {} +// +// Set (size_t num_tcks, size_t degree, const std::map& properties = std::map()) +// : Base::Set(num_tcks, degree, properties) {} +// +// Set (size_t num_tcks, const Track& default_value, const std::map& properties = std::map()) +// : Base::Set(num_tcks, default_value, properties) {} + + + + Set (const Set& s_set) + : Base::Set(s_set) {} + + Set (std::string file_location, size_t num_points = 0, double strands_per_width = -1.0) + : Fibre::Base::Set(std::vector(), std::vector(), std::map()) + { load(file_location, num_points, strands_per_width); } + + Set (std::string file_location, double strands_per_width) + : Fibre::Base::Set(std::vector(), std::vector(), std::map()) + { load(file_location, strands_per_width); } + + Set (const Strand::Set& strands, size_t num_length_sections = 0); + + + Set (const Tractlet::Set& t, size_t num_length_sections, size_t num_width_sections); + + + Set (const Tractlet::Set& t, size_t num_length_sections, double strands_per_acs); + + + BASE_GENERAL_FUNCTIONS(Set); + + BASE_SET_FUNCTIONS(Set); + + + Strand::Set to_strands(size_t degree) const; + + Tractlet::Set to_tractlets(size_t degree) const; + + Tractlet::Set to_tractlets(size_t degree, size_t num_tractlets) const; + + Tractlet::Set to_tractlets(size_t degree, double width) const; + + Set peel(double distance, bool to_cube = false); + + Set trim(double sphere_radius); + + void remove_short_tracks(size_t min_num_points); + + void load(const std::string& path, size_t num_points = 0, double strands_per_width = -1.0); + + void load(const std::string& path, double strands_per_width) + { load(path, 0, strands_per_width); } + + void save(const std::string& path, size_t degree = 0, size_t num_tractlets = 0) const; + + + Set& operator+= (const Set& set) + { Base::Set::operator+=(set); return *this; } + + Set& operator-= (const Set& set) + { Base::Set::operator-=(set); return *this; } + + Set& operator*= (const Set& set) + { Base::Set::operator*=(set); return *this; } + + Set& operator*= (double c) + { Base::Set::operator*=(c); return *this; } + + + Set& operator/= (const Set& set) + { Base::Set::operator/=(set); return *this; } + + Set& operator/= (double c) + { Base::Set::operator/=(c); return *this; } + + + Set operator+ (const Set& set) const + { Set answer (*this); answer += set; return answer; } + + Set operator- (const Set& set) const + { Set answer (*this); answer -= set; return answer; } + + Set operator* (const Set& set) const + { Set answer (*this); answer *= set; return answer; } + + Set operator* (double c) const + { Set answer (*this); answer *= c; return answer; } + + + Set operator/ (const Set& set) const + { Set answer (*this); answer /= set; return answer; } + + Set operator/ (double c) const + { Set answer (*this); answer /= c; return answer; } + + private: + + void from_strands(const Strand::Set& strands, size_t num_length_sections); + + }; + + + + inline Track::Set operator* (double c, Track::Set set) + { Track::Set answer (set); answer *= c; return answer; } + + } + +} + + +#endif diff --git a/src/bts/fibre/tractlet.cpp b/src/bts/fibre/tractlet.cpp new file mode 100644 index 0000000..d964550 --- /dev/null +++ b/src/bts/fibre/tractlet.cpp @@ -0,0 +1,637 @@ +/* + Copyright 2010 Brain Research Institute/National ICT Australia (NICTA), Melbourne, Australia + + Written by Thomas G Close, 5/05/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + +*/ + + +#include "math/matrix.h" + +#include "bts/triple.h" + +#include "bts/common.h" +#include "bts/math/common.h" + +#include "bts/math/svd.h" +#include "bts/fibre/tractlet.h" +#include "bts/fibre/strand/set.h" +#include "bts/fibre/track/set.h" +#include "bts/fibre/tractlet/section.h" + +#include "phantom/subdiv/subdiv.h" +#include "phantom/resample/resample.h" + +#include "phantom/interface.h" + +//#include "bts/image/expected/buffer.h" + +namespace BTS { + + namespace Fibre { + + + const Coord Tractlet::FILE_SEPARATOR = Triple (-INFINITY, -INFINITY, -INFINITY); + const std::string Tractlet::FILE_EXTENSION = "tct"; + + const char* Tractlet::PROPS_LIST[] = { Object::ACS_SQRT_PROP, PROPS_LIST_END }; + + const double Tractlet::STRANDS_PER_AREA_DEFAULT = 1000; + + const double Tractlet::REASONABLE_WIDTH = 0.1; + + + +// Tractlet::Tractlet (std::vector axes, double base_width, double acs) +// +// : acs(acs), base_width(base_width), axes(axes) { +// +// if (axes.size() != 3) +// throw Exception ("axes must be of length 3 (one for each spatial dimension)."); +// +// if (axes[1].degree() != axes[0].degree() || axes[2].degree() != axes[0].degree()) +// throw Exception ("axes degrees do not match {" + str(axes[0].degree()) + ", " + str(axes[1].degree()) + ", " + str(axes[2].degree()) +"}"); +// +// this->axes[1][0].normalise(); +// this->axes[2][0].normalise(); +// +// init(); +// +// } + + + + Tractlet::Tractlet (Track t, size_t degree, double width) + : Base::Object((size_t)3, 3 * degree, select_props(*t.props)), dgree(degree) { + + from_track(t, degree, width); + + for (size_t prop_i = 0; prop_i < num_props(); ++prop_i) + prop(prop_i) = t.prop(t.prop_key(prop_i)); + + } + + + Tractlet::Tractlet(const Strand& s, double width) + : Base::Object((size_t)3, 3 * s.degree(), select_props(*s.props)), dgree(s.degree()) { + + from_track(Track(s, Track::NUM_LENGTH_SECTIONS_DEFAULT), s.degree(), width); + + for (size_t prop_i = 0; prop_i < num_props(); ++prop_i) + prop(prop_i) = s.prop(s.prop_key(prop_i)); + + } + + + void Tractlet::from_track(Track primary_axis, size_t degree, double width) { + + //acs(acs), base_width(1.0), axes(3) { + + //Requires a bit of stuffing around changing formats to use subdiv function from NFG suite. + Fibre::Track::Set tcks(1, primary_axis.num_points()), subdivided; + tcks[0] = primary_axis.base(); + + std::vector > pre_points; + std::vector > post_points; + + ::Strand_collection c, subdivided_c;//; + + ::generate_pre_points(tcks, pre_points); + + ::generate_post_points(tcks, post_points); + + //Assign the radius of the primary axis to be that of the desired width. + tcks.add_extend_elem_prop(BTS::Fibre::Track::RADIUS_PROP, str(width)); + + ::convert_mr_to_nfg(&c, tcks, pre_points, post_points); + + //Subdivide the strand so that 7 subdivided strands are in place of the original axis. + ::subdivide_collection(&subdivided_c, &c, width/2.0001); + + ::convert_nfg_to_mr(subdivided, pre_points, post_points, &subdivided_c); + + //Convert subdivided back into strands. + Strand::Set subdiv_strands = subdivided.to_strands(degree); + + Strand ax1_max = (subdiv_strands[0] + subdiv_strands[1])/2.0; + Strand ax2_max = subdiv_strands[2]; + + operator[](0) = primary_axis.base().to_strand(degree); + + operator[](1) = ax1_max - operator[](0); + operator[](2) = ax2_max - operator[](0); + + for (size_t prop_i = 0; prop_i < num_props(); ++prop_i) + prop(prop_i) = primary_axis.prop(prop_key(prop_i)); + + } + + + std::vector Tractlet::cross_sectional_areas(size_t num_points) const { + + std::vector areas(num_points); + + // Get tangents to the primary path of the tractlet at 'num_points' along its path. + Fibre::Track primary_tang = operator[](0).to_tangents(num_points); + + // Get the extent of the auxiliary axis at 'num_points' along its path. + Fibre::Track aux_disp_1 = operator[](1).to_track(num_points); + Fibre::Track aux_disp_2 = operator[](2).to_track(num_points); + + for (size_t point_i = 0; point_i < num_points; ++point_i) { + + // Get the normal to the oval defined by the two auxiliary axes at tau=point_i/num_points along the tractlet, + // scaled by the oval's area. + Coord area_normal = (M_PI / 4.0) * aux_disp_1[point_i].cross(aux_disp_2[point_i]); + + // Normalise the tangent of the primary axis at the current point (!note that it is done in place as it is not used again). + const Coord norm_tangent = primary_tang[point_i].normalise(); + + // Get the component of the ovals area that is perpendicular to the tractlet's primary + areas[point_i] = MR::Math::abs(area_normal.dot(norm_tangent)); + + } + + return areas; + + } + + + + + + //Ensure that tractlets do not pass through themselves + Tractlet& Tractlet::sanitize() { + + Coord primary = operator[](0)[1]; + Coord norm_primary = primary; + + if (norm_primary.norm() != 0) { + + norm_primary.normalise(); + + + std::vector > perps(2); + + //Get the component of the first axis that is perpendicular to the primary orientation + perps[0] = operator()(0,0) - norm_primary * operator()(0,0).dot(norm_primary); + + //Get the component of the first axis that is perpendicular to both the primary orientation and first axis + Triple perp2_orient = perps[0].cross(primary).normalise(); + + perps[1] = perp2_orient * operator[](2)[0].dot(perp2_orient); + + for (size_t ax_i = 1; ax_i < 3; ++ax_i) { + + Coord base = operator[](ax_i)[0]; + Coord perp = perps[ax_i-1]; + + if (perp.norm() < REASONABLE_WIDTH) { + base -= perp; + perp *= REASONABLE_WIDTH / perp.norm(); + base += perp; + } + + for (size_t degree_i = 1; degree_i < degree(); ++degree_i) + for (size_t dim_i = 0; dim_i < 3; ++dim_i) { + + double& higher = operator[](ax_i)[degree_i][dim_i]; + double ref = abs(perp[dim_i] / M_SQRT2); + + //If the higher degree is larger than the base degree reset it to be less than the base degree, + //while preserving end points. + if (abs(higher) > 1.8 * ref) + higher = Math::sign(higher) * ref * 0.9; + else if (abs(higher) > abs(perp[dim_i])) + higher = Math::sign(higher) * (abs(higher) - abs(perp[dim_i])); + + } + + } + + } + + return *this; + + } + + + void Tractlet::add_section_gradient(const Tractlet& tractlet, const Section& section, const Strand::BasicSection& gradient) { + + + Strand pos_gradient = Strand::outer_product(section.position_coeffs, gradient.position()); + + //Add position gradient. + operator[](0) += pos_gradient; + operator[](1) += pos_gradient * section.ax1_fraction; + operator[](2) += pos_gradient * section.ax2_fraction; + + //Add tangent gradient. + + Strand tang_gradient = Strand::outer_product(section.tangent_coeffs, gradient.tangent() * section.length_fraction); + + operator[](0) += tang_gradient; + operator[](1) += tang_gradient * section.ax1_fraction; + operator[](2) += tang_gradient * section.ax2_fraction; + + + if (has_var_acs()) { + + if (true) { + + throw Exception ("tied_width gradient needs to be adjusted after accounting for tractlet sheer."); + + acs_sqrt() += gradient.intensity() * (tractlet[1][0].norm() * tractlet[2][0].norm() - tractlet[1][0].dot(tractlet[2][0])); + operator()(1,0) += gradient.intensity() * tractlet.acs() * (tractlet[1][0] * (tractlet[2][0].norm() / tractlet[1][0].norm()) - tractlet[2][0]); + operator()(2,0) += gradient.intensity() * tractlet.acs() * (tractlet[2][0] * (tractlet[1][0].norm() / tractlet[2][0].norm()) - tractlet[1][0]); + + } else + acs_sqrt() += gradient.intensity(); + } + + + } + + + size_t Tractlet::num_width_strands(size_t num_width_sections) { + + double width_fraction = 1.0 / (double)num_width_sections; + + size_t num_strands = 0; + + for (double ax1_frac = (-1.0 + width_fraction); ax1_frac < 1.0; ax1_frac += 2.0 * width_fraction) + for (double ax2_frac = (-1.0 + width_fraction); ax2_frac < 1.0; ax2_frac += 2.0 * width_fraction) + if (MR::Math::pow2(ax1_frac) + MR::Math::pow2(ax2_frac) <= (1.0 - width_fraction / 2.0)) + ++num_strands; + + return num_strands; + + } + + + std::vector& Tractlet::sections(std::vector& sections, + size_t num_length_sections, + size_t num_width_sections, + const Triple& vox_lengths, + const Triple& offsets, + size_t num_encodings) const { + + + sections.resize(total_num_sections(num_length_sections, num_width_sections), Tractlet::Section(num_encodings)); + + double length_fraction = 1.0 / (double)num_length_sections; + double width_fraction = 1.0 / (double)num_width_sections; + + const MR::Math::Matrix& position_matrix = Strand::position_matrix(num_length_sections, this->degree()); + const MR::Math::Matrix& tangent_matrix = Strand::tangent_matrix(num_length_sections, this->degree()); + + size_t section_count = 0; + //Loop over length of tractlet. + for (size_t section_i = 0; section_i < num_length_sections; section_i++) { + + // Loop across cross-section of tractlet. Loop each perturbation axis from a 'width_fraction' from -1 to a width_fraction + // from +1, in intervals of 2*width_fraction's. It is performed this way because each section is to represent the + // tractlet +- a width fraction in both directions about its centre ('position'). + for (double ax1_frac = (-1.0 + width_fraction); ax1_frac < 1.0; ax1_frac += 2.0 * width_fraction) { + + for (double ax2_frac = (-1.0 + width_fraction); ax2_frac < 1.0; ax2_frac += 2.0 * width_fraction) { + + // Include section if the "coordinate" consisting of the combined fractions along each perturbation axes lies + // within the unit circle minus a half a width_fraction. This will give the resulting cross-sections an + // elliptical shape (or circular if axes are equal). + if (MR::Math::pow2(ax1_frac) + MR::Math::pow2(ax2_frac) <= (1.0 - width_fraction / 2.0)) { + + sections[section_count].set(*this, position_matrix.row(section_i), tangent_matrix.row(section_i), ax1_frac, ax2_frac, length_fraction, width_fraction); + sections[section_count].normalize(vox_lengths, offsets); + + ++section_count; + + } + + } + + } + + } + + return sections; + + } + + + Strand::Set Tractlet::to_strands(size_t num_width_sections) const { + + Strand::Set strands(std::vector(), this->prop_keys()); + + double width_fraction = 1.0 / (double)num_width_sections; + + // Loop across cross-section of tractlet. Loop each perturbation axis from a 'width_fraction' from -1 to a width_fraction + // from +1, in intervals of 2*width_fraction's. It is performed this way because each strand is to represent the + // tractlet +- a width_fraction radius about it. + for (double ax1_frac = (-1.0 + width_fraction); ax1_frac < 1.0; ax1_frac += 2.0 * width_fraction) { + + for (double ax2_frac = (-1.0 + width_fraction); ax2_frac < 1.0; ax2_frac += 2.0 * width_fraction) { + + //Include section if coord consisting of the combined fractions along each perturbation axes lies within the + // unit circle minus a half a width_fraction. This will give the resulting cross-sections an elliptical + // shape (or circular if axes are equal). + if (MR::Math::pow2(ax1_frac) + MR::Math::pow2(ax2_frac) <= (1.0 - width_fraction /2.0)) { + Strand s(degree(), this->prop_keys()); + s.base() = operator[](0) + operator[](1) * ax1_frac + operator[](2) * ax2_frac; + for (size_t prop_i = 0; prop_i < num_props(); ++prop_i) + s.prop(prop_i) = prop(prop_i); + strands.push_back(s); + } + + } + + } + + return strands; + + } + + + Strand::Set Tractlet::to_strands(double strands_per_acs) const { + + double num_strands = strands_per_acs * acs(); + + size_t num_width_sections = (size_t)MR::Math::round(MR::Math::sqrt(num_strands * 4.0 / M_PI)); + + return to_strands(num_width_sections); + + } + + + + Tractlet Tractlet::flip() const { + + Tractlet t(*this); + + for (size_t ax_i = 0; ax_i < 3; ax_i++) + t[ax_i] = operator[](ax_i).flip(); + + return t; + + } + + + Tractlet Tractlet::switch_axes() const { + + Tractlet t(*this); + + t[1] = operator[](2); + t[2] = operator[](1); + + return t; + + } + + + Tractlet Tractlet::invert_axis(size_t ax_i) const { + + assert(ax_i == 1 || ax_i == 2); + + Tractlet t(*this); + + t[ax_i] = operator[](ax_i) * -1; + + return t; + + } + + + double Tractlet::distance(const Tractlet& reference, double strands_per_acs) const { + + double dist; + + if (strands_per_acs <= 0.0) { + + bool flipped; + bool switched; + bool invert1; + bool invert2; + + dist = distance(reference,flipped,switched,invert1, invert2); + + } else { + + Strand::Set this_strands = to_strands(strands_per_acs); + Strand::Set reference_strands = reference.to_strands(strands_per_acs); + + if (this_strands.size() > reference_strands.size()) + dist = reference_strands.distance(this_strands); + else + dist = this_strands.distance(reference_strands); + + } + + return dist; + + } + + + double Tractlet::distance(const Tractlet& reference, bool& flipped, bool& switched, bool& invert1, bool& invert2) const { + + double min_dist = INFINITY; + + //There are four ambiguities in the Tractlet model: + // - Flipping the direction of the sections + // - Switching the two axes + // - Inverting the first axis + // - Inverting the second axis + // Each combination is checked to see which is the minimal distance. + + flipped = false; + switched = false; + invert1 = false; + invert2 = false; + + for (size_t invt1 = 0; invt1 <= 1; ++invt1) + for (size_t invt2 = 0; invt2 <= 1; ++invt2) + for (size_t flip = 0; flip <= 1; ++flip) + for (size_t swtch = 0; swtch <= 1; ++swtch) { + + Tractlet modified (reference); + + if (invt1) + modified = modified.invert_axis(1); + + if (invt2) + modified = modified.invert_axis(2); + + if (flip) + modified = modified.flip(); + + if (swtch) + modified = modified.switch_axes(); + + double dist = (*this - modified).norm2(); + + if (dist < min_dist) { + min_dist = dist; + flipped = flip; + switched = swtch; + invert1 = invt1; + invert2 = invt2; + } + + } + + return min_dist; + + } + + + Tractlet Tractlet::smallest_distance_set(const Tractlet& reference) const { + + bool flipped; + bool switched; + bool invert1; + bool invert2; + + distance(reference, flipped, switched, invert1, invert2); + + Tractlet t (*this); + + if (invert1) + t = t.invert_axis(1); + + if (invert2) + t = t.invert_axis(2); + + if (flipped) + t = t.flip(); + + if (switched) + t = t.switch_axes(); + + return t; + + } + + + double Tractlet::rotation() const { + + + std::pair< Triple, Triple > ax1_endpoints = Strand(operator[](1)).endpoints(); + std::pair< Triple, Triple > ax2_endpoints = Strand(operator[](2)).endpoints(); + + Triple start = (ax1_endpoints.first.normalise() + ax2_endpoints.first.normalise()) / 2.0; + Triple finish = (ax1_endpoints.second.normalise() + ax2_endpoints.second.normalise()) / 2.0; + + Triple primary_orient = operator[](0)[1]; + primary_orient.normalise(); + + start = start - start.dot(primary_orient) * primary_orient; + finish = finish - finish.dot(primary_orient) * primary_orient; + + start.normalise(); + finish.normalise(); + + Triple sign_vec = start.cross(finish).normalise() - primary_orient; + + double sign; + if (sign_vec.norm() > 1.0) + sign = 1.0; + else + sign = -1.0; + + return MR::Math::acos(start.dot(finish)/(finish.norm() * start.norm())) * sign; + + + return start.angle(finish); + + } + + + //!Resizes each of the 3 axes to the new degree value. + void Tractlet::redegree(size_t new_degree, double default_value) { + + Tractlet new_tractlet (new_degree, *this->props); + new_tractlet.zero(); + + for (size_t ax_i = 0; ax_i < degree(); ++ax_i) + for (size_t degree_i = 0; degree_i < degree(); ++degree_i) + new_tractlet(ax_i,degree_i) = operator()(ax_i,degree_i); + + *this = new_tractlet; + + } + + + Tractlet operator+ (double c, Tractlet t) { return t + c; } + + + Tractlet operator* (double c, Tractlet t) { return t * c; } + + + std::ostream& operator<< (std::ostream& stream, const Tractlet& tractlet) { + + + if (tractlet.has_var_acs()) + stream << "acs: " << tractlet.acs() << std::endl; + + stream << std::endl; + + for (size_t axis_i = 0; axis_i < 3; axis_i++) + stream << "axis " + str(axis_i) + ": " << std::endl << tractlet[axis_i] << std::endl; + + return stream; + + } + + + //!Only implemented for resizing empty tractlets and for use in general template functions. + void Tractlet::resize(size_t num_axes, const Strand& default_value) { + + size_t old_size = size(); + + resize(num_axes); + + for (size_t ax_i = old_size; ax_i < num_axes; ++ax_i) + operator[](ax_i) = default_value; + + } + + + Tractlet& Tractlet::push_back(const Strand& strand) { + + if (!dgree) + dgree = strand.degree(); + else if (dgree != strand.degree()) + throw Exception ("Attempting to push a strand of degree " + str(strand.degree()) + " on a tractlet of degree " + str(dgree) + "."); + + assert(bsize() % dgree == 0); + + size_t strand_i = bsize() / (dgree * 3); + + if (strand_i > 2) + throw Exception ("Attempting to push a fourth strand onto an already created tractlet."); + + resize(strand_i+1); + MR::Math::Vector::sub(strand_i * dgree * 3, (strand_i+1) * dgree * 3) = strand; + + return *this; + + } + + + } + +} diff --git a/src/bts/fibre/tractlet.h b/src/bts/fibre/tractlet.h new file mode 100644 index 0000000..f9f17ca --- /dev/null +++ b/src/bts/fibre/tractlet.h @@ -0,0 +1,318 @@ +/* + Copyright 2010 Brain Research Institute/National ICT Australia (NICTA), Melbourne, Australia + + Written by Thomas G Close, 5/05/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + +*/ + +#ifndef __bts_fibre_tractlet_h__ +#define __bts_fibre_tractlet_h__ + + +#include + +#include "math/matrix.h" + +#include "bts/common.h" +#include "bts/file.h" + +#include "bts/coord.h" +#include "bts/fibre/strand.h" +#include "bts/fibre/base/reader.h" +#include "bts/fibre/base/writer.h" + + + +namespace BTS { + + namespace Fibre { + + class Tractlet : public Base::Object { + + // Nested classes and typedefs. + public: + + typedef Strand Element; + + class Set; + class Section; + class Tensor; + class Walker; + + typedef Base::Reader Reader; + typedef Base::Writer Writer; + + typedef Base::TextReader TextReader; + typedef Base::TextWriter TextWriter; + + friend class Object; + friend class Track; + friend class Strand; + friend class Set; + friend class Base::Set; + friend class Tensor; + friend class Base::Tensor; + friend class Base::Reader; + friend class Base::Writer; + friend class Base::Reader; + friend class Base::Writer; + + //Public const static members, + public: + + const static Coord FILE_SEPARATOR; + const static std::string FILE_EXTENSION; + + const static char* BASE_WIDTH_PROP; + + const static double BASE_WIDTH_PROP_DEFAULT; + const static double STRANDS_PER_AREA_DEFAULT; + + const static double REASONABLE_WIDTH; + + const static char* PROPS_LIST[]; + + + //Public static functions + public: + + static size_t num_width_strands(size_t num_width_sections); + + static size_t total_num_sections(size_t num_length_sections, size_t num_width_sections) + { return num_width_strands(num_width_sections) * num_length_sections; } + + + //Protected member variables. + protected: + + size_t dgree; + + //Public member functions. + public: + + Tractlet(size_t degree, const std::vector& props = std::vector()) + : Base::Object (3, degree * 9 + props.size(), props), dgree(degree) {} + + //TODO: Try to make protected by making Base::Reader a friend + public: + + Tractlet(const std::vector& props = std::vector()) + : Base::Object(3, 0, props), dgree(0) {} + + public: + + Tractlet(const Tractlet& t) + : Base::Object(t), dgree(t.dgree) {} + + ~Tractlet() {} + + Tractlet& operator= (const Tractlet& t) + { Base::Object::operator=(t); dgree = t.dgree; return *this; } + + Tractlet (const Strand& s, double width); + + Tractlet (Track primary_axis, size_t degree, double width); + + protected: + + /*! Used by Base::Set::operator[]() to initiate a from a section of a larger state vector or + * by Base::Tensor::row/column() for a slice of the tensor matrix. + * + * @param degree Degree of the tractlet + * @param view The view onto the larger vector or matrix + * @param props The properties stored in the set or tensor + */ + Tractlet(size_t degree, const MR::Math::Vector::View& view, std::vector* props) + : Base::Object((size_t)3, view, props), dgree(degree) {} + + void from_track(Track primary_axis, size_t degree, double width); + + public: + + + Strand operator[](size_t index) + { assert(index < 3); return Strand(dgree, sub(index * degree() * 3, (index+1) * degree() * 3), &EMPTY_PROPS); } + + Strand operator[](size_t index) const + { assert(index < 3); return Strand(dgree, sub(index * degree() * 3, (index+1) * degree() * 3), &EMPTY_PROPS); } + + Coord operator()(size_t axis_i, size_t degree_i) { + assert(axis_i < 3); assert(bsize() % dgree == 0); assert(bsize() / 9 == dgree); + return Coord(sub((axis_i * degree() + degree_i) * 3, (axis_i * degree() + degree_i) * 3 + 3)); + } + + const Coord operator()(size_t axis_i, size_t degree_i) const { + assert(axis_i < 3); assert(bsize() % dgree == 0); assert(bsize() / 9 == dgree); + return Coord(sub((axis_i * degree() + degree_i) * 3, (axis_i * degree() + degree_i) * 3 + 3)); + } + + //!Resizes each of the 3 axes to the new degree value. + void redegree(size_t new_degree, double default_value = NAN); + + double acs() const + { return has_prop(ACS_SQRT_PROP) ? MR::Math::pow2(prop(ACS_SQRT_PROP)) : 1.0; /* The ACS is stored in the state vector via its squareroot to prevent it from becoming < 0 */} + + void add_acs(double acs = 1.0) + { add_prop(ACS_SQRT_PROP, acs); } + + void set_acs(double acs) + { assert(acs >= 0); prop(ACS_SQRT_PROP) = MR::Math::sqrt(acs); } //sqrt is stored instead of straight value to prevent ACS becoming < 0 during iterative methods + + void remove_acs() + { remove_prop(ACS_SQRT_PROP); } + + bool has_var_acs() const + { return has_prop(ACS_SQRT_PROP); } + + double& acs_sqrt() + { assert(has_var_acs()); return prop(ACS_SQRT_PROP); } + + double acs_sqrt() const + { assert(has_var_acs()); return prop(ACS_SQRT_PROP); } + + //Ensure that tractlets do not pass through themselves + Tractlet& sanitize(); + + std::vector cross_sectional_areas(size_t num_points) const; + + Tractlet base() + { return Tractlet(dgree, sub(0,bsize()), &EMPTY_PROPS); } + + const Tractlet base() const + { return Tractlet(dgree, sub(0,bsize()), &EMPTY_PROPS); } + + Strand backbone() const + { return Strand(dgree, sub(0, dgree*3), &EMPTY_PROPS); } + + + std::vector
& sections( std::vector
& sections, + size_t num_length_sections, + size_t num_width_sections, + const Triple& vox_lengths = Triple::Ones, + const Triple& offsets = Triple::Zeros, + size_t num_encodings = 0) const; + + + /*!Section positions are normalized to the image so that the bottom-left-back (the minimal coordinate point) + corner is mapped to [0,0,0] and the voxel sizes are normalized to [1,1,1] so the inverse voxel lengths are required to calculate the gradient*/ + void add_section_gradient(const Tractlet& tractlet, const Section& section, const Strand::BasicSection& gradient); + + + + BASE_GENERAL_FUNCTIONS(Tractlet); + + + BASE_MULT_DIVIDE_FUNCTIONS(Tractlet); + + + BASE_ADD_SUBTRACT_FUNCTIONS(Tractlet); + + + + /*! Returns the degree of the tractlet (as determined by the size of the base vector divided by 3) + * + * @return The degree of the tractlet + */ + size_t degree() const + { return dgree; } + + /*! Projects extends or trims the primary axis so that its endpoints lie on the sphere. + * + * @return The degree of the tractlet + */ + void project_to_sphere(double sphere_radius) + { operator[](0).project_to_sphere(sphere_radius); } + + + Strand::Set to_strands(size_t num_samples) const; + + + Strand::Set to_strands(double strands_per_acs) const; + + + double distance(const Tractlet& reference, bool& flipped, bool& switched, bool& invert1, bool& invert2) const; + + /*!If 'num_strands' argument is non-zero, instead of measuring the distance between parameters, + the distance between generated strands is calculated instead*/ + double distance(const Tractlet& reference, double strands_per_acs = 0.0) const; + + + Tractlet smallest_distance_set(const Tractlet& reference) const; + + + //Doesn't actually effect the shape of the tract only the direction it travels. + Tractlet flip() const; + + //Doesn't actually effect the shape of the tract only the order of its secondary axes. + Tractlet switch_axes() const; + + //Doesn't actually effect the shape of the tract only the sign of its secondary axes. + Tractlet invert_axis(size_t axis_i) const; + + + double rotation() const; + + + //! Only included to get template function to work (a strand will never have element properties. + Tractlet& push_back(const Strand& strand, bool without_properties) + { return push_back(strand); } + + protected: + + void clear() + { Object::clear(); dgree = 0; } + + void clear(const std::vector& properties) + { Object::clear(properties); dgree = 0; } + + /*! Only used in reader as tractlets should always only have 3 strands. Is only named push_back to fit in + * with other object classes. NB: This function doesn't actually resize the tractlet class (because, as + * mentioned above, it always has 3 strands) but checks to see which of its strands are still invalidated (set + * to NAN) + * + * @param strand The strand to be "pushed" onto the back of the strand. + * @return + */ + + Tractlet& push_back(const Strand& strand); + + + //TODO: work out how to remove this function + //!Only implemented for resizing empty tractlets and for use in general template functions. + void resize(size_t num_axes, const Strand& default_value); + + + //TODO: work out how to remove this function + //!Only implemented for resizing empty tractlets and for use in general template functions. + void resize(size_t num_axes, double fill_value = NAN) + { Base::Object::resize(num_axes, dgree * 3, fill_value); } + + + friend std::ostream& operator<< (std::ostream& stream, const Tractlet& tractlet); + + }; + + Tractlet operator+ (double c, Tractlet t); + Tractlet operator* (double c, Tractlet t); + + + } +} + + +#endif diff --git a/src/bts/fibre/tractlet/section.cpp b/src/bts/fibre/tractlet/section.cpp new file mode 100644 index 0000000..cafdc22 --- /dev/null +++ b/src/bts/fibre/tractlet/section.cpp @@ -0,0 +1,51 @@ +/* + Copyright 2010 Brain Research Institute/National ICT Australia (NICTA), Melbourne, Australia + + Written by Thomas G Close, 5/05/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + +*/ + +#include "bts/fibre/tractlet.h" + +#include "bts/fibre/tractlet/section.h" + + + +namespace BTS { + + namespace Fibre { + + const std::string Tractlet::Section::FILE_EXTENSION = "tsc"; + const Coord Tractlet::Section::FILE_SEPARATOR = Coord (-INFINITY, NAN, NAN); + + + std::ostream& operator<< (std::ostream& stream , const BTS::Fibre::Tractlet::Section& section) { + + stream << (const Fibre::Strand::BasicSection&)section; + + stream << "width1: " << section.width1() << std::endl; + stream << "witdh2: " << section.width2() << std::endl; + + return (stream); + + } + + + + } +} diff --git a/src/bts/fibre/tractlet/section.h b/src/bts/fibre/tractlet/section.h new file mode 100644 index 0000000..89c3167 --- /dev/null +++ b/src/bts/fibre/tractlet/section.h @@ -0,0 +1,170 @@ +/* + Copyright 2010 Brain Research Institute/National ICT Australia (NICTA), Melbourne, Australia + + Written by Thomas G Close, 5/05/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + +*/ + +#ifndef __bts_fibre_tractlet_section_h__ +#define __bts_fibre_tractlet_section_h__ + +#include "bts/fibre/tractlet.h" +#include "bts/fibre/strand/section.h" + +namespace BTS { + + namespace Fibre { + + + class Tractlet::Section : public Strand::Section { + + public: + + //TODO: Work out how to do this more elegantly +// class Tensor; + + typedef Fibre::Base::Reader
Reader; + typedef Fibre::Base::Writer
Writer; + + public: + + const static std::string FILE_EXTENSION; + const static Coord FILE_SEPARATOR; + + public: + + //Reference data. Used in working backwards to calculate gradient. + double ax1_fraction; //The fraction of the section along axis1 (from -1 to 1) + double ax2_fraction; //The fraction of the section along axis2 (from -1 to 1) + double width_fraction; + + //TODO: Remove this reference. + const Tractlet* parent; + + public: + + Section (const MR::Math::Vector::View& view, std::vector* props) + : Strand::Section((size_t)4, view, props) {} + + Section(size_t init_precalc_size = 0) + : Strand::Section((size_t)4, PROPS, init_precalc_size), ax1_fraction(NAN), ax2_fraction(NAN), width_fraction(NAN) {} + + Section(const Tractlet& tractlet, + const MR::Math::Vector::View& position_coeffs, + const MR::Math::Vector::View& tangent_coeffs, + double ax1_fraction, + double ax2_fraction, + double length_fraction, + double width_fraction, + size_t init_precalc_size = 0) + + : Strand::Section(init_precalc_size) + + { + + set(tractlet, + position_coeffs, + tangent_coeffs, + ax1_fraction, + ax2_fraction, + length_fraction, + width_fraction); + + } + + + void set(const Tractlet& tractlet, + const MR::Math::Vector::View& position_coeffs, + const MR::Math::Vector::View& tangent_coeffs, + double ax1_fraction, + double ax2_fraction, + double length_fraction, + double width_fraction) + { + + Strand::Section::set(tractlet.acs(), position_coeffs, tangent_coeffs, length_fraction); + + this->ax1_fraction = ax1_fraction; + this->ax2_fraction = ax2_fraction; + this->width_fraction = width_fraction; + + width1() = tractlet[1].left_product(position_coeffs); + width2() = tractlet[2].left_product(position_coeffs); + + position() = tractlet[0].left_product(position_coeffs) + ax1_fraction * width1() + ax2_fraction * width2(); + + width1() *= width_fraction; + width2() *= width_fraction; + + tangent() = (tractlet[0].left_product(tangent_coeffs) + + ax1_fraction * tractlet[1].left_product(tangent_coeffs) + + ax2_fraction * tractlet[2].left_product(tangent_coeffs)) * length_fraction; + + this->parent = &tractlet; + + } + + + Section(const Section& s) + : Strand::Section(s), + ax1_fraction(s.ax1_fraction), + ax2_fraction(s.ax2_fraction), + parent(s.parent) {} + + + Section& operator= (const Section& s) + { this->Strand::Section::operator=(s); ax1_fraction= s.ax1_fraction; ax2_fraction = s.ax2_fraction; parent = s.parent; return *this; } + + + ~Section() {} + + + Coord width1() + { return Coord(MR::Math::Vector::sub(6,9)); } + + Coord width1() const + { return Coord(MR::Math::Vector::sub(6,9)); } + + Coord width2() + { return Coord(MR::Math::Vector::sub(9,12)); } + + Coord width2() const + { return Coord(MR::Math::Vector::sub(9,12)); } + + + BASE_GENERAL_FUNCTIONS(Section); + + BASE_MULT_DIVIDE_FUNCTIONS(Section); + + BASE_ADD_SUBTRACT_FUNCTIONS(Section); + + }; + + + + inline Tractlet::Section operator* (double scalar, const Tractlet::Section& section) + { return section * scalar; } + + + std::ostream& operator<< (std::ostream& stream , const BTS::Fibre::Tractlet::Section& section); + + } +} + + +#endif diff --git a/src/bts/fibre/tractlet/section/tensor.cpp b/src/bts/fibre/tractlet/section/tensor.cpp new file mode 100644 index 0000000..6d62e29 --- /dev/null +++ b/src/bts/fibre/tractlet/section/tensor.cpp @@ -0,0 +1,65 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, 16/08/2010. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + +//#ifndef __bts_fibre_tractlet_section_tensor_cpp_h__ +//#define __bts_fibre_tractlet_section_tensor_cpp_h__ + +//#include "bts/fibre/tractlet/section/tensor.h" +//#include "bts/fibre/strand/basic_section/tensor.h" +// +//namespace BTS { +// +// namespace Fibre { +// +//// +//// Tractlet::Section::Tensor& Tractlet::Section::Tensor::operator= (const Strand::BasicSection::Tensor& tensor) { +//// +//// zero(); +//// +//// acs.position = tensor.acs.position; +//// acs.tangent = tensor.acs.tangent; +//// +//// position[X].position = tensor.position[X].position; +//// position[Y].position = tensor.position[Y].position; +//// position[Z].position = tensor.position[Z].position; +//// +//// tangent[X].position = tensor.tangent[X].position; +//// tangent[Y].position = tensor.tangent[Y].position; +//// tangent[Z].position = tensor.tangent[Z].position; +//// +//// position[X].tangent = tensor.position[X].tangent; +//// position[Y].tangent = tensor.position[Y].tangent; +//// position[Z].tangent = tensor.position[Z].tangent; +//// +//// tangent[X].tangent = tensor.tangent[X].tangent; +//// tangent[Y].tangent = tensor.tangent[Y].tangent; +//// tangent[Z].tangent = tensor.tangent[Z].tangent; +//// +//// return *this; +//// +//// } +// +// } +// +//} + +//#endif /* __bts_fibre_tractlet_section_tensor_cpp_h__ */ diff --git a/src/bts/fibre/tractlet/section/tensor.h b/src/bts/fibre/tractlet/section/tensor.h new file mode 100644 index 0000000..6e78900 --- /dev/null +++ b/src/bts/fibre/tractlet/section/tensor.h @@ -0,0 +1,157 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Tractlet::Sectionhomas G Close, 07/08/2010. + + Tractlet::Sectionhis file is part of MRtrix. + + MRtrix 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. + + MRtrix is distributed in the hope that it will be useful, + but WITractlet::SectionHOUTractlet::Section ANY WARRANTractlet::SectionY; without even the implied warranty of + MERCHANTractlet::SectionABILITractlet::SectionY or FITractlet::SectionNESS FOR A PARTractlet::SectionICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with MRtrix. If not, see . + +*/ + +//#ifndef __bts_fibre_tractlet_section_tensor_h__ +//#define __bts_fibre_tractlet_section_tensor_h__ +// +// +//#include "bts/fibre/tractlet/section.h" +//#include "bts/fibre/strand/basic_section/tensor.h" +// +//#include "bts/fibre/tensor/writer.h" +// +//namespace BTS { +// +// namespace Fibre { +// +//// class Tractlet::Section::Tensor : public Strand::BasicSection::Tensor_tpl { +//// +//// public: +//// +//// typedef Fibre::Tensor::Writer Writer; +//// typedef Tractlet::Section ColumnClass; +//// +//// public: +//// +//// Element width1; +//// Element width2; +//// +//// public: +//// +//// //Default argument is to get section to work with macro in test_gradient.cpp +//// Tensor() {} +//// +//// +//// Tensor(const Tensor& s) +//// : Strand::BasicSection::Tensor_tpl(s), width1(s.width1), width2(s.width2) {} +//// +//// +//// Tensor& operator= (const Tensor& s) +//// { Strand::BasicSection::Tensor_tpl::operator=(s); width1 = s.width1; width2 = s.width2; return *this; } +//// +//// Tensor& operator=(const Strand::BasicSection::Tensor& t); +//// +//// ~Tensor() {} +//// +//// +//// Tensor& zero() +//// { Strand::BasicSection::Tensor_tpl::zero(); width1.zero(); width2.zero(); return *this; } +//// +//// +//// Tensor& invalidate() +//// { Strand::BasicSection::Tensor_tpl::invalidate(); width1.invalidate(); width2.invalidate(); return *this; } +//// +//// +//// +//// Tractlet::Section get_diagonal() const +//// { throw Exception ("Not implemented yet."); return Tractlet::Section(); } +//// +//// +//// void set_diagonal(const Tractlet::Section& section) +//// { throw Exception ("Not implemented yet."); } +//// +//// +//// //---------------------------------------------------------------// +//// // Generic Functions (NB: Can be removed in production versions) // +//// //---------------------------------------------------------------// +//// +//// // Tractlet::Sectionhe following generic functions are used in 'Fibre::Base::Writer/Reader' and 'Analysis::ContainerTractlet::Sectionester', +//// // which are in turn used in 'test_gradient.cpp' to check gradient calculations. +//// +//// //Public static members and typedefs +//// public: +//// +//// //For debugging purposes only. +//// Element& operator[] (size_t index) { +//// +//// switch (index) { +//// case 0: return position; +//// case 1: return tangent; +//// case 2: return width1; +//// case 3: return width2; +//// default: throw Exception ("Index, " + str(index) + ", is out of bounds (4)."); +//// } +//// +//// } +//// +//// const Element& operator[] (size_t index) const { +//// +//// switch (index) { +//// case 0: return position; +//// case 1: return tangent; +//// case 2: return width1; +//// case 3: return width2; +//// default: throw Exception ("Index, " + str(index) + ", is out of bounds (4)."); +//// } +//// +//// } +//// +//// Tensor& operator*= (double scalar) +//// { Strand::BasicSection::Tensor_tpl::operator*=(scalar); width1 *= scalar; width2 *= scalar; return *this; } +//// +//// +//// size_t size() const { return 4; } +//// void clear() { count = 0; } +//// +//// void push_back(Element& t) { +//// +//// switch (count++) { +//// case 0: position = t; break; +//// case 1: tangent = t; break; +//// case 2: width1 = t; break; +//// case 3: width2 = t; break; +//// default: throw Exception ("Attempting to add a fifth triple to Tractlet::Section (max 4)."); +//// } +//// +//// } +//// +//// +//// }; +//// +//// +//// inline std::ostream& operator<< (std::ostream& stream, const Tractlet::Section::Tensor& seg) { +//// +//// stream << "Intensity: " << seg.intensity << std::endl; +//// stream << "Position: " << seg.position << std::endl; +//// stream << "Tangent: " << seg.tangent << std::endl; +//// stream << "Width1: " << seg.width1 << std::endl; +//// stream << "Width2: " << seg.width2 << std::endl; +//// +//// return stream; +//// +//// } +// +// } +// +//} +// +//#endif /* __bts_fibre_tractlet_section_tensor_h__ */ diff --git a/src/bts/fibre/tractlet/set.cpp b/src/bts/fibre/tractlet/set.cpp new file mode 100644 index 0000000..946a55a --- /dev/null +++ b/src/bts/fibre/tractlet/set.cpp @@ -0,0 +1,675 @@ +/* + Copyright 2010 Brain Research Institute/National ICT Australia (NICTA), Melbourne, Australia + + Written by Thomas G Close, 5/05/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + +*/ + +#include + +#include "bts/common.h" +#include "bts/math/svd.h" + +#include "bts/fibre/tractlet.h" +#include "bts/fibre/track/set.h" +#include "bts/fibre/tractlet/set.h" +#include "bts/fibre/strand/set.h" + +#include "bts/fibre/properties/extended.h" + +#include "bts/fibre/base/reader.cpp.h" +#include "bts/fibre/base/writer.cpp.h" + +namespace BTS { + + namespace Fibre { + + const std::string Tractlet::Set::FILE_EXTENSION = "tst"; + + const char* Tractlet::Set::PROPS_LIST[] = { Base::Set::BASE_INTENSITY_PROP, PROPS_LIST_END }; + + + + Tractlet::Set::Set(const Strand::Set& strands) + : Fibre::Base::Set( select_props(*strands.props), + select_props(*strands.elem_props), + strands.get_extend_props()) { + + from_strands(strands); + + } + + + //TODO: Look into preallocating for speed + Tractlet::Set::Set(const Strand::Set& strands, double width) + : Fibre::Base::Set( select_props(*strands.props), + select_props(*strands.elem_props), + strands.get_extend_props()) { + + from_strands(strands,width); + + } + + + //TODO: Look into preallocating for speed + Tractlet::Set::Set(const Strand::Set& strands, size_t num_tractlets, const std::string& cluster_save_location) + : Fibre::Base::Set( select_props(*strands.props), + select_props(*strands.elem_props), + strands.get_extend_props()) { + + from_strands(strands,num_tractlets,cluster_save_location); + + } + + + Tractlet::Set::Set (const Track::Set& strands, size_t degree) + : Fibre::Base::Set(select_props(*strands.props), + select_props(*strands.elem_props), + strands.get_extend_props()) { + + from_strands(Strand::Set(strands, degree)); + + } + + + //TODO: Look into preallocating for speed + Tractlet::Set::Set (const Track::Set& tcks, size_t degree, size_t num_tractlets, const std::string& cluster_save_location) + : Fibre::Base::Set(select_props(*tcks.props), + select_props(*tcks.elem_props), + tcks.get_extend_props()) { + + from_strands(Strand::Set(tcks, degree), num_tractlets, cluster_save_location); + + } + + + //TODO: Look into preallocating for speed + Tractlet::Set::Set (const Track::Set& tcks, size_t degree, double width) + : Fibre::Base::Set( select_props(*tcks.props), + select_props(*tcks.elem_props), + tcks.get_extend_props()) { + + from_strands(Strand::Set(tcks),width); + + + } + + + + void Tractlet::Set::from_strands(const Strand::Set& strands) { + + if (!strands.has_extend_elem_prop(BUNDLE_INDEX_EPROP)) + throw Exception ("'" + BUNDLE_INDEX_EPROP + "' property was not found in strand set, which is required for conversion to tractlet set."); + + add_extend_elem_prop(BUNDLE_INDEX_EPROP,"-1"); + + std::set bundle_indices; + + //Get a list of bundle indices present in the current set. + for (size_t strand_i = 0; strand_i < strands.size(); ++strand_i) + bundle_indices.insert(to(strands.get_extend_elem_prop(BUNDLE_INDEX_EPROP, strand_i))); + + //Loop through the strand set and convert each bundle into a separate tractlet. + for (std::set::iterator bundle_it = bundle_indices.begin(); bundle_it != bundle_indices.end(); ++bundle_it) { + + Strand::Set bundle_strands(std::vector(), *strands.elem_props); + + //TODO: Maybe look into preallocating the size of the strand set to avoid repeated 'push_back' calls. + for (size_t strand_i = 0; strand_i < strands.size(); ++strand_i) + if (to(strands.get_extend_elem_prop(BUNDLE_INDEX_EPROP, strand_i)) == *bundle_it) + bundle_strands.push_back(strands[strand_i]); + + size_t num_strands = bundle_strands.size(); + + bundle_strands = bundle_strands.shortest_span(); + + Strand centroid; + centroid = bundle_strands[0]; + centroid.zero(); + + for (size_t strand_i = 0; strand_i < bundle_strands.size(); ++strand_i) + centroid += bundle_strands[strand_i]; + + centroid /= (double)num_strands; + + Tractlet tractlet(centroid.degree(), select_props(centroid.prop_keys())); + + for (size_t prop_i = 0; prop_i < tractlet.num_props(); ++prop_i) + tractlet.prop(prop_i) = centroid.prop(tractlet.prop_key(prop_i)); + + tractlet[0] = centroid.base(); + + + if (num_strands == 1) { + //Get width axes perpendicular to the main orientation and each other. + Coord ax1_basewidth = centroid[1].cross(centroid[1].min_axis()).normalise(); + Coord ax2_basewidth = centroid[1].cross(ax1_basewidth).normalise(); + + tractlet[1][0] = ax1_basewidth * Tractlet::REASONABLE_WIDTH; + tractlet[2][0] = ax2_basewidth * Tractlet::REASONABLE_WIDTH; + + + } else if (num_strands == 2) { + + Strand ax1 = bundle_strands[0] - centroid; + + Coord ax2_basewidth = centroid[1].cross(ax1[1]).normalise() * Tractlet::REASONABLE_WIDTH; + + tractlet[1] = ax1; + tractlet[2][0] = ax2_basewidth; + + } else { + + //Set up the difference matrix which holds the difference between each strand and the centroid. + + size_t num_rows = num_strands; + if (centroid.bsize() > num_strands) + num_rows = centroid.bsize(); //If vector size of strands is less than number in bundle the difference matrix is padded out with zeros; + + MR::Math::Matrix diff_matrix (num_rows, centroid.bsize()); + diff_matrix = 0; + + for (size_t strand_i = 0; strand_i < num_strands; ++strand_i) { + + diff_matrix.row(strand_i) = bundle_strands[strand_i].base(); + diff_matrix.row(strand_i) -= centroid.base(); + + } + + //Perform singular value decomposition to get the two axes that describe the most variance. + Math::USV usv = Math::svd(diff_matrix); + + tractlet[1] = usv.v.column(0); + tractlet[2] = usv.v.column(1); + + //Calculate the RMS of projections onto the two axes. + double rms_proj1 = 0.0; + double rms_proj2 = 0.0; + + for (size_t strand_i = 0; strand_i < num_strands; ++strand_i) { + + rms_proj1 += MR::Math::pow2(dot(diff_matrix.row(strand_i), tractlet[1])); + rms_proj2 += MR::Math::pow2(dot(diff_matrix.row(strand_i), tractlet[2])); + + } + + rms_proj1 /= (double)num_strands; + rms_proj2 /= (double)num_strands; + + rms_proj1 = MR::Math::sqrt(rms_proj1); + rms_proj2 = MR::Math::sqrt(rms_proj2); + + // Multiply the RMS projections by two to get the extent of the tractlet along each axes + // (Assumes that the strand bundle is rougly circular w.r.t to the two axes) + tractlet[1] *= rms_proj1 * 2.0; + tractlet[2] *= rms_proj2 * 2.0; + + } + + tractlet.sanitize(); + + //Keep the bundle index property (so it keeps the same colour in the plotting routines). + std::map properties_row; + properties_row[BUNDLE_INDEX_EPROP] = str(*bundle_it); + + push_back(tractlet, properties_row); + + } + + for (size_t prop_i = 0; prop_i < num_props(); ++prop_i) + prop(prop_i) = strands.prop(prop_key(prop_i)); + + + if (!strands.var_elem_degrees()) + freeze_elem_degree(); + + + //TODO: Look into automatically trying to fix degree of tractlet set after conversion. + + } + + + void Tractlet::Set::from_strands(const Strand::Set& set, size_t num_tractlets, + const std::string& cluster_save_location) { + + if (num_tractlets) { + Strand::Set set_copy(set); + set_copy.cluster(num_tractlets); + + if (cluster_save_location.size()) + set_copy.save(cluster_save_location); + + from_strands(set_copy); + } else + from_strands(set); + + } + + + void Tractlet::Set::from_strands (const Strand::Set& set, double width) { + + for (size_t strand_i = 0; strand_i < set.size(); ++strand_i) + push_back(Tractlet(set[strand_i], width)); + + for (size_t prop_i = 0; prop_i < num_props(); ++prop_i) + prop(prop_i) = set.prop(prop_key(prop_i)); + + copy_extend_elem_props(set); + + if (has_extend_elem_prop(Fibre::Track::RADIUS_PROP)) + remove_extend_elem_prop(Fibre::Track::RADIUS_PROP); + + if (!set.var_elem_degrees()) + freeze_elem_degree(); + + + } + + +// +// //FIXME: Will not work yet +// Tractlet::Set::Set(const Strand::Set& set) { +// +// +// if (!set.has_extend_elem_prop(BUNDLE_INDEX_EPROP)) +// throw Exception ("'" + BUNDLE_INDEX_EPROP + "' property was not found in strand set, which is required for conversion to tractlet set."); +// +// add_extend_elem_prop(BUNDLE_INDEX_EPROP,"-1"); +// +// std::set bundle_indices; +// +// //Get a list of bundle indices present in the current set. +// for (size_t strand_i = 0; strand_i < set.size(); ++strand_i) +// bundle_indices.insert(to(set.get_extend_elem_prop(BUNDLE_INDEX_EPROP, strand_i))); +// +// //Loop through the strand set and convert each bundle into a separate tractlet. +// for (std::set::iterator bundle_it = bundle_indices.begin(); bundle_it != bundle_indices.end(); ++bundle_it) { +// +// Fibre::Strand::Set bundle_strands; +// +// for (size_t strand_i = 0; strand_i < set.size(); ++strand_i) +// if (to(set.get_extend_elem_prop(BUNDLE_INDEX_EPROP, strand_i)) == *bundle_it) +// bundle_strands.push_back(operator[](strand_i)); +// +// size_t num_strands = bundle_strands.size(); +// +// bundle_strands = bundle_strands.shortest_span(); +// +// Fibre::Strand centroid; +// centroid.zero(); +// +// for (size_t strand_i = 0; strand_i < bundle_strands.size(); ++strand_i) +// centroid += bundle_strands[strand_i]; +// +// centroid /= (double)num_strands; +// +// Fibre::Tractlet tractlet(centroid.degree()); +// tractlet.zero(); +// tractlet.set_acs(centroid.acs()); +// tractlet[0] = centroid; +// +// +// if (num_strands == 1) { +// //Get width axes perpendicular to the main orientation and each other. +// Coord ax1_basewidth = centroid[1].cross(centroid[1].min_axis()).normalise(); +// Coord ax2_basewidth = centroid[1].cross(ax1_basewidth).normalise(); +// +// tractlet[1][0] = ax1_basewidth * Tractlet::REASONABLE_WIDTH; +// tractlet[2][0] = ax2_basewidth * Tractlet::REASONABLE_WIDTH; +// +// +// } else if (num_strands == 2) { +// +// Strand ax1 = bundle_strands[0] - centroid; +// +// Coord ax2_basewidth = centroid[1].cross(ax1[1]).normalise() * Tractlet::REASONABLE_WIDTH; +// +// tractlet[1] = ax1; +// tractlet[2][0] = ax2_basewidth; +// +// } else { +// +// //Set up the difference matrix which holds the difference between each strand and the centroid. +// +// size_t vector_size = centroid.vsize(); +// +// size_t num_rows = num_strands; +// if (vector_size > num_strands) +// num_rows = vector_size; //If vector size of strands is less than number in bundle the difference matrix is padded out with zeros; +// +// MR::Math::Matrix diff_matrix (num_rows, vector_size); +// diff_matrix = 0; +// +// for (size_t strand_i = 0; strand_i < num_strands; ++strand_i) { +// +// diff_matrix.row(strand_i) = bundle_strands[strand_i]; +// diff_matrix.row(strand_i) -= centroid; +// +// } +// +// //Perform singular value decomposition to get the two axes that describe the most variance. +// Math::USV usv = Math::svd(diff_matrix); +// +// MR::Math::Vector axis1 = usv.v.column(0); +// MR::Math::Vector axis2 = usv.v.column(1); +// +// +// //Calculate the RMS of projections onto the two axes. +// double rms_proj1 = 0.0; +// double rms_proj2 = 0.0; +// +// for (size_t strand_i = 0; strand_i < num_strands; ++strand_i) { +// +// rms_proj1 += MR::Math::pow2(dot(diff_matrix.row(strand_i), axis1)); +// rms_proj2 += MR::Math::pow2(dot(diff_matrix.row(strand_i), axis2)); +// +// } +// +// rms_proj1 /= (double)num_strands; +// rms_proj2 /= (double)num_strands; +// +// rms_proj1 = MR::Math::sqrt(rms_proj1); +// rms_proj2 = MR::Math::sqrt(rms_proj2); +// +// // Multiply the RMS projections by two to get the extent of the tractlet along each axes +// // (Assumes that the strand bundle is rougly circular w.r.t to the two axes) +// tractlet[1] *= rms_proj1 * 2.0; +// tractlet[2] *= rms_proj2 * 2.0; +// +// } +// +// tractlet.sanitize(); +// +// //Keep the bundle index property (so it keeps the same colour in the plotting routines). +// std::map properties_row; +// properties_row[BUNDLE_INDEX_EPROP] = str(*bundle_it); +// +// push_back(tractlet, properties_row); +// +// } +// +// copy_props(set); +// copy_relevant_elem_props(set); +// +// +// } + + + + Track::Set Tractlet::Set::to_tracks(size_t num_length_sections, size_t num_width_sections) const { + + return Track::Set(*this, num_length_sections, num_width_sections); + + } + + + Track::Set Tractlet::Set::to_tracks(size_t num_length_sections, double strands_per_acs) const { + + return Track::Set(*this, num_length_sections, strands_per_acs); + + } + + + Strand::Set Tractlet::Set::to_strands(size_t num_samples) const { + + return Strand::Set(*this, num_samples); + + } + + + Strand::Set Tractlet::Set::to_strands(double strands_per_vol) const { + + return Strand::Set(*this, strands_per_vol); + + } + + + std::vector& Tractlet::Set::append_characteristic_property_keys(std::vector& header) { + + header.push_back("tract_volume"); + + return header; + + } + + + Tractlet::Set& Tractlet::Set::sanitize() { + + for (size_t tract_i = 0; tract_i < size(); ++tract_i) + operator[](tract_i).sanitize(); + + return *this; + + } + + + void Tractlet::Set::calc_characteristic_properties() { + + // Do nothing. + + } + + + void Tractlet::Set::load(const std::string& location, size_t degree, size_t num_tractlets) { + + this->clear(); + + if (File::has_or_txt_extension(location)) { + + this->Base::Set::load(location); + + } else if (File::has_or_txt_extension(location) || File::has_or_txt_extension(location)) { + + Strand::Set strands (location, degree); + + if (num_tractlets) + operator=(strands.to_tractlets(num_tractlets)); + else if (strands.has_extend_elem_prop(Track::BUNDLE_INDEX_EPROP)) + operator=(strands.to_tractlets()); + else + throw Exception(" \"-width\" parameter is required for implicit conversion to tractlet set ('" + location + "') if '" + Track::BUNDLE_INDEX_EPROP + "' property is not present."); + + } else + throw Exception("The extension of file \"" + location + "\" is not a recognised type (\"" + Tractlet::FILE_EXTENSION + "\", \"" + Strand::FILE_EXTENSION + "\" or \"" + Track::FILE_EXTENSION + "\")."); + + } + + + void Tractlet::Set::save(const std::string& location, size_t num_length_sections, double strands_per_acs) const { + + if (File::has_or_txt_extension(location)) { + + this->Base::Set::save(location); + + } else if (File::has_or_txt_extension(location)) { + + if (strands_per_acs <= 0.0) + throw Exception(" \"-strands_per_acs\" parameter is required for implicit conversion to strand set ('" + location + "')."); + + Strand::Set strands = this->to_strands(strands_per_acs); + + strands.save(location); + + } else if (File::has_or_txt_extension(location)) { + + if (num_length_sections == 0) + throw Exception(" \"-num_length_sections\" parameter is required for implicit conversion to track set ('" + location + "')."); + + if (strands_per_acs <= 0.0) + throw Exception(" \"-strands_per_acs\" parameter is required for implicit conversion to track set ('" + location + "')."); + + Track::Set tcks = this->to_tracks(num_length_sections, strands_per_acs); + + tcks.save(location); + + } else + throw Exception("The extension of file \"" + location + "\" is not a recognised type (\"" + Tractlet::FILE_EXTENSION + "\" or \"" + Strand::FILE_EXTENSION + "\")."); + + } + + + + void Tractlet::Set::project_to_sphere(double sphere_radius) { + + for (size_t tract_i = 0; tract_i < size(); ++tract_i) + operator[](tract_i).project_to_sphere(sphere_radius); + + } + + + + Strand::Set Tractlet::Set::backbones() const { + + Strand::Set strands(size(), degree()); + for (size_t tractlet_i = 0; tractlet_i < size(); tractlet_i++) + strands[tractlet_i] = operator[](tractlet_i).backbone(); + + strands.copy_props(*this); + strands.copy_relevant_elem_props(*this); + + return strands; + } + + + Tractlet::Set Tractlet::Set::permute(const std::vector& indices) const { + + if (var_elem_degrees()) + throw Exception ("'permute' is currently not implemented for variable element size sets."); + + Set permuted_set (size(), degree(), *props, *elem_props, get_extend_props()); + + this->Fibre::Base::Set::permute(permuted_set, indices); + + return permuted_set; + + } + + + size_t Tractlet::Set::max_degree() const { + + size_t max_degree = 0; + + for (size_t tract_i = 0; tract_i < size(); ++tract_i) + if (operator[](tract_i).degree() > max_degree) + max_degree = operator[](tract_i).degree(); + + return max_degree; + + } + + + + std::string Tractlet::Set::matlab_str() const { + + std::stringstream ss; + + ss << "{ 'b_intens', " << base_intensity() << ", "; + + for (size_t tractlet_i = 0; tractlet_i < size(); tractlet_i++) { + + ss << "{ 'acs', " << operator[](tractlet_i).acs() << ", "; + + for (size_t ax_i = 0; ax_i < 3; ax_i++) { + + ss << "["; + + for (size_t degree_i = 0; degree_i < operator[](tractlet_i)[ax_i].size(); degree_i++) { + + for (size_t dim_i = 0; dim_i < 3; dim_i++) + ss << operator[](tractlet_i)[ax_i][degree_i][dim_i] << " "; + + if (degree_i != 2) + ss << "; "; + } + + ss << "]"; + + if (tractlet_i != 2) + ss << ", "; + + } + + ss << "}"; + + if (tractlet_i != (size() -1)) + ss << ", "; + } + + ss << "}"; + + return ss.str(); + + } + + Tractlet::Set Tractlet::Set::peel(double distance, size_t num_length_sections, size_t num_width_sections, bool to_cube) const { + + Tractlet::Set include; + + include.set_extend_prop("peel_distance", str(distance)); + + if (to_cube) + include.set_extend_prop("peel_shape", "cube"); + else + include.set_extend_prop("peel_shape", "sphere"); + + include.add_extend_elem_props(*this); + + + for (size_t tract_i = 0; tract_i < size(); ++tract_i) { + + Track::Set tcks = operator[](tract_i).to_strands(num_width_sections).to_tracks(num_length_sections); + + bool in_roi = false; + + for (size_t tck_i = 0; tck_i < tcks.size(); ++tck_i) { + for (size_t point_i = 0; point_i < tcks[tck_i].num_points(); point_i++) { + + Track tck = tcks[tck_i]; + + if (to_cube) { + if ((abs(tck[point_i][X]) <= distance) && (abs(tck[point_i][Y]) <= distance) && (abs(tck[point_i][Z]) <= distance)) { + in_roi = true; + break; + } + } else { + if (tck[point_i].norm() <= distance) { + in_roi = true; + break; + } + } + } + + if (in_roi) + break; + } + + if (in_roi) + include.push_back(operator[](tract_i), get_extend_elem_prop_row(tract_i)); + + } + + include.copy_props(*this); + include.copy_relevant_elem_props(*this); + + return include; + } + + + } + +} diff --git a/src/bts/fibre/tractlet/set.h b/src/bts/fibre/tractlet/set.h new file mode 100644 index 0000000..a58f545 --- /dev/null +++ b/src/bts/fibre/tractlet/set.h @@ -0,0 +1,268 @@ +/* + Copyright 2010 Brain Research Institute/National ICT Australia (NICTA), Melbourne, Australia + + Written by Thomas G Close, 5/05/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + +*/ + +#include "bts/fibre/base/set.h" + + +#ifndef __bts_fibre_tractlet_set_h__ +#define __bts_fibre_tractlet_set_h__ + +#include + +#include "bts/fibre/track.h" +#include "bts/fibre/tractlet.h" +#include "bts/fibre/base/set_reader.h" +#include "bts/fibre/base/set_writer.h" + +#include "bts/common.h" +#include "bts/file.h" + + +#include "bts/math/munkres.h" + +#include "k_means/KMlocal.h" // k-means algorithms + +#define LOOP(op) \ + for (size_t tractlet_i = 0; tractlet_i < size(); ++tractlet_i) { op } + +namespace BTS { + + namespace Fibre { + + class Tractlet::Set : public Base::Set { + + //Public nested classes and typedefs + public: + + class Walker; + class Momentum; + typedef Base::Tensor Tensor; + typedef Base::SetReader Reader; + typedef Base::SetWriter Writer; + + typedef Base::SetTextReader TextReader; + typedef Base::SetTextWriter TextWriter; + + friend class Object; + friend class Base::Tensor; + friend class Base::SetReader; + friend class Base::SetWriter; + friend class Track::Set; + friend class Strand::Set; + + public: + + std::vector& append_characteristic_property_keys(std::vector& header); + + + //Public static constants + public: + + const static std::string FILE_EXTENSION; + + protected: + + const static char* PROPS_LIST[]; + + //Public methods; + public: + + /*! Initialises a tractlet set with variable tractlet sizes, without base intensity or tractlet intensities + * + * @param extended_props The extended properties of the set + */ + Set (const std::map& extended_props = std::map()) + : Base::Set(std::vector(), std::vector(), extended_props) {} + + + /*! Initialises a tractlet set with variable strand sizes, with properties element propertiess + * + * @param props The set properties + * @param elem_props The element properties + * @param extended_props The extended properties of the set + */ + Set (const std::vector& props, const std::vector& elem_props, const std::map& extended_props = std::map()) + : Base::Set(props, elem_props, extended_props) {} + + + /*! Initialises a tractlet set of a preset size with tractlet degree + * + * @param size Size of the tractlet set + * @param degree The (fixed) degree of the the tractlets in the tractlet set (can be freed using the 'free_elem_degree()' function) + * @param extended_props The extended properties of the set + */ + Set (size_t size, size_t degree, const std::map& extended_props = std::map()) + : Base::Set(size, degree, 9 * degree, std::vector(), std::vector(), extended_props) {} + + + /*! Initialises a tractlet set of a preset size with strand degree, with properties and element properties + * + * @param size Size of the tractlet set + * @param props The set properties + * @param elem_props The element properties + * @param degree The (fixed) degree of the the tractlets in the tractlet set (can be freed using the 'free_elem_degree()' function) + * @param extended_props The extended properties of the set + */ + Set (size_t size, size_t degree, const std::vector& props, const std::vector& elem_props, const std::map& extended_props = std::map()) + : Base::Set(size, degree, 9 * degree + elem_props.size(), props, elem_props, extended_props) {} + + + Set (std::string file_location, size_t degree = 0, size_t num_tractlets = 0) + : Base::Set(std::vector(), std::vector(), std::map()) + { load(file_location, degree, num_tractlets); } + + Set (const Set& s_set) + : Base::Set(s_set) {} + + Set(const Strand::Set& set); + + Set(const Strand::Set& strands, double width); + + Set(const Strand::Set& set, size_t num_tractlets, const std::string& cluster_save_location = ""); + + Set (const Track::Set&, size_t degree); + + Set (const Track::Set& set, size_t degree, double width); + + Set (const Track::Set& set, size_t degree, size_t num_tractlets, const std::string& cluster_save_location = ""); + + + BASE_GENERAL_FUNCTIONS(Set); + + BASE_SET_FUNCTIONS(Set); + + + size_t max_degree() const; + + size_t degree() const + { if (var_elem_degrees()) throw Exception ("Tractlet set has variable rows, so its 'degree' is undefined"); return elem_dgree; } + + void project_to_sphere(double sphere_radius); + + void load(const std::string& location, size_t degree = 0, size_t num_tractlets = 0); + + void save(const std::string& location, size_t num_length_sections = 0, double strands_per_acs = -1.0) const; + + void save(const std::string& location, double strands_per_acs) const + { save(location, 0, strands_per_acs); } + + //!Converts to a constant number of strands per tractlet + Strand::Set to_strands(size_t num_length_sections) const; + + //!Converts to a constant number of strands per tractlet cross-sectional area + Strand::Set to_strands(double strands_per_acs) const; + + Track::Set to_tracks(size_t num_length_sections, size_t num_width_sections) const; + + Track::Set to_tracks(size_t num_length_sections, double strands_per_acs) const; + + Tractlet::Set peel(double inclusion_radius, size_t num_length_sections, size_t num_width_sections, bool to_cube = false) const; + + Strand::Set backbones() const; + + Tractlet::Set& sanitize(); + + Set permute(const std::vector& indices) const; + + Set smallest_distance_set(const Set& reference) + { Set smallest; Base::Set::smallest_distance_set(reference, smallest); return smallest; } + + Set& operator+= (const Set& set) + { Base::Set::operator+=(set); return *this; } + + Set& operator-= (const Set& set) + { Base::Set::operator-=(set); return *this; } + + Set& operator*= (const Set& set) + { Base::Set::operator*=(set); return *this; } + + Set& operator*= (double c) + { Base::Set::operator*=(c); return *this; } + + Set& operator/= (const Set& set) + { Base::Set::operator/=(set); return *this; } + + Set& operator/= (double c) + { Base::Set::operator/=(c); return *this; } + + Set operator+ (const Set& set) const + { Set answer (*this); answer += set; return answer; } + + Set operator- (const Set& set) const + { Set answer (*this); answer -= set; return answer; } + + Set operator* (const Set& set) const + { Set answer (*this); answer *= set; return answer; } + + Set operator* (double c) const + { Set answer (*this); answer *= c; return answer; } + + Set operator/ (double c) const + { Set answer (*this); answer /= c; return answer; } + + Set operator/ (const Set& set) const + { Set answer (*this); answer /= set; return answer; } + + std::string matlab_str() const; + + void calc_characteristic_properties(); + + private: + + /*! Initiates the tractlet set from a set of strands by first clustering the strands into clusters and then converting + * the clusters into tractlets. + * + * @param strands The strands to be converted + */ + void from_strands(const Strand::Set& strands); + + /*! Initiates the tractlet set from a set of strands by first clustering the strands into a number of clusters + * specified by the @arg num_clusters parameter, and then converting the clusters into tractlets. + * + * @param strands The strands to be converted + * @param num_clusters The number of new clusters to generate + */ + void from_strands(const Strand::Set& strands, size_t num_clusters, const std::string& cluster_save_location = ""); + + + /*! Initiates the tractlet set from a set of strands by converting each strand into a new tractlet with given width + * + * @param strands The strands to be converted + * @param width The width of the new tractlets about the provided strand 'backbones' + */ + void from_strands(const Strand::Set& strands, double width); + + }; + + + inline Tractlet::Set operator* (double c, Tractlet::Set set) { Tractlet::Set answer (set); answer *= c; return answer; } + + + } + +} + +#undef LOOP + +#endif + + diff --git a/src/bts/fibre/tractlet/set/momentum.cpp b/src/bts/fibre/tractlet/set/momentum.cpp new file mode 100644 index 0000000..095941b --- /dev/null +++ b/src/bts/fibre/tractlet/set/momentum.cpp @@ -0,0 +1,72 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, Aug 2, 2010. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + +#include "bts/fibre/tractlet/set/momentum.h" + + + + +namespace BTS { + + namespace Fibre{ + + const double Tractlet::Set::Momentum::STEP_SCALE_DEFAULT = 1.0; + const char* Tractlet::Set::Momentum::STEP_LOCATION_DEFAULT = "/home/tclose/data/mcmc/hamiltonian/params/stepsizes/default.tct"; + + Tractlet::Set::Momentum Tractlet::Set::Momentum::factory( const Set& state, + double step_scale, + const std::string& step_location, + MCMC::Proposal::Distribution* const proposal_distribution) { + Fibre::Tractlet::Set step; + + if (step_location.size()) { + step.load(step_location); + + //If the loaded step only contains one strand use this as the template for the whole set + if (step.size() == 1) { + Fibre::Tractlet::Set full_step(state.size(), state.degree()); + full_step.copy_props(step); + full_step.copy_elem_props(step); + + for (size_t elem_i = 0; elem_i < state.size(); ++elem_i) + full_step[elem_i] = step[0]; + + step = full_step; + + } + + else if (step.size() != state.size()) + throw Exception ("Loaded step sizes' size (" + str(step.size()) + ") does not match state (" + str(state.size()) + ")."); + + } else { + step = state; + step.set(step_scale); + } + + + return Fibre::Tractlet::Set::Momentum (proposal_distribution, step); + + } + + } + +} diff --git a/src/bts/fibre/tractlet/set/momentum.h b/src/bts/fibre/tractlet/set/momentum.h new file mode 100644 index 0000000..78ec69d --- /dev/null +++ b/src/bts/fibre/tractlet/set/momentum.h @@ -0,0 +1,90 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, Aug 2, 2010. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + +#ifndef __bts_fibre_tractlet_set_momentum_h__ +#define __bts_fibre_tractlet_set_momentum_h__ + +#include "bts/fibre/tractlet/set.h" +#include "bts/mcmc/proposal/distribution.h" +#include "bts/mcmc/proposal/momentum.h" + +namespace BTS { + + namespace Fibre { + + class Tractlet::Set::Momentum { + + //Public static variables, nested classes and typedefs + public: + + static const double STEP_SCALE_DEFAULT; + static const char* STEP_LOCATION_DEFAULT; + + protected: + + MCMC::Proposal::Momentum mcmc_momentum; + + //Public static functions. + public: + + static Momentum factory( const Set& state, + double step_scale, + const std::string& step_location, + MCMC::Proposal::Distribution* const proposal_distribution); + + + + //Public member functions + public: + + Momentum(MCMC::Proposal::Distribution* const prop_distr = 0) + : mcmc_momentum(prop_distr) {} + + Momentum(MCMC::Proposal::Distribution* const proposal_distribution, + const Set& relative_step_sizes) + + : mcmc_momentum(proposal_distribution, relative_step_sizes) {} + + + void half_update_momentum(const Set& gradient) + { mcmc_momentum.half_update_momentum(gradient); } + + void update_state(Set& state) const + { MR::Math::Vector& state_vector = state; mcmc_momentum.update_state(state_vector); } + + + double predicted_change(const Set& gradient) const + { return mcmc_momentum.predicted_change(gradient); } + + double log_kinetic_energy() const + { return mcmc_momentum.log_kinetic_energy(); } + + void randomize() + { mcmc_momentum.randomize(); } + + }; + + } + +} + +#endif /* __bts_fibre_tractlet_set_momentum_h__ */ diff --git a/src/bts/fibre/tractlet/set/tensor.cpp b/src/bts/fibre/tractlet/set/tensor.cpp new file mode 100644 index 0000000..cd6e7a3 --- /dev/null +++ b/src/bts/fibre/tractlet/set/tensor.cpp @@ -0,0 +1,45 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, 08/08/2010. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + +//#include "bts/fibre/tractlet/set/tensor.h" +// +//namespace BTS { +// +// namespace Fibre { +// +//#ifdef STRUCTURED_SET_TENSOR +// Tractlet::Set::Tensor::Tensor(const Tractlet::Set& default_value) +// : base_intensity(default_value) { +// +// for (size_t elem_i = 0; elem_i < default_value.size(); elem_i++) +// elems.push_back(Tractlet::Tensor_tpl(default_value[elem_i].degree(), default_value)); +// +// this->init(); +// +// } +// +//#endif +// +// } +// +//} + diff --git a/src/bts/fibre/tractlet/set/tensor.h b/src/bts/fibre/tractlet/set/tensor.h new file mode 100644 index 0000000..a0592ed --- /dev/null +++ b/src/bts/fibre/tractlet/set/tensor.h @@ -0,0 +1,214 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, 08/08/2010. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + +//#ifndef __bts_fibre_tractlet_set_tensor_h__ +//#define __bts_fibre_tractlet_set_tensor_h__ +// +//#include "bts/fibre/set/tensor.h" +//#include "bts/fibre/tractlet/set.h" +//#include "bts/fibre/tensor/writer2.h" +// +//namespace BTS { +// +// namespace Fibre { +// +//#ifndef STRUCTURED_SET_TENSOR +// class Tractlet::Set::Tensor : public MR::Math::Matrix { +// +// public: +// +// typedef Fibre::Tensor::Writer2 Writer; +// +// public: +// +// Tensor () {} +// +// Tensor(const Set& default_value) +// : MR::Math::Matrix(default_value.vsize(), default_value.vsize()) { zero(); } +// +// Tensor(const Tensor& t) +// : MR::Math::Matrix(t) {} +// +// ~Tensor() {} +// +// +// Tensor& operator= (const Tensor& t) +// { this->MR::Math::Matrix::operator=(t); return *this; } +// +// +// size_t matrix_length() const +// { return this->rows(); } +// +// +// const MR::Math::Matrix& matrix() const +// { return *this; } +// +// Tensor& zero() +// { MR::Math::Matrix::operator=(0.0); return *this; } +// +// Tensor& invalidate() +// { MR::Math::Matrix::operator=(NAN); return *this; } +// +// void from_matrix(const MR::Math::Matrix& matrix) +// { MR::Math::Matrix::operator=(matrix); } +// +// Tensor& operator+= (const MR::Math::Matrix& tensor) +// { MR::Math::Matrix::operator+=(tensor); return *this; } +// +// Tensor& operator-= (const MR::Math::Matrix& tensor) +// { MR::Math::Matrix::operator-=(tensor); return *this; } +// +// Tensor& operator*= (const MR::Math::Matrix& tensor) +// { MR::Math::Matrix::operator*=(tensor); return *this; } +// +// Tensor& operator*= (double c) +// { MR::Math::Matrix::operator*=(c); return *this; } +// +// Tensor& operator/= (const MR::Math::Matrix& tensor) +// { MR::Math::Matrix::operator/=(tensor); return *this; } +// +// Tensor& operator/= (double c) +// { MR::Math::Matrix::operator/=(c); return *this; } +// +// Tensor operator+ (const MR::Math::Matrix& t) const +// { Tensor answer (*this); answer += t; return answer; } +// +// Tensor operator- (const MR::Math::Matrix& t) const +// { Tensor answer (*this); answer -= t; return answer; } +// +// Tensor operator* (const MR::Math::Matrix& t) const +// { Tensor answer (*this); answer *= t; return answer; } +// +// Tensor operator* (double c) const +// { Tensor answer (*this); answer *= c; return answer; } +// +// Tensor operator/ (const MR::Math::Matrix& t) const +// { Tensor answer (*this); answer /= t; return answer; } +// +// Tensor operator/ (double c) const +// { Tensor answer (*this); answer /= c; return answer; } +// +// }; +// +//// std::ostream& operator<<(std::ostream& stream, const Strand::Set::Tensor& tensor) { +//// +//// stream << "base_intensity: " << tensor.base_intensity << std::endl; +//// +//// for (size_t elem_i = 0; elem_i < tensor.size(); elem_i++) +//// stream << tensor[elem_i] << std::endl; +//// +//// return stream; +//// +//// } +// +//#else +// class Tractlet::Set::Tensor : public Tractlet::Set::Tensor_tpl { +// +// public: +// +// typedef Fibre::Tensor::Writer Writer; +// +// public: +// +// Tensor () {} +// +// Tensor(const Set& default_value) +// : Tensor_tpl(default_value) {} +// +// Tensor(const Tensor_tpl& t) +// : Tensor_tpl(t) {} +// +// ~Tensor() {} +// +// +// Tensor& operator= (const Tensor_tpl& t) +// { Tensor_tpl::operator=(t); return *this; } +// +// +// size_t matrix_length() const +// { return Flattener< Set >::length(*this); } +// +// +// MR::Math::Matrix matrix() const +// { return Flattener< Set >::flatten(*this); } +// +// +// Tensor from_matrix(const MR::Math::Matrix& matrix) +// { return Flattener< Set >::unflatten(matrix, *this); } +// +// Tensor& operator+= (const Tensor& tensor) +// { Tensor_tpl::operator+=(tensor); return *this; } +// +// Tensor& operator-= (const Tensor& tensor) +// { Tensor_tpl::operator-=(tensor); return *this; } +// +// Tensor& operator*= (const Tensor& tensor) +// { Tensor_tpl::operator*=(tensor); return *this; } +// +// Tensor& operator*= (double c) +// { Tensor_tpl::operator*=(c); return *this; } +// +// Tensor& operator/= (const Tensor& tensor) +// { Tensor_tpl::operator/=(tensor); return *this; } +// +// Tensor& operator/= (double c) +// { Tensor_tpl::operator/=(c); return *this; } +// +// Tensor operator+ (const Tensor& t) const +// { Tensor answer (*this); answer += t; return answer; } +// +// Tensor operator- (const Tensor& t) const +// { Tensor answer (*this); answer -= t; return answer; } +// +// Tensor operator* (const Tensor& t) const +// { Tensor answer (*this); answer *= t; return answer; } +// +// Tensor operator* (double c) const +// { Tensor answer (*this); answer *= c; return answer; } +// +// Tensor operator/ (const Tensor& t) const +// { Tensor answer (*this); answer /= t; return answer; } +// +// Tensor operator/ (double c) const +// { Tensor answer (*this); answer /= c; return answer; } +// +// }; +// +// std::ostream& operator<<(std::ostream& stream, const Tractlet::Set::Tensor& tensor) { +// +// stream << "base_intensity: " << tensor.base_intensity << std::endl; +// +// for (size_t elem_i = 0; elem_i < tensor.size(); elem_i++) +// stream << tensor[elem_i] << std::endl; +// +// return stream; +// +// } +// +//#endif +// +// +// } +// +//} +// +//#endif /* __bts_fibre_set_tensor_h__ */ diff --git a/src/bts/fibre/tractlet/set/walker.cpp b/src/bts/fibre/tractlet/set/walker.cpp new file mode 100644 index 0000000..0591fe9 --- /dev/null +++ b/src/bts/fibre/tractlet/set/walker.cpp @@ -0,0 +1,103 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, Aug 2, 2010. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + +#include "bts/fibre/tractlet/set/walker.h" + +namespace BTS { + + namespace Fibre { + + + const char* Tractlet::Set::Walker::TYPE_DEFAULT = "standard"; + const double Tractlet::Set::Walker::STEP_SCALE_DEFAULT = 0.001; + const std::string Tractlet::Set::Walker::STEP_LOCATION_DEFAULT = "/home/tclose/Data/Tractography/fibre/tract/masks/mcmc/metropolis/default.tct"; + + + Tractlet::Set::Walker* Tractlet::Set::Walker::factory(const Tractlet::Set& state, + const std::string& type, + double step_scale, + const std::string& step_location, + MCMC::Proposal::Distribution* distribution, + double base_intens_scale) { + + + + Walker* walker; + + if (type == "standard") { + Fibre::Tractlet::Set step; + + if (step_location.size()) { + step.load(step_location); + + if (step.size() == 1) { + + Fibre::Tractlet step_template = step[0]; + + step.resize(state.size()); + + for (size_t tract_i = 0; tract_i < state.size(); ++tract_i) { + + step[tract_i] = step_template; + + if (state[tract_i].degree() > step_template.degree()) + throw Exception ("Tractlet (" + str(tract_i) + ") is larger than step template."); + else if (state[tract_i].degree() < step_template.degree()) + step[tract_i].redegree(state[tract_i].degree()); + + } + + } else if (step.size() != state.size()) + throw Exception ("Loaded step sizes' size (" + str(step.size()) + ") does not match state (" + str(state.size()) + ")."); + + step *= step_scale; + + } else { + step = state; + step.zero(); + step.set(step_scale); + } + + walker = new Walker (distribution, step); + + } else + + throw Exception ("Unrecognised Fibre::Tractlet::Set::Walker type '" + type + "'."); + + return walker; + + + + } + + + void Tractlet::Set::Walker::step(const Tractlet::Set& current, Tractlet::Set& proposed, double scalar) const { + + MCMC::Proposal::Walker::step(current, proposed, scalar); + + } + + + } + + +} diff --git a/src/bts/fibre/tractlet/set/walker.h b/src/bts/fibre/tractlet/set/walker.h new file mode 100644 index 0000000..cf9ebea --- /dev/null +++ b/src/bts/fibre/tractlet/set/walker.h @@ -0,0 +1,74 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, Aug 2, 2010. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + +#ifndef __bts_fibre_tractlet_set_walker_h__ +#define __bts_fibre_tractlet_set_walker_h__ + +#include "bts/fibre/tractlet/set.h" +#include "bts/fibre/tractlet/walker.h" +#include "bts/mcmc/proposal/walker.h" +#include "bts/mcmc/proposal/distribution.h" + +namespace BTS { + + namespace Fibre { + + class Tractlet::Set::Walker : public MCMC::Proposal::Walker { + + //Public static const members. + public: + + static const char* TYPE_DEFAULT; + static const double STEP_SCALE_DEFAULT; + static const std::string STEP_LOCATION_DEFAULT; + + //Public static member functions. + public: + + static Walker* factory(const Tractlet::Set& state, + const std::string& type, + double step_scale, + const std::string& step_location, + MCMC::Proposal::Distribution* distribution, + double base_intens_scale); + + //Public member functions + public: + + Walker(MCMC::Proposal::Distribution* const proposal_distribution, + const Set& relative_step_sizes) + + : MCMC::Proposal::Walker (proposal_distribution, relative_step_sizes) {} + + virtual ~Walker() {} + + + void step(const Set& current, Set& proposed, double scalar = 1.0) const; + + + }; + + } + +} + +#endif /* __bts_fibre_tractlet_set_walker_h__ */ diff --git a/src/bts/fibre/tractlet/tensor.cpp b/src/bts/fibre/tractlet/tensor.cpp new file mode 100644 index 0000000..664a46f --- /dev/null +++ b/src/bts/fibre/tractlet/tensor.cpp @@ -0,0 +1,165 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, 24/11/2010. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + +#include "bts/fibre/tractlet.h" +#include "bts/fibre/tractlet/tensor.h" +#include "bts/fibre/tractlet/section.h" +#include "bts/fibre/tractlet/section/tensor.h" + + +namespace BTS { + + namespace Fibre { + + void Fibre::Tractlet::Tensor::add_section_hessian(const Tractlet& tractlet, + const Tractlet::Section& section, + const Strand::BasicSection& gradient, + const Strand::BasicSection::Tensor& hessian) { + + + Fibre::Tractlet d2_intensity = get_template(); + + Strand pos_gradient = Strand::outer_product(section.position_coeffs, gradient.position() / section.intensity()); + + if (has_var_acs()) + d2_intensity.set_acs(0.0); + +// d2_intensity.set_base_width(0.0); + + //Add position gradient. + d2_intensity[0] += pos_gradient; + d2_intensity[1] += pos_gradient * section.ax1_fraction; + d2_intensity[2] += pos_gradient * section.ax2_fraction; + + //Add tangent gradient. + + Strand tang_gradient = Strand::outer_product(section.tangent_coeffs, gradient.tangent() * (section.length_fraction / section.intensity())); + + d2_intensity[0] += tang_gradient; + d2_intensity[1] += tang_gradient * section.ax1_fraction; + d2_intensity[2] += tang_gradient * section.ax2_fraction; + + + Fibre::Tractlet acs_gradient = d2_intensity * section.intensity(); + + + if (true) { //Needs some serious rewriting. + + throw Exception ("tied_width hessian needs to be adjusted after accounting for tractlet sheer."); + + double norm1 = tractlet[1][0].norm(); + double norm2 = tractlet[2][0].norm(); + + Coord d_intensity_d1 = tractlet.acs() * ((norm2/norm1) * tractlet(1,0) - tractlet(2,0)); + Coord d_intensity_d2 = tractlet.acs() * ((norm1/norm2) * tractlet(2,0) - tractlet(1,0)); + + for (size_t dim_i1 = 0; dim_i1 < 3; dim_i1++) { + + + operator()(1,0,dim_i1,2,0,dim_i1) -= gradient.intensity() * tractlet.acs(); + operator()(2,0,dim_i1,1,0,dim_i1) -= gradient.intensity() * tractlet.acs(); + + operator()(1,0,dim_i1,1,0,dim_i1) += gradient.intensity() * tractlet.acs() * norm2 / norm1; + operator()(2,0,dim_i1,2,0,dim_i1) += gradient.intensity() * tractlet.acs() * norm1 / norm2; + + + for (size_t dim_i2 = 0; dim_i2 < 3; dim_i2++) { + + + operator()(1,0,dim_i1,1,0,dim_i2) -= tractlet.acs() * gradient.intensity() * tractlet[1][0][dim_i1] * tractlet[1][0][dim_i2] * (norm2 / MR::Math::pow3(norm1)); + operator()(2,0,dim_i1,2,0,dim_i2) -= tractlet.acs() * gradient.intensity() * tractlet[2][0][dim_i1] * tractlet[2][0][dim_i2] * (norm1 / MR::Math::pow3(norm2)); + + operator()(1,0,dim_i1,2,0,dim_i2) += tractlet.acs() * gradient.intensity() * tractlet[2][0][dim_i2] * tractlet[1][0][dim_i1] / (norm1 * norm2); + operator()(2,0,dim_i1,1,0,dim_i2) += tractlet.acs() * gradient.intensity() * tractlet[1][0][dim_i2] * tractlet[2][0][dim_i1] / (norm2 * norm1); + + for (size_t ax_i = 0; ax_i < 3; ++ax_i) + for (size_t degree_i = 0; degree_i < tractlet.degree(); ++degree_i) { + + operator()(ax_i,degree_i,dim_i1,1,0,dim_i2) += tractlet.acs() * d2_intensity(ax_i,degree_i)[dim_i1] * d_intensity_d1[dim_i2]; + operator()(ax_i,degree_i,dim_i1,2,0,dim_i2) += tractlet.acs() * d2_intensity(ax_i,degree_i)[dim_i1] * d_intensity_d2[dim_i2]; + + operator()(1,0,dim_i1,ax_i,degree_i,dim_i2) += tractlet.acs() * d2_intensity(ax_i,degree_i)[dim_i2] * d_intensity_d1[dim_i1]; + operator()(2,0,dim_i1,ax_i,degree_i,dim_i2) += tractlet.acs() * d2_intensity(ax_i,degree_i)[dim_i2] * d_intensity_d2[dim_i1]; + + } + + } + + } + + + if (has_var_acs()) { + acs_gradient(1,0) += gradient.intensity() * d_intensity_d1; + acs_gradient(2,0) += gradient.intensity() * d_intensity_d2; + } + + } + + + if (has_var_acs()) + acs() += acs_gradient; + + + for (size_t degree_i1 = 0; degree_i1 < degree(); degree_i1++) + for (size_t dim_i1 = 0; dim_i1 < 3; dim_i1++) { + + Fibre::Tractlet ax0 = row(0,degree_i1,dim_i1); + Fibre::Tractlet ax1 = row(1,degree_i1,dim_i1); + Fibre::Tractlet ax2 = row(2,degree_i1,dim_i1); + + if (has_var_acs()) { + ax0.acs_sqrt() += acs_gradient.operator()(0,degree_i1)[dim_i1]; + ax1.acs_sqrt() += acs_gradient.operator()(1,degree_i1)[dim_i1]; + ax2.acs_sqrt() += acs_gradient.operator()(2,degree_i1)[dim_i1]; + } + + + for (size_t degree_i2 = 0; degree_i2 < degree(); degree_i2++) + for (size_t dim_i2 = 0; dim_i2 < 3; dim_i2++) { + + double ax0_ax0 = section.position_coeffs[degree_i1] * section.position_coeffs[degree_i2] * hessian.position(dim_i1).position(dim_i2) + + section.position_coeffs[degree_i1] * section.tangent_coeffs[degree_i2] * hessian.position(dim_i1).tangent(dim_i2) * section.length_fraction + + section.tangent_coeffs[degree_i1] * section.position_coeffs[degree_i2] * hessian.tangent(dim_i1).position(dim_i2) * section.length_fraction + + section.tangent_coeffs[degree_i1] * section.tangent_coeffs[degree_i2] * hessian.tangent(dim_i1).tangent(dim_i2) * MR::Math::pow2(section.length_fraction); + + ax0[0][degree_i2][dim_i2] += ax0_ax0; + ax0[1][degree_i2][dim_i2] += ax0_ax0 * section.ax1_fraction; + ax1[0][degree_i2][dim_i2] += ax0_ax0 * section.ax1_fraction; + ax0[2][degree_i2][dim_i2] += ax0_ax0 * section.ax2_fraction; + ax2[0][degree_i2][dim_i2] += ax0_ax0 * section.ax2_fraction; + + ax1[1][degree_i2][dim_i2] += ax0_ax0 * MR::Math::pow2(section.ax1_fraction); + ax1[2][degree_i2][dim_i2] += ax0_ax0 * section.ax1_fraction * section.ax2_fraction; + ax2[1][degree_i2][dim_i2] += ax0_ax0 * section.ax1_fraction * section.ax2_fraction; + + ax2[2][degree_i2][dim_i2] += ax0_ax0 * MR::Math::pow2(section.ax2_fraction); + + } + + + } + + } + + } + +} diff --git a/src/bts/fibre/tractlet/tensor.h b/src/bts/fibre/tractlet/tensor.h new file mode 100644 index 0000000..3577195 --- /dev/null +++ b/src/bts/fibre/tractlet/tensor.h @@ -0,0 +1,137 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, 07/08/2010. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + + + +#ifndef __bts_fibre_tractlet_tensor_h__ +#define __bts_fibre_tractlet_tensor_h__ + + +#include "bts/fibre/tractlet.h" +#include "bts/fibre/base/tensor.h" +#include "bts/fibre/strand/basic_section/tensor.h" + + +namespace BTS { + + namespace Fibre { + + class Tractlet::Tensor : public Base::Tensor { + + + public: + +// typedef Base::TensorWriter Writer; + + //Public member functions + public: + + Tensor() {} + + Tensor(const Tractlet& tractlet_template) + : Base::Tensor(tractlet_template) {} + + + Tensor (const Tractlet& tractlet_template, const MR::Math::Matrix::View& view) + : Base::Tensor(tractlet_template, view) {} + + + Tensor(const Tensor& t) + : Base::Tensor(t) {} + + + Tensor& operator=(const Tensor& t) + { Base::Tensor::operator=(t); return *this; } + + Tensor& operator=(const MR::Math::Matrix& m) + { Base::Tensor::operator=(m); return *this; } + + Tensor& operator=(double c) + { Base::Tensor::operator=(c); return *this; } + + size_t degree() const + { return tmpl.degree(); } + + size_t vsize() const + { return tmpl.vsize(); } + + Tractlet row(size_t idx) + { return Tractlet(degree(), MR::Math::Matrix::row(idx), tmpl.props); } + + const Tractlet row(size_t idx) const + { return Tractlet(degree(), MR::Math::Matrix::row(idx), tmpl.props); } + + Tractlet row(size_t ax_i, size_t degree_i, size_t dim_i) + { return Tractlet(degree(), MR::Math::Matrix::row((ax_i * degree() + degree_i)*3 + dim_i), tmpl.props); } + + const Tractlet row(size_t ax_i, size_t degree_i, size_t dim_i) const + { return Tractlet(degree(), MR::Math::Matrix::row((ax_i * degree() + degree_i)*3 + dim_i), tmpl.props); } + + Tractlet column(size_t idx) + { return Tractlet(degree(), MR::Math::Matrix::column(idx), tmpl.props); } + + const Tractlet column(size_t idx) const + { return Tractlet(degree(), MR::Math::Matrix::column(idx), tmpl.props); } + + bool has_var_acs() const + { return tmpl.has_var_acs(); } + + Tractlet acs() + { assert(has_var_acs()); return Tractlet(degree(), MR::Math::Matrix::row(vsize() + tmpl.prop_index(Object::ACS_SQRT_PROP)), tmpl.props); } + + double& operator()(size_t row_ax_i, + size_t row_degree_i, + size_t row_dim_i, + size_t col_ax_i, + size_t col_degree_i, + size_t col_dim_i) + { return MR::Math::Matrix::operator()(row_ax_i * tmpl.degree() * 3 + row_degree_i * 3 + row_dim_i, col_ax_i * tmpl.degree() * 3 + col_degree_i * 3 + col_dim_i); } + + + double operator()(size_t row_ax_i, + size_t row_degree_i, + size_t row_dim_i, + size_t col_ax_i, + size_t col_degree_i, + size_t col_dim_i) const + { return MR::Math::Matrix::operator()(row_ax_i * tmpl.degree() * 3 + row_degree_i * 3 + row_dim_i, col_ax_i * tmpl.degree() * 3 + col_degree_i * 3 + col_dim_i); } + + Tractlet operator[](size_t idx) + { return Tractlet(degree(), MR::Math::Matrix::row(idx), tmpl.props); } + + const Tractlet operator[](size_t idx) const + { return Tractlet(degree(), MR::Math::Matrix::row(idx), tmpl.props); } + + void add_section_hessian(const Tractlet& tractlet, + const Tractlet::Section& section, + const Strand::BasicSection& gradient, + const Strand::BasicSection::Tensor& hessian); + + }; + + } + +} + +#include "bts/fibre/base/tensor_writer.h" + +#endif /* __bts_fibre_tractlet_tensor_h__ */ diff --git a/src/bts/fibre/tractlet/walker.h b/src/bts/fibre/tractlet/walker.h new file mode 100644 index 0000000..e0bfec1 --- /dev/null +++ b/src/bts/fibre/tractlet/walker.h @@ -0,0 +1,56 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, Aug 2, 2010. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + +#ifndef __bts_fibre_tractlet_walker_h__ +#define __bts_fibre_tractlet_walker_h__ + +#include "bts/fibre/tractlet.h" +#include "bts/mcmc/proposal/walker.h" +#include "bts/mcmc/proposal/distribution.h" + +namespace BTS { + + namespace Fibre { + + class Tractlet::Walker : public MCMC::Proposal::Walker { + + //Public member functions + public: + + Walker(MCMC::Proposal::Distribution* const prop_distr) + : MCMC::Proposal::Walker(prop_distr) {} + + Walker(MCMC::Proposal::Distribution* const proposal_distribution, + const Tractlet& relative_step_sizes) + + : MCMC::Proposal::Walker(proposal_distribution, relative_step_sizes) {} + + virtual ~Walker() {} + + + }; + + } + +} + +#endif /* __bts_fibre_tractlet_walker_h__ */ diff --git a/src/bts/file.cpp b/src/bts/file.cpp new file mode 100644 index 0000000..2c500b8 --- /dev/null +++ b/src/bts/file.cpp @@ -0,0 +1,124 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + +#include + +#include "bts/common.h" +#include "bts/file.h" + + +namespace BTS { + + namespace File { + + std::vector list_filenames(std::string dir_location, std::string prefix, std::string suffix) { + + if (!File::is_dir(dir_location)) + throw MR::Exception("Input location provided " + dir_location + " is not a directory"); + + File::Dir dir(dir_location); + + std::vector filenames; + + std::string filename; + + + while (!(filename = dir.read_name()).empty()) { + + if (filename[0] != '.' && filename.size() - prefix.size() - suffix.size() >= 0) { //If the file is not hidden or has a name shorter than the prefix and suffix combined. + + if (!filename.substr(0,prefix.size()).compare(prefix) && !filename.substr(filename.size() - suffix.size(), filename.size()).compare(suffix)) //If the file matches the prefix and suffix + filenames.push_back(filename); + } + } + + sort(filenames.begin(), filenames.end()); + + return filenames; + + } + + + std::pair split_at_extension (std::string filename) { + + std::pair basename_and_ext; + + size_t extension_i = filename.find_last_of("."); + + if (extension_i == std::string::npos) + basename_and_ext.second = ""; + else + basename_and_ext.second = filename.substr(extension_i); + + basename_and_ext.first = filename.substr(0, extension_i); + + return basename_and_ext; + } + + + void clear_path(const std::string& location) { + + if (File::exists(location)) { + + if (OVERWRITE_FILES) + remove(location.c_str()); + else + throw Exception ("File '" + location + "' exists, if you want to automatically overwrite it set OVERWRITE_FILES to true."); + + } + + } + + + std::string extension(std::string location) { + + std::string file_ext; + + size_t extension_i = location.find_last_of("."); + + if (extension_i == std::string::npos || extension_i == location.size()-1) + file_ext = ""; + else + file_ext = location.substr(extension_i+1); + + return file_ext; + } + + + std::string strip_extension(std::string location) { + + std::string stripped; + + size_t extension_i = location.find_last_of("."); + + if (extension_i == std::string::npos) + stripped = location; + else + stripped = location.substr(0, extension_i); + + return stripped; + } + + + } + +} diff --git a/src/bts/file.h b/src/bts/file.h new file mode 100644 index 0000000..5baff61 --- /dev/null +++ b/src/bts/file.h @@ -0,0 +1,177 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + + +#ifndef __bts_file_h__ +#define __bts_file_h__ + +#include +#include +#include +#include + +//#include "bts/common.h" + +#include "file/path.h" + +#include "exception.h" + + +#include "types.h" + + +namespace BTS { + + namespace File { + + const bool OVERWRITE_FILES = true; + + typedef MR::Path::Dir Dir; + + const std::string TXT_FILE_EXTENSTION = "txt"; + + + inline bool exists(const std::string& path) { return MR::Path::exists(path); } + + + inline void remove(const std::string& location) + { std::remove(location.c_str()); } + + + inline bool is_dir(const std::string path) { return MR::Path::is_dir(path); } + + + inline bool is_file (const std::string path) { return MR::Path::is_file(path); } + + + inline std::string join (const std::string& first, const std::string& second) { return MR::Path::join(first,second); } + + + std::pair split_at_extension (std::string filename); + + + std::string extension(std::string location); + + + std::string strip_extension(std::string location); + + + void clear_path(const std::string& location); + + + inline std::string basename(std::string location) { return MR::Path::basename(location); } + + + inline std::string dirname(std::string location) { return MR::Path::dirname(location); } + + + inline bool has_extension (const std::string& name, const std::string& suffix) + { return MR::Path::has_suffix(name, suffix); } + + + inline bool has_txt_extension (const std::string& name, const std::string& suffix) + { return has_extension(name, TXT_FILE_EXTENSTION) && has_extension(strip_extension(name), suffix); } + + + inline bool has_or_txt_extension (const std::string& name, const std::string& suffix) + { return has_txt_extension(name, suffix) || has_extension(name, suffix); } + + + template bool has_extension(const std::string& location) + { return MR::Path::has_suffix(location, T::FILE_EXTENSION); } + + + template bool has_or_set_extension(const std::string& location) + { return has_extension(location) || has_extension(location); } + + + template bool has_txt_extension (const std::string& name) + { return has_txt_extension(name, T::FILE_EXTENSION); } + + + template bool has_or_txt_extension (const std::string& name) + { return has_or_txt_extension(name, T::FILE_EXTENSION); } + + + template bool has_txt_or_set_extension(const std::string& location) + { return has_or_set_extension(location) || has_or_txt_extension(location); } + + + std::vector list_filenames(std::string dir_location, std::string prefix = std::string(""), std::string suffix = std::string("")); + + + template std::vector& load_vector(std::string location, std::vector& vector) { + + vector.clear(); + + std::ifstream fin (location.c_str()); + + char line[256]; + T t; + while (fin.getline(line, 256)) + vector.push_back(to(line, t)); + + fin.close(); + + return vector; + + } + + + template void save_vector(std::string location, const std::vector& vector) { + + std::ofstream fout (location.c_str()); + + for (size_t i = 0; i < vector.size(); i++) + fout << vector[i] << std::endl; + + fout.close(); + + + } + + + inline void mkdir(const std::string& location, bool make_parents = false) { + + std::string cmd = "mkdir "; + + if (make_parents) + cmd += "-p "; + + cmd += location; + + int failed = system(cmd.c_str()); + + if (failed) + throw MR::Exception ("Could not make directory '" + location + "'."); + + } + + + + + } + +} + +#endif + diff --git a/src/bts/image/buffer.cpp.h b/src/bts/image/buffer.cpp.h new file mode 100644 index 0000000..3f3cef7 --- /dev/null +++ b/src/bts/image/buffer.cpp.h @@ -0,0 +1,346 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, 16/07/2010. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + +#ifndef __image_buffer_tpl_cpp_h__ +#define __image_buffer_tpl_cpp_h__ + +#define LOOP(op) \ +for (int z = 0; z < dims[Z]; z++) { \ + for (int y = 0; y < dims[Y]; y++) { \ + for (int x = 0; x < dims[X]; x++) { \ + op \ + } \ + } \ +} + +namespace BTS { + + namespace Image { + + + template T& Buffer_tpl::operator() (const Index& c) { + + if (enforce_bounds && !in_bounds(c)) + throw Exception ("Coordinate " + str(c) + " is out of image bounds " + str(dimensions) + " (set 'enforce_bounds=false' if this is intentional)."); + + iterator it = voxels.find(c); + + if (it == voxels.end()) + return voxels[c] = new_voxel(c); + else + return it->second; + + } + + + template const T& Buffer_tpl::operator() (const Index& c) const { + + if (enforce_bounds && !in_bounds(c)) + throw Exception ("Coordinate " + str(c) + " is out of image bounds " + str(dimensions) + " (set 'enforce_bounds=false' if this is intentional)."); + + const_iterator it = voxels.find(c); + + if (it == voxels.end()) + throw Exception ("Coordinate " + str(c) + " has not been initialised and can't be since this buffer is const. Suggest using 'is_empty(const Coord&)' to check if it has been initialised first."); + + return it->second; + + } + + + template bool Buffer_tpl::is_empty(const Index& c) const { + + return !voxels.count(c); + + } + + + template template Buffer_tpl& Buffer_tpl::operator+= (const Buffer_tpl& buff) { + + if (dims() != buff.dims()) + throw Exception ("Buffer dimensions do not match, " + str(buff.dims()) + " and " + str(dims()) + "."); + + for (typename Buffer_tpl::const_iterator vox_it = buff.begin(); vox_it != buff.end(); ++vox_it) { + if (!is_empty(vox_it->first)) + this->operator()(vox_it->first) = vox_it->second; + else + this->operator()(vox_it->first) += vox_it->second; + } + + return *this; + + } + + template template Buffer_tpl& Buffer_tpl::operator-= (const Buffer_tpl& buff) { + + if (dims() != buff.dims()) + throw Exception ("Buffer dimensions do not match, " + str(buff.dims()) + " and " + str(dims()) + "."); + + for (typename Buffer_tpl::const_iterator vox_it = buff.begin(); vox_it != buff.end(); ++vox_it) { + + if (!is_empty(vox_it->first)) { + this->operator()(vox_it->first) = vox_it->second; + negate(this->operator()(vox_it->first)); + } else + this->operator()(vox_it->first) -= vox_it->second; + + } + + return *this; + + } + + + + template Buffer_tpl& Buffer_tpl::operator+= (const Buffer_tpl& buff) { + + if (dims() != buff.dims()) + throw Exception ("Buffer dimensions do not match, " + str(buff.dims()) + " and " + str(dims()) + "."); + + for (const_iterator vox_it = buff.begin(); vox_it != buff.end(); ++vox_it) + this->operator()(vox_it->first) += vox_it->second; + + return *this; + + } + + template Buffer_tpl& Buffer_tpl::operator-= (const Buffer_tpl& buff) { + + if (dims() != buff.dims()) + throw Exception ("Buffer dimensions do not match, " + str(buff.dims()) + " and " + str(dims()) + "."); + + for (const_iterator vox_it = buff.begin(); vox_it != buff.end(); ++vox_it) + this->operator()(vox_it->first) -= vox_it->second; + + return *this; + + } + + + template template Buffer_tpl& Buffer_tpl::operator*= (const Buffer_tpl& buff) { + + if (dims() != buff.dims()) + throw Exception ("Buffer dimensions do not match, " + str(buff.dims()) + " and " + str(dims()) + "."); + + for (typename Buffer_tpl::const_iterator vox_it = buff.begin(); vox_it != buff.end(); ++vox_it) { + + if (!is_empty(vox_it->first)) + this->operator()(vox_it->first) *= vox_it->second; + + } + + return *this; + + } + + template template Buffer_tpl& Buffer_tpl::operator/= (const Buffer_tpl& buff) { + + if (dims() != buff.dims()) + throw Exception ("Buffer dimensions do not match, " + str(buff.dims()) + " and " + str(dims()) + "."); + + for (typename Buffer_tpl::const_iterator vox_it = buff.begin(); vox_it != buff.end(); ++vox_it) { + + if (!is_empty(vox_it->first)) + this->operator()(vox_it->first) /= vox_it->second; + + } + + return *this; + + } + + + template Buffer_tpl& Buffer_tpl::negate() { + + for (typename Buffer_tpl::iterator vox_it = this->begin(); vox_it != this->end(); ++vox_it) + vox_it->second.negate(); + + return *this; + + } + + + template Buffer_tpl Buffer_tpl::operator+ (const Buffer_tpl& buff) const { + + Buffer_tpl answer; + + if (this->num_not_empty_voxels() > buff.num_not_empty_voxels()) { + answer = *this; + answer += buff; + } else { + answer = buff; + answer += *this; + } + + return answer; + + } + + + template Buffer_tpl Buffer_tpl::operator- (const Buffer_tpl& buff) const { + + Buffer_tpl answer; + + if (this->num_not_empty_voxels() > buff.num_not_empty_voxels()) { + answer = *this; + answer -= buff; + } else { + answer = buff; + answer -= *this; + } + + return answer; + + } + + + + template Buffer_tpl Buffer_tpl::operator* (const Buffer_tpl& buff) const { + + Buffer_tpl answer; + + if (this->num_not_empty_voxels() > buff.num_not_empty_voxels()) { + answer = *this; + answer *= buff; + } else { + answer = buff; + answer *= *this; + } + + return answer; + + } + + + template Buffer_tpl Buffer_tpl::operator/ (const Buffer_tpl& buff) const { + + Buffer_tpl answer; + + if (this->num_not_empty_voxels() > buff.num_not_empty_voxels()) { + answer = *this; + answer /= buff; + } else { + answer = buff; + answer /= *this; + } + + return answer; + + } + + + template template Buffer_tpl& Buffer_tpl::operator*= (const U& M) { + + for (iterator vox_it = begin(); vox_it != end(); ++vox_it) + vox_it->second *= M; + + return *this; + + } + + + template template Buffer_tpl& Buffer_tpl::operator/= (const U& M) { + + for (iterator vox_it = begin(); vox_it != end(); ++vox_it) + vox_it->second /= M; + + return *this; + + } + + + template std::ostream& operator<< (std::ostream& stream, const Image::Buffer_tpl& B) { + + stream << "Dims: " << B.dims(); + + if (B.enforce_bounds) + stream << " (enforced)"; + + stream << std::endl; + + for (typename Image::Buffer_tpl::const_iterator vox_it = B.begin(); vox_it != B.end(); ++vox_it) + stream << vox_it->first << ": " << vox_it->second; + + return stream; + + } + + + template std::set Buffer_tpl::non_empty() const { + + std::set nempty; + + for (const_iterator vox_it = begin(); vox_it != end(); ++vox_it) + nempty.insert(vox_it->first); + + return nempty; + + } + + template std::set Buffer_tpl::non_empty_or_inbounds() const { + + std::set nempty; + + for (const_iterator vox_it = begin(); vox_it != end(); ++vox_it) + nempty.insert(vox_it->first); + + for (size_t x = 0; x < dim(X); ++x) + for (size_t y = 0; y < dim(Y); ++y) + for (size_t z = 0; z < dim(Z);++z) + nempty.insert(Index(x,y,z)); + + return nempty; + + } + + template std::set Buffer_tpl::empty_inbounds() const { + + std::set empty; + + for (size_t x = 0; x < dim(X); ++x) + for (size_t y = 0; y < dim(Y); ++y) + for (size_t z = 0; z < dim(Z);++z) + if (is_empty(x,y,z)) + empty.insert(Index(x,y,z)); + + return empty; + + } + + + template void Buffer_tpl::clear_and_enforce_bounds() { + + clear(); + + enforce_bounds = true; + + } + + + + + } + +} +#undef LOOP + +#endif /* __image_buffer_tpl_cpp_h__ */ diff --git a/src/bts/image/buffer.h b/src/bts/image/buffer.h new file mode 100644 index 0000000..f658a19 --- /dev/null +++ b/src/bts/image/buffer.h @@ -0,0 +1,359 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + + +#ifndef __bts_image_buffer_h__ +#define __bts_image_buffer_h__ + +namespace BTS { + + namespace Image { + + template class Buffer_tpl; + + } + +} + +#include + +#include "bts/common.h" + +#include "bts/image/index.h" + +#define LOOP(op) \ +for (size_t z = 0; z < this->dim(Z); z++) { \ + for (size_t y = 0; y < this->dim(Y); y++) { \ + for (size_t x = 0; x < this->dim(X); x++) { \ + op \ + } \ + } \ +} + + +namespace BTS { + + namespace Image { + + template std::ostream& operator<<(std::ostream& stream, const Buffer_tpl& B); + + template class Buffer_tpl { + + public: + + typedef typename std::map::iterator iterator; + typedef typename std::map::const_iterator const_iterator; + + + //Protected member variables + protected: + + Triple dimensions; + std::map voxels; + bool enforce_bounds; + + //Public member functions + public: + + Buffer_tpl (bool enforce_bounds = true) + : dimensions(0,0,0), enforce_bounds(enforce_bounds) {} + + + Buffer_tpl (const Triple& dimensions, bool enforce_bounds = true) + : dimensions(dimensions), enforce_bounds(enforce_bounds) {} + + + Buffer_tpl (const Buffer_tpl& B) + : dimensions(B.dims()), voxels(B.voxels), enforce_bounds(B.enforce_bounds) {} + + + ~Buffer_tpl() {} + + + Buffer_tpl& operator= (const Buffer_tpl& B) + { dimensions = B.dimensions; voxels = B.voxels; enforce_bounds = B.enforce_bounds; return *this; } + + + inline T& operator() (int x, int y, int z) + { return operator()(Index(x,y,z)); } + + + inline const T& operator() (int x, int y, int z) const + { return operator()(Index(x,y,z)); } + + + inline T& operator() (const Index& c); + + + inline const T& operator() (const Index& c) const; + + + bool is_empty(size_t x, size_t y, size_t z) const + { return is_empty(Index(x,y,z)); } + + + bool is_empty(const Index& c) const; + + + std::set non_empty() const; + + + std::set non_empty_or_inbounds() const; + + + std::set empty_inbounds() const; + + + iterator begin() + { return voxels.begin(); } + + const_iterator begin() const + { return voxels.begin(); } + + iterator end() + { return voxels.end(); } + + const_iterator end() const + { return voxels.end(); } + + + virtual Buffer_tpl& clear() + { voxels.clear(); return *this; } + + + //FIXME: Would be better if it was virtual but that throws a compile error for some reason. + Buffer_tpl& zero() + { for (iterator vox_it = begin(); vox_it != end(); ++vox_it) BTS::zero(vox_it->second); return *this; } + + + Buffer_tpl& invalidate() + { for (iterator vox_it = begin(); vox_it != end(); ++vox_it) BTS::invalidate(vox_it->second); return *this; } + + /*! Resizes the dimensions of the image. Note that is does not change the underlying voxels which are sparsely + * implemented in a std::map. It does set enforce_bounds to false as it does not guarantee that the existing voxels + * are contained within the new bounds. */ + void resize(const Triple& dimensions) + { this->dimensions = dimensions; relax_bounds(); } + + + void reset(const Triple& dimensions) + { reset(dimensions, enforce_bounds); } + + void reset(const Triple& dimensions, bool enforce_bounds) + { this->dimensions = dimensions; this->enforce_bounds = enforce_bounds; voxels.clear(); } + + + //!Relaxes the constraint that voxels need to be within the given bounds of the image. + void relax_bounds() + { enforce_bounds = false; } + + void clear_and_enforce_bounds(); + + + bool bounds_are_enforced() const + { return enforce_bounds; } + + Buffer_tpl& operator+= (const Buffer_tpl& buff); + + + Buffer_tpl& operator-= (const Buffer_tpl& buff); + + + template Buffer_tpl& operator+= (const Buffer_tpl& buff); + + + template Buffer_tpl& operator-= (const Buffer_tpl& buff); + + + template Buffer_tpl& operator*= (const Buffer_tpl& buff); + + + template Buffer_tpl& operator/= (const Buffer_tpl& buff); + + + template Buffer_tpl& operator*= (const U& M); + + + template Buffer_tpl& operator/= (const U& M); + + + Buffer_tpl& negate(); + + + Buffer_tpl operator+ (const Buffer_tpl& buff) const; + + + Buffer_tpl operator- (const Buffer_tpl& buff) const; + + + Buffer_tpl operator* (const Buffer_tpl& buff) const; + + + Buffer_tpl operator/ (const Buffer_tpl& buff) const; + + + Buffer_tpl operator* (double M) const + { Buffer_tpl mult = *this; mult *= M; return mult; } + + + Buffer_tpl operator/ (double M) const + { Buffer_tpl mult = *this; mult /= M; return mult; } + + + const Triple& dims () const + { return dimensions; } + + + size_t dim (size_t dim_index) const + { return dimensions[dim_index]; } + + + size_t num_voxels_in_bounds() const + { return dim(X) * dim(Y) * dim(Z); } + + + size_t num_not_empty_voxels() const + { return voxels.size(); } + + + bool in_bounds(Index coord) const + { return coord.non_negative() && coord.bounded_by(dims()); } + + protected: + + virtual T new_voxel(const Index& c) + { return T(); } + + + friend std::ostream& operator<<<>(std::ostream& stream, const Buffer_tpl& B); + + }; + + + template Buffer_tpl operator* (double M, Buffer_tpl mult) + { mult *= M; return mult; } + + } + +} + +#undef LOOP + +#include "bts/image/voxel.h" + +namespace BTS { + + namespace Image { + + class Buffer : public Buffer_tpl< Voxel > { + + protected: + + size_t num_encodings; + + public: + + Buffer (size_t num_encodings = 0, bool enforce_bounds = true) + : Buffer_tpl< Voxel >(enforce_bounds), num_encodings(num_encodings) {} + + + Buffer (const Triple& dimensions, size_t num_encodings, bool enforce_bounds = true) + : Buffer_tpl< Voxel >(dimensions, enforce_bounds) {} + + + Buffer (const Buffer& B) + : Buffer_tpl< Voxel >(B) {} + + template Buffer (const Buffer_tpl& B) + : Buffer_tpl< Voxel >(B.dims(), B.bounds_are_enforced()), num_encodings(0) { + + int read_num_encodings = -1; + + for (typename Buffer_tpl::const_iterator vox_it = B.begin(); vox_it != B.end(); ++vox_it) { + + this->operator()(vox_it->first) = vox_it->second; + + if (read_num_encodings == -1) + read_num_encodings = vox_it->second.num_encodings(); + else if (read_num_encodings != (int)vox_it->second.num_encodings()) + throw Exception ("Number of encodings in copied voxels do not match (" + str(read_num_encodings) + " and " + str(vox_it->second.num_encodings()) + ")."); + + } + + num_encodings = read_num_encodings; + + } + + + ~Buffer() {} + + + Buffer& operator= (const Buffer& B) + { this->Buffer_tpl< Voxel >::operator=(B); return *this; } + + + protected: + + Voxel new_voxel(const Index& coord) + { return Voxel(num_encodings); } + + + }; + + + namespace Float { + + typedef Image::Buffer_tpl Buffer; + + }; + + namespace Double { + + typedef Image::Buffer_tpl Buffer; + + }; + + namespace Int { + + typedef Image::Buffer_tpl Buffer; + + }; + + namespace UInt { + + typedef Image::Buffer_tpl Buffer; + + }; + + namespace Bool { + + typedef Image::Buffer_tpl Buffer; + + }; + + } +} + +#undef LOOP + + +#endif diff --git a/src/bts/image/container/buffer.h b/src/bts/image/container/buffer.h new file mode 100644 index 0000000..e1d4991 --- /dev/null +++ b/src/bts/image/container/buffer.h @@ -0,0 +1,150 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + + +#ifndef __bts_image_container_buffer_h__ +#define __bts_image_container_buffer_h__ + + +namespace BTS { + + namespace Image { + + namespace Container { + + template class Buffer; + + } + + } + +} + +#include +#include "bts/image/container/voxel.h" +#include "bts/fibre/strand/section.h" +#include "bts/fibre/tractlet/section.h" +#include "bts/fibre/tractlet/tensor.h" +#include "bts/fibre/strand/tensor.h" + + + +#define LOOP(op) \ +for (size_t z = 0; z < this->dim(Z); z++) { \ + for (size_t y = 0; y < this->dim(Y); y++) { \ + for (size_t x = 0; x < this->dim(X); x++) { \ + op \ + } \ + } \ +} + + +namespace BTS { + + namespace Image { + + namespace Container { + + template class Buffer : public Image::Buffer_tpl< Container::Voxel > { + + + public: + + typedef std::vector Set; + + protected: + + size_t number_directions; + + public: + + Buffer () + : Image::Buffer_tpl< Voxel >(false), number_directions(0) {} + + + Buffer (Triple dims, size_t num_encodings) + : Image::Buffer_tpl< Voxel >(dims,false), number_directions(num_encodings) {} + + + Buffer (const Buffer& B) + : Image::Buffer_tpl< Voxel >(B), number_directions(B.number_directions) {} + + + ~Buffer () {} + + + Buffer* clone() + { return new Buffer(*this); } + + + Buffer& operator= (const Buffer& B) + { Image::Buffer_tpl< Voxel >::operator= (B); number_directions = B.number_directions; return *this; } + + + size_t num_encodings() const + { return number_directions; } + + Buffer& clear () + { this->Image::Buffer_tpl< Voxel >::clear(); return *this; } + + Buffer& zero () + { this->Image::Buffer_tpl< Voxel >::zero(); return *this; } + + void reset(const Triple& dimensions, size_t num_encodings) + { Image::Buffer_tpl< Voxel >::reset(dimensions); number_directions = num_encodings; } + + void reset(const Triple& dimensions, size_t num_encodings, bool enforce_bounds) + { Image::Buffer_tpl< Voxel >::reset(dimensions, enforce_bounds); number_directions = num_encodings; } + + void quick_clear () + { for (typename Image::Buffer_tpl< Voxel >::iterator vox_it = this->begin(); vox_it != this->end(); ++vox_it) vox_it->second.quick_empty(); } + + inline Voxel& operator() (int x, int y, int z) + { return operator()(Index(x,y,z)); } + + inline Voxel& operator() (const Index& c) + { Voxel& vox = Image::Buffer_tpl< Voxel >::operator()(c); vox.undo_empty(); return vox; } + + bool is_empty(const Index& c) const + { typename Image::Buffer_tpl< Voxel >::const_iterator vox_it = this->voxels.find(c); return (vox_it == this->end()) ? true : vox_it->second.is_empty(); } + + bool is_empty(size_t x, size_t y, size_t z) const + { return is_empty(Index(x,y,z)); } + + + protected: + + Container::Voxel new_voxel(const Index& coord) + { return Container::Voxel(number_directions); } + + }; + + } + + } + +} + + +#undef LOOP + +#endif //__bts_image_container_buffer_h__ diff --git a/src/bts/image/container/voxel.h b/src/bts/image/container/voxel.h new file mode 100644 index 0000000..83957db --- /dev/null +++ b/src/bts/image/container/voxel.h @@ -0,0 +1,128 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + + +#ifndef __bts_image_container_voxel_h__ +#define __bts_image_container_voxel_h__ + + +namespace BTS { + + namespace Image { + + namespace Container { + + template class Voxel; + + } + + } + +} + + +#include "bts/image/voxel.h" + +#define LOOP(op) \ +for (size_t encode_i = 0; encode_i < this->num_encodings(); encode_i++) {\ + op \ +} + + + + +namespace BTS { + + namespace Image { + + namespace Container { + + template class Voxel : public Image::Voxel { + + protected: + + bool fake_empty; + + public: + + Voxel() + : fake_empty(false) {} + + Voxel(size_t num_encodings) + : Image::Voxel(num_encodings), fake_empty(false) {} + + Voxel(size_t num_encodings, const T& default_value) + : Image::Voxel(num_encodings, default_value), fake_empty(false) {} + + Voxel(const Voxel& v) + : Image::Voxel(v), fake_empty(false) {} + + Voxel(const Image::Voxel& v) + : Image::Voxel(v), fake_empty(false) {} + + Voxel& operator=(const Voxel& v) + { this->Image::Voxel::operator=(v); fake_empty = v.fake_empty; return *this; } + + Voxel& operator*=(double M) + { assert(!fake_empty); LOOP(this->operator[](encode_i) *= M;); return *this; } + + Voxel& operator/=(double M) + { assert(!fake_empty); LOOP(this->operator[](encode_i) /= M;); return *this; } + + Voxel& zero() + { assert(!fake_empty); this->Image::Voxel::zero(); return *this; } + + void quick_empty() + { fake_empty = true; } + + bool is_empty() const + { return fake_empty; } + + void undo_empty() + { fake_empty = false; } + + void reset(const T& template_value) { + + assert(this->num_encodings()); + + if (this->operator[](0).degree() != template_value.degree()) { + T zero_value(template_value); + zero_value.zero(); + LOOP(this->operator[](encode_i) = zero_value;) + } else { + LOOP(this->operator[](encode_i).zero();) + } + + } + + + }; + + } + + } + +} + +#undef LOOP + +#endif diff --git a/src/bts/image/expected/buffer.cpp b/src/bts/image/expected/buffer.cpp new file mode 100644 index 0000000..3c8df74 --- /dev/null +++ b/src/bts/image/expected/buffer.cpp @@ -0,0 +1,255 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, Aug 30, 2010. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + + +#include "image/header.h" + +#include "bts/common.h" + +#include "bts/image/expected/buffer.h" +#include "bts/image/expected/trilinear/buffer.h" +#include "bts/image/expected/gaussian/buffer.h" +#include "bts/image/expected/quartic/buffer.h" +#include "bts/image/expected/sinc/buffer.h" +#include "bts/image/expected/top_hat/buffer.h" +#include "bts/image/expected/reverse_sqrt/buffer.h" +#include "bts/image/expected/realistic/buffer.h" + +#include "bts/image/voxel.h" + +#include "bts/fibre/strand/set.h" +#include "bts/fibre/tractlet/set.h" + +#include "bts/image/inline_functions.h" + +#define LOOP(op) \ +for (size_t z = 0; z < this->dim(Z); z++) { \ + for (size_t y = 0; y < this->dim(Y); y++) { \ + for (size_t x = 0; x < this->dim(X); x++) { \ + op \ + } \ + } \ +} + + +namespace BTS { + + namespace Image { + + namespace Expected { + + + const Triple Buffer::DIMS_DEFAULT = Triple(3,3,3); + const Triple Buffer::VOX_LENGTHS_DEFAULT = Triple(0.15,0.15,0.15); + const Triple Buffer::OFFSETS_DEFAULT = Triple::Zeros; + const std::string Buffer::FILE_EXTENSION = "mif"; + + const double Buffer::INTERP_EXTENT_DEFAULT = 1.0; + const double Buffer::HALF_WIDTH_DEFAULT = 0.392470007505158; + const char* Buffer::TYPE_DEFAULT = "quartic"; + const size_t Buffer::NUM_LENGTH_SECTIONS_DEFAULT = 15; + const size_t Buffer::NUM_WIDTH_SECTIONS_DEFAULT = 4; + const bool Buffer::ENFORCE_BOUNDS_DEFAULT = false; + + const std::string Buffer::STRAND_BASE_INTENSITY_REFERENCE = "/home/tclose/Data/Tractography/fibre/strand/single/x.str"; + const std::string Buffer::TRACTLET_BASE_INTENSITY_REFERENCE = "/home/tclose/Data/Tractography/fibre/tract/single/x-all.tct"; + + + Buffer* Buffer::factory(const std::string& type, + const Triple& dims, + const Triple& vox_lengths, + const Diffusion::Model& diffusion_model, + size_t num_length_sections, + size_t num_width_sections, + double interp_extent, + const Triple& offsets, + bool enforce_bounds, + double gaussian_half_width) { + + Buffer* image; + + if (type == Trilinear::Buffer::SHORT_NAME) + image = new Trilinear::Buffer ( + dims, + vox_lengths, + diffusion_model, + num_length_sections, + num_width_sections, + interp_extent, + offsets, + enforce_bounds); + + else if (type == Gaussian::Buffer::SHORT_NAME) + image = new Gaussian::Buffer ( + dims, + vox_lengths, + diffusion_model, + num_length_sections, + num_width_sections, + interp_extent, + gaussian_half_width, + offsets, + enforce_bounds); + + else if (type == Quartic::Buffer::SHORT_NAME) + + image = new Quartic::Buffer ( + dims, + vox_lengths, + diffusion_model, + num_length_sections, + num_width_sections, + interp_extent, + offsets, + enforce_bounds); + + else if (type == Sinc::Buffer::SHORT_NAME) + + image = new Sinc::Buffer ( + dims, + vox_lengths, + diffusion_model, + num_length_sections, + num_width_sections, + interp_extent, + offsets, + enforce_bounds); + + else if (type == TopHat::Buffer::SHORT_NAME) + + image = new TopHat::Buffer ( + dims, + vox_lengths, + diffusion_model, + num_length_sections, + num_width_sections, + interp_extent, + offsets, + enforce_bounds); + + else if (type == ReverseSqrt::Buffer::SHORT_NAME) + + image = new ReverseSqrt::Buffer ( + dims, + vox_lengths, + diffusion_model, + num_length_sections, + num_width_sections, + interp_extent, + offsets, + enforce_bounds); + + else if (type == Realistic::Buffer::SHORT_NAME) + + image = new Realistic::Buffer ( + dims, + vox_lengths, + diffusion_model, + num_length_sections, + num_width_sections, + interp_extent, + offsets, + enforce_bounds); + + else + throw Exception ("Unrecognised interpolation type '" + type + "' passed to option '-exp_type'."); + + + return image; + + } + + + + Image::Buffer Buffer::clean_buffer() { + + Image::Buffer clean_buffer (dims(), num_encodings()); + + LOOP(clean_buffer(x,y,z) = operator()(x,y,z);) + + return clean_buffer; + + } + + + double Buffer::base_intensity_default(const Image::Observed::Buffer& obs_image, const std::string& state_location) { + + if (File::has_extension(state_location)) { + +// Fibre::Strand::Set state (state_location); + Fibre::Strand::Set state (STRAND_BASE_INTENSITY_REFERENCE); + state.set_base_intensity(1.0); + this->expected_image(state); + + } else if (File::has_extension(state_location)) { + +// Fibre::Tractlet::Set state (state_location); + Fibre::Tractlet::Set state (TRACTLET_BASE_INTENSITY_REFERENCE); + state.set_base_intensity(1.0); + this->expected_image(state); + + } else + return NAN; + + this->save("/home/tclose/data/calibration_expected.mif"); + + return obs_image.max_b0() / this->max_b0(); + + + } + + double Buffer::base_intensity_default(const Image::Observed::Buffer& obs_image, Fibre::Strand::Set strands) { + + strands.set_base_intensity(1.0); + this->expected_image(strands); + + this->save("/home/tclose/data/calibration_expected.mif"); + + return obs_image.max_b0() / this->max_b0(); + + } + + + double Buffer::base_intensity_default(const Image::Observed::Buffer& obs_image, Fibre::Tractlet::Set tractlets) { + + tractlets.set_base_intensity(1.0); + this->expected_image(tractlets); + + this->save("/home/tclose/data/calibration_expected.mif"); + + return obs_image.max_b0() / this->max_b0(); + + } + + + bool Buffer::dims_match(const Observed::Buffer& reference) { + + return (reference.dims() == this->dims()); + + } + + + } + + } + +} diff --git a/src/bts/image/expected/buffer.h b/src/bts/image/expected/buffer.h new file mode 100644 index 0000000..828bdb4 --- /dev/null +++ b/src/bts/image/expected/buffer.h @@ -0,0 +1,600 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + +#ifndef __bts_image_expected_buffer_h__ +#define __bts_image_expected_buffer_h__ + +namespace BTS { + + namespace Image { + + namespace Expected { + + class Buffer; + + } + + } + +} + +#include "bts/common.h" + +#include "bts/image/observed/buffer.h" +#include "bts/image/index.h" +#include "bts/image/container/buffer.h" +#include "bts/image/reference/buffer.h" + +#include "bts/fibre/strand.h" +#include "bts/fibre/tractlet.h" + +#include "bts/diffusion/model.h" + +#define IMAGE_PARAMETERS \ +\ + Option ("img_dims", "The number of voxels along each dimension") \ + + Argument ("img_dims", "").type_text ("[3,3,3]"), \ +\ + Option ("img_vox_lengths", "The length of the voxels along each dimension") \ + + Argument ("img_vox_lengths", "").type_text ("[0.15,0.15,0.15]"), \ +\ + Option ("img_offsets", "The offset of the centre of the image from the origin (0,0,0).") \ + + Argument ("img_offset", "").type_text ("auto") \ + + +//Loads the parameters into variables +#define SET_IMAGE_PARAMETERS \ +\ + Triple img_dims = Image::Expected::Buffer::DIMS_DEFAULT; \ + Triple img_vox_lengths = Image::Expected::Buffer::VOX_LENGTHS_DEFAULT; \ + Triple img_offsets = Triple::Invalid; \ +\ + Options img_opt = get_options("img_dims"); \ + if (img_opt.size()) \ + img_dims = parse_triple(std::string(img_opt[0][0])); \ +\ + img_opt = get_options("img_vox_lengths"); \ + if (img_opt.size()) \ + img_vox_lengths = parse_triple(std::string(img_opt[0][0])); \ +\ + img_opt = get_options("img_offsets"); \ + if (img_opt.size()) \ + img_offsets = parse_triple(std::string(img_opt[0][0])); + +// Triple img_dims (img_dim); +// Triple img_vox_lengths (img_vox_length); + + +//Adds the parameters to the properties to be saved with the data. +#define ADD_IMAGE_PROPERTIES(properties) \ + properties["img_dims"] = str(img_dims); \ + properties["img_vox_lengths"] = str(img_vox_lengths); \ + properties["img_offsets"] = str(img_offsets); \ + + +//Defines the parameters required to initialise a object. +#define EXPECTED_IMAGE_PARAMETERS \ +\ + Option ("exp_num_length_sections", "The number of samples along each strand path when generating the corresponding image set.") \ + + Argument ("exp_num_length_sections", "").type_integer (1, Image::Expected::Buffer::NUM_LENGTH_SECTIONS_DEFAULT, LARGE_INT), \ +\ + Option ("exp_num_width_sections", "The number of samples across the tractlet width axes when generating the expected image.") \ + + Argument ("exp_num_width_sections", "").type_integer (1, Image::Expected::Buffer::NUM_WIDTH_SECTIONS_DEFAULT, LARGE_INT), \ +\ + Option ("exp_type", "Form of the kernel that will be used to interpolate the signal from the tractlets") \ + + Argument ("exp_type", "").type_text (Image::Expected::Buffer::TYPE_DEFAULT).type_text(), \ +\ + Option ("exp_interp_extent", "Extent of the kernel that will be used to interpolate the signal from the tractlets") \ + + Argument ("exp_interp_extent", "").type_float (SMALL_FLOAT, Image::Expected::Buffer::INTERP_EXTENT_DEFAULT, LARGE_FLOAT), \ +\ + Option ("exp_enforce_bounds", "Only record the signal (and include in likelihood calculations) that falls within the bounds of the image."), \ +\ + Option ("exp_half_width", "'Variance' of the kernel that will be used to interpolate the signal from the tractlets when using the Gaussian type kernel.") \ + + Argument ("exp_half_width", "").type_float (SMALL_FLOAT, Image::Expected::Buffer::HALF_WIDTH_DEFAULT, LARGE_FLOAT), \ +\ + Option ("exp_base_intensity", "The base intensity the strands/tractlets will be set to initially (possibly permanently). If < 0, the base intensity will be estimated from the observed image (if applicable).") \ + + Argument ("exp_base_intensity", "").type_float (-1.01, 1.0, LARGE_FLOAT), \ +\ + Option ("exp_untie_width_intensity", "When not set, intensity will be coupled to the average cross-sectional area of the tract.") + +//Loads the parameters into variables +#define SET_EXPECTED_IMAGE_PARAMETERS \ +\ + size_t exp_num_length_sections = Image::Expected::Buffer::NUM_LENGTH_SECTIONS_DEFAULT; \ + size_t exp_num_width_sections = Image::Expected::Buffer::NUM_WIDTH_SECTIONS_DEFAULT; \ + std::string exp_type = Image::Expected::Buffer::TYPE_DEFAULT; \ + double exp_interp_extent = Image::Expected::Buffer::INTERP_EXTENT_DEFAULT; \ + bool exp_enforce_bounds = Image::Expected::Buffer::ENFORCE_BOUNDS_DEFAULT; \ + double exp_half_width = Image::Expected::Buffer::HALF_WIDTH_DEFAULT; \ + double exp_base_intensity = 1.0; \ +\ + Options exp_opt = get_options("exp_num_length_sections"); \ + if (exp_opt.size()) \ + exp_num_length_sections = exp_opt[0][0]; \ +\ +exp_opt = get_options("exp_num_width_sections"); \ + if (exp_opt.size()) \ + exp_num_width_sections = exp_opt[0][0]; \ +\ + exp_opt = get_options("exp_type"); \ + if (exp_opt.size()) \ + exp_type = exp_opt[0][0].c_str(); \ +\ + exp_opt = get_options("exp_interp_extent"); \ + if (exp_opt.size()) \ + exp_interp_extent = exp_opt[0][0]; \ +\ + exp_opt = get_options("exp_enforce_bounds"); \ + if (exp_opt.size()) \ + exp_enforce_bounds = true; \ +\ + exp_opt = get_options("exp_half_width"); \ + if (exp_opt.size()) \ + exp_half_width = exp_opt[0][0]; \ +\ + exp_opt = get_options("exp_base_intensity"); \ + if (exp_opt.size()) \ + exp_base_intensity = exp_opt[0][0]; + +//Adds the parameters to the properties to be saved with the data. +#define ADD_EXPECTED_IMAGE_PROPERTIES(properties) \ + properties["exp_num_length_sections"] = str(exp_num_length_sections); \ + properties["exp_num_width_sections"] = str(exp_num_width_sections); \ + properties["exp_interp_extent"] = str(exp_interp_extent); \ + properties["exp_enforce_bounds"] = str(exp_enforce_bounds); \ + properties["exp_type"] = exp_type; \ + properties["exp_base_intensity"] = str(exp_base_intensity); \ + if (exp_type == "gaussian") { \ + properties["exp_half_width"] = exp_half_width; \ + } \ + + +#include "math/matrix.h" + +#include "bts/common.h" + +#include "bts/image/index.h" +#include "bts/image/buffer.h" +#include "bts/fibre/strand.h" +#include "bts/fibre/tractlet.h" + +#include "bts/diffusion/model.h" + +#include "bts/image/observed/buffer.h" +#include "bts/image/container/buffer.h" + +#include "bts/image/expected/voxel.h" + +namespace BTS { + + namespace Image { + + namespace Expected { + + namespace Gaussian { + class Buffer; + class Voxel; + } + namespace Quartic { + class Buffer; + class Voxel; + } + namespace Trilinear { + class Buffer; + class Voxel; + } + namespace TopHat { + class Buffer; + class Voxel; + } + namespace Sinc { + class Buffer; + class Voxel; + } + namespace ReverseSqrt { + class Buffer; + class Voxel; + } + namespace Realistic { + class Buffer; + class Voxel; + } + + + class Buffer { + + public: + + typedef std::map::iterator iterator; + typedef std::map::const_iterator const_iterator; + + public: + + const static size_t NUM_LENGTH_SECTIONS_DEFAULT; + const static size_t NUM_WIDTH_SECTIONS_DEFAULT; + + const static Triple DIMS_DEFAULT; + const static Triple VOX_LENGTHS_DEFAULT; + const static Triple OFFSETS_DEFAULT; + const static std::string FILE_EXTENSION; + + const static double INTERP_EXTENT_DEFAULT; + const static bool ENFORCE_BOUNDS_DEFAULT; + const static double HALF_WIDTH_DEFAULT; + const static char* TYPE_DEFAULT; + + const static std::string STRAND_BASE_INTENSITY_REFERENCE; + const static std::string TRACTLET_BASE_INTENSITY_REFERENCE; + + //Public static methods. + public: + + static Buffer* factory(const std::string& type, + const Triple& dims, const Triple& vox_lengths, + const Diffusion::Model& diffusion_model, + size_t num_length_sections, size_t num_width_sections, + double interp_extent, const Triple& offsets, + bool enforce_bounds, double gaussian_half_width); + + static Buffer* factory(const std::string& type, + const Observed::Buffer& obs_image, + const Diffusion::Model& diffusion_model, + size_t num_length_sections, size_t num_width_sections, + double interp_extent, bool enforce_bounds, + double gaussian_half_width) + + { + return factory(type, obs_image.dims(), obs_image.vox_lengths(), + diffusion_model, num_length_sections, num_width_sections, + interp_extent, obs_image.offsets(), enforce_bounds, + gaussian_half_width); + } + + //Used for pretty printing in gdb. Is set in the constructor of derived classes. + protected: + + char type[50]; + + public: + + virtual Voxel& operator()(int x, int y, int z) = 0; + + virtual const Voxel& operator()(int x, int y, int z) const = 0; + + virtual Voxel& operator()(Index c) = 0; + + virtual const Voxel& operator()(Index c) const = 0; + + virtual const Triple& dims() const = 0; + + virtual const Triple& vox_lengths() const = 0; + + //! Offset of the lowest corner of the lowest voxel coordinate ([0,0,0]) of the image. + virtual const Triple& offsets() const = 0; + + virtual size_t dim(size_t dim_index) const = 0; + + virtual double vox_length(size_t dim_index) const = 0; + + //! Offset of the lowest corner of the lowest voxel coordinate ([0,0,0]) of the image. + virtual double offset(size_t dim_index) const = 0; + + virtual size_t num_encodings() const = 0; + + virtual const Diffusion::Encoding& encoding(size_t index) const = 0; + + virtual size_t num_length_sections() const = 0; + + virtual size_t num_width_sections() const = 0; + + virtual void save(const std::string& location) const = 0; + + virtual Buffer& expected_image(const Fibre::Strand::Set& strands) = 0; + + virtual Buffer& part_image(const Fibre::Strand& strand) = 0; + + virtual Buffer + & expected_image(const Fibre::Tractlet::Set& tractlets) = 0; + + virtual Reference::Buffer::Set + & expected_image_with_references(const Fibre::Strand::Set& fibres) = 0; + + virtual Reference::Buffer::Set + & expected_image_with_references( + const Fibre::Tractlet::Set& fibres) = 0; + + virtual Buffer& expected_image(const Fibre::Strand::Set& strands, + Container::Buffer::Set& gradients) = 0; + + virtual Buffer& expected_image(const Fibre::Tractlet::Set& tractlets, + Container::Buffer::Set& gradients) = 0; + + virtual Buffer& expected_image(const Fibre::Strand::Set& strands, + Container::Buffer::Set& gradients, + Container::Buffer::Set& hessians) = 0; + + virtual Buffer& expected_image(const Fibre::Tractlet::Set& tractlets, + Container::Buffer::Set& gradients, + Container::Buffer::Set& hessians) = 0; + + virtual void precalculate_section_weighting_gradients( + const Fibre::Strand& dummy) = 0; + + virtual void precalculate_section_weighting_gradients_and_hessians( + const Fibre::Strand& dummy) = 0; + + virtual void precalculate_section_weighting_gradients( + const Fibre::Tractlet& dummy) = 0; + + virtual void precalculate_section_weighting_gradients_and_hessians( + const Fibre::Tractlet& dummy) = 0; + + virtual Buffer* clone() const = 0; + + virtual const Diffusion::Model& get_diffusion_model() const = 0; + + virtual std::ostream& to_stream(std::ostream& stream) const = 0; + + Image::Buffer clean_buffer(); + + double base_intensity_default(const Observed::Buffer& obs_image, const std::string& state_location); + + double base_intensity_default(const Observed::Buffer& obs_image, Fibre::Strand::Set strands); + + double base_intensity_default(const Observed::Buffer& obs_image, Fibre::Tractlet::Set tractlets); + + bool dims_match(const Observed::Buffer& reference); + + virtual Properties& properties() = 0; + + virtual const Properties& properties() const = 0; + + virtual double rms(bool include_b0s) const = 0; + + virtual double max_b0() const = 0; + + virtual Buffer& zero() = 0; + + virtual Buffer& clear() = 0; + + virtual Buffer& negate() = 0; + + virtual std::set non_empty() const = 0; + + virtual std::set non_empty_or_inbounds() const = 0; + + virtual std::set empty_inbounds() const = 0; + + virtual bool bounds_are_enforced() const = 0; + + virtual void clear_and_enforce_bounds() = 0; + + virtual void relax_bounds() = 0; + + virtual Buffer& operator+=(const Buffer& buffer) = 0; + + virtual Buffer& operator-=(const Buffer& buffer) = 0; + + virtual iterator begin() { + throw Exception("not implemented"); + } + + virtual iterator end() { + throw Exception("not implemented"); + } + }; + +#define EXPECTED_BUFFER_FUNCTIONS \ + \ + void save(const std::string& location) const \ + { this->Observed::Buffer_tpl::save(location); } \ + \ + Buffer& expected_image(const Fibre::Strand::Set& strands) \ + { this->Buffer_tpl::expected_image(strands); return *this; } \ +\ + Buffer& part_image(const Fibre::Strand& strand) \ + { this->Buffer_tpl::part_image(strand); return *this; } \ + \ + Buffer& expected_image(const Fibre::Tractlet::Set& tractlets) \ + { this->Buffer_tpl::expected_image(tractlets); return *this; } \ + \ + Reference::Buffer::Set& expected_image_with_references(const Fibre::Strand::Set& fibres) \ + { return this->Buffer_tpl::expected_image_with_references(fibres); } \ + \ + Reference::Buffer::Set& expected_image_with_references(const Fibre::Tractlet::Set& fibres) \ + { return this->Buffer_tpl::expected_image_with_references(fibres); } \ + \ + Buffer& expected_image(const Fibre::Strand::Set& strands, Container::Buffer::Set& gradients) \ + { this->Buffer_tpl::expected_image(strands, gradients); return *this; } \ + \ + Buffer& expected_image(const Fibre::Tractlet::Set& tractlets, Container::Buffer::Set& gradients) \ + { this->Buffer_tpl::expected_image(tractlets, gradients); return *this; } \ + \ + Buffer& expected_image(const Fibre::Strand::Set& strands, Container::Buffer::Set& gradients, Container::Buffer::Set& hessians) \ + { this->Buffer_tpl::expected_image(strands, gradients, hessians); return *this; } \ + \ + Buffer& expected_image(const Fibre::Tractlet::Set& tractlets, Container::Buffer::Set& gradients, Container::Buffer::Set& hessians) \ + { this->Buffer_tpl::expected_image(tractlets, gradients, hessians); return *this; } \ + \ + Buffer& part_image (const Fibre::Strand& strand, Container::Buffer& gradients, Container::Buffer& hessians) \ + { this->Buffer_tpl::part_image(strand, gradients, hessians); return *this; } \ + \ + Buffer& part_image (const Fibre::Tractlet& tractlet, Container::Buffer& gradients, Container::Buffer& hessians) \ + { this->Buffer_tpl::part_image(tractlet, gradients, hessians); return *this; } \ + \ + Buffer& part_image(const Fibre::Strand& strand, Container::Buffer& gradients) \ + { this->Buffer_tpl::part_image(strand, gradients); return *this; } \ + \ + Buffer& part_image(const Fibre::Tractlet& tractlet, Container::Buffer& gradients) \ + { this->Buffer_tpl::part_image(tractlet, gradients); return *this; } \ + \ + void precalculate_section_weighting_gradients(const Fibre::Strand& dummy) \ + { Expected::Buffer_tpl::precalculate_section_weighting_gradients(); } \ + \ + void precalculate_section_weighting_gradients_and_hessians(const Fibre::Strand& dummy) \ + { Expected::Buffer_tpl::precalculate_section_weighting_gradients_and_hessians(); } \ + \ + void precalculate_section_weighting_gradients(const Fibre::Tractlet& dummy) \ + { Expected::Buffer_tpl::precalculate_section_weighting_gradients(); } \ + \ + void precalculate_section_weighting_gradients_and_hessians(const Fibre::Tractlet& dummy) \ + { Expected::Buffer_tpl::precalculate_section_weighting_gradients_and_hessians(); } \ + \ + Buffer* clone() const \ + { return new Buffer(*this); } \ + \ + const Diffusion::Model& get_diffusion_model() const \ + { return this->Buffer_tpl::get_diffusion_model(); } \ + \ + size_t num_length_sections() const \ + { return this->Buffer_tpl::num_length_sections(); } \ + \ + size_t num_width_sections() const \ + { return this->Buffer_tpl::num_width_sections(); } \ + \ + Voxel& operator() (Index coord) \ + { return Image::Buffer_tpl::operator()(coord); } \ + \ + const Voxel& operator() (Index coord) const \ + { return Image::Buffer_tpl::operator()(coord); } \ + \ + Voxel& operator() (int x, int y, int z) \ + { return Image::Buffer_tpl::operator()(x,y,z); } \ + \ + const Voxel& operator() (int x, int y, int z) const \ + { return Image::Buffer_tpl::operator()(x,y,z); } \ + \ + size_t num_encodings() const \ + { return this->Buffer_tpl::num_encodings(); } \ + \ + const Diffusion::Encoding& encoding(size_t index) const \ + { return this->Buffer_tpl::encoding(index); } \ + \ + size_t dim(size_t dim_index) const \ + { return this->Image::Buffer_tpl::dim(dim_index); } \ + \ + double vox_length(size_t dim_index) const \ + { return this->Buffer_tpl::vox_length(dim_index); } \ + \ + double offset(size_t dim_index) const \ + { return this->Buffer_tpl::offset(dim_index); } \ + \ + const Triple& dims() const \ + { return this->Image::Buffer_tpl::dims(); } \ + \ + const Triple& vox_lengths() const \ + { return this->Buffer_tpl::vox_lengths(); } \ + \ + const Triple& offsets() const \ + { return this->Buffer_tpl::offsets(); } \ + \ + Buffer& zero () \ + { this->Buffer_tpl::zero(); return *this; } \ + \ + Buffer& clear () \ + { this->Buffer_tpl::clear(); return *this; } \ +\ + Buffer& negate () \ + { this->Buffer_tpl::negate(); return *this; } \ + \ + Buffer& operator+= (const Buffer& buff) \ + { this->Buffer_tpl::operator+= (buff); return *this; } \ + \ + Buffer& operator-= (const Buffer& buff) \ + { this->Buffer_tpl::operator-= (buff); return *this; } \ + \ + Buffer& operator*= (double M) \ + { this->Buffer_tpl::operator*= (M); return *this; } \ + \ + Buffer& operator/= (double M) \ + { this->Buffer_tpl::operator/= (M); return *this; } \ + \ + template Buffer& operator+= (const Image::Buffer_tpl& buff) \ + { this->Buffer_tpl::operator+= (buff); return *this; } \ + \ + template Buffer& operator-= (const Image::Buffer_tpl& buff) \ + { this->Buffer_tpl::operator-= (buff); return *this; } \ +\ + Buffer& operator+= (const Expected::Buffer& buff) \ + { this->Buffer_tpl::operator+= (buff); return *this; } \ +\ + Buffer& operator-= (const Expected::Buffer& buff) \ + { this->Buffer_tpl::operator-= (buff); return *this; } \ +\ + std::ostream& to_stream (std::ostream& stream) const \ + { return this->Buffer_tpl::to_stream(stream); } \ + \ + Properties& properties() \ + { return this->Buffer_tpl::properties(); } \ + \ + const Properties& properties() const \ + { return this->Buffer_tpl::properties(); } \ + \ + double rms(bool include_b0s) const \ + { return Buffer_tpl::rms(include_b0s); } \ + \ + double max_b0() const \ + { return Buffer_tpl::max_b0(); } \ + \ + std::set non_empty() const \ + { return Image::Buffer_tpl::non_empty(); } \ + \ + std::set non_empty_or_inbounds() const \ + { return Image::Buffer_tpl::non_empty_or_inbounds(); } \ +\ + std::set empty_inbounds() const \ + { return Image::Buffer_tpl::empty_inbounds(); } \ +\ + bool bounds_are_enforced() const \ + { return Image::Buffer_tpl::bounds_are_enforced(); } \ + \ + void clear_and_enforce_bounds() \ + { return Image::Buffer_tpl::clear_and_enforce_bounds(); } \ +\ + void relax_bounds() \ + { return Image::Buffer_tpl::relax_bounds(); } \ +\ + protected: \ +\ + virtual Voxel new_voxel(const Index& coord) \ + { return Voxel(*this,coord); } \ +\ + void name_init() \ + { strncpy (this->type, SHORT_NAME.c_str(), 50); } \ +\ + friend class Voxel + + inline std::ostream& operator<<(std::ostream& stream, const Buffer& image) { + + return image.to_stream(stream); + + } + + } + + } + +} + + + +#endif diff --git a/src/bts/image/expected/buffer_tpl.cpp.h b/src/bts/image/expected/buffer_tpl.cpp.h new file mode 100644 index 0000000..53b569f --- /dev/null +++ b/src/bts/image/expected/buffer_tpl.cpp.h @@ -0,0 +1,536 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, 16/07/2010. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + +#ifndef __bts_image_expected_buffer_cpp_h__ +#define __bts_image_expected_buffer_cpp_h__ + +#include "bts/image/expected/buffer_tpl.h" +#include "bts/image/reference/buffer.h" + +#include "bts/fibre/tractlet/set.h" +#include "bts/fibre/strand/set.h" +#include "bts/fibre/strand/section.h" +#include "bts/fibre/tractlet/section.h" +#include "bts/coord/tensor.h" +#include "bts/fibre/strand/tensor.h" +#include "bts/fibre/tractlet/tensor.h" + + +namespace BTS { + + namespace Image { + + namespace Expected { + +#define LOOP(op) \ + for (size_t z = 0; z < this->dim(Z); z++) { \ + for (size_t y = 0; y < this->dim(Y); y++) { \ + for (size_t x = 0; x < this->dim(X); x++) { \ + op \ + } \ + } \ + } + + +//***************************************// +//********* Non Hessian Versions ********// +//***************************************// + + template template void Buffer_tpl::part_image(const U& fibre) { + + + std::vector path; + + fibre.sections(path, num_len_sections, num_wth_sections, this->voxel_lengths, this->corner_offsets); + + for (typename std::vector::iterator section_it = path.begin(); section_it != path.end(); ++section_it) { + + typename U::Section& section = *section_it; + +#ifdef OPTIMISED + diffusion_model.precalculate_weightings(section); +#endif + + std::set neighbourhood = this->get_neighbourhood(section.position()); + + for (typename std::set::iterator vox_it = neighbourhood.begin(); vox_it != neighbourhood.end(); ++vox_it) { + + T& voxel = **vox_it; + +#ifdef OPTIMISED + voxel.precalculate_interpolation(section); +#endif + + for (size_t encode_i = 0; encode_i < this->num_encodings(); encode_i++) { + + voxel[encode_i] += voxel.direction(encode_i).signal(section); + + } + + } + + } + + } + + + template template void Buffer_tpl::expected_image(const typename U::Set& fibres) { + + this->zero(); + + for (size_t fibre_i = 0; fibre_i < fibres.size(); fibre_i++) + part_image(fibres[fibre_i]); + + for (typename Buffer_tpl::iterator vox_it = this->begin(); vox_it != this->end(); ++vox_it) + for (size_t encode_i = 0; encode_i < num_encodings(); ++encode_i) + vox_it->second[encode_i] *= fibres.base_intensity(); + + } + + + + template template void Buffer_tpl::part_image(const U& fibre, + std::vector& path, + Reference::Buffer& section_reference) { + + + fibre.sections(path, num_len_sections, num_wth_sections, this->voxel_lengths, this->corner_offsets, this->num_encodings()); + + for (typename std::vector::iterator section_it = path.begin(); section_it != path.end(); ++section_it) { + + typename U::Section& section = *section_it; + +#ifdef OPTIMISED + diffusion_model.precalculate_weightings(section); +#endif + + std::set neighbourhood = this->get_neighbourhood(section.position()); + + for (typename std::set::iterator vox_it = neighbourhood.begin(); vox_it != neighbourhood.end(); ++vox_it) { + + T& voxel = **vox_it; + + section_reference(voxel.coord()).push_back(§ion); + +#ifdef OPTIMISED + voxel.precalculate_interpolation(section); +#endif + + for (size_t encode_i = 0; encode_i < this->num_encodings(); encode_i++) { + + voxel[encode_i] += voxel.direction(encode_i).signal(section); + + } + + } + + } + + } + + + template template typename Image::Reference::Buffer::Set& Buffer_tpl::expected_image_with_references(const typename U::Set& fibres) { + + this->zero(); + + std::map >& sections = get_sections(U()); + typename Reference::Buffer::Set& section_refs = get_section_references(U()); + + for (size_t fibre_i = 0; fibre_i < fibres.size(); fibre_i++) { + + section_refs[fibre_i].clear_references(); + + part_image(fibres[fibre_i], sections[fibre_i], section_refs[fibre_i]); + + } + + for (typename Buffer_tpl::iterator vox_it = this->begin(); vox_it != this->end(); ++vox_it) + for (size_t encode_i = 0; encode_i < num_encodings(); ++encode_i) + vox_it->second[encode_i] *= fibres.base_intensity(); + + + return section_refs; + + + } + + + template template + void Buffer_tpl::part_image( const U& fibre, + Container::Buffer& gradients) { + + + std::vector path; + + fibre.sections(path, num_len_sections, num_wth_sections, this->voxel_lengths, this->corner_offsets); + + for (typename std::vector::iterator section_it = path.begin(); section_it != path.end(); ++section_it) { + + typename U::Section& section = *section_it; + +#ifdef OPTIMISED + diffusion_model.precalculate_weightings_and_gradients(section); +#endif + + std::set neighbourhood = this->get_neighbourhood(section.position()); + + for (typename std::set::iterator vox_it = neighbourhood.begin(); vox_it != neighbourhood.end(); ++vox_it) { + + T& voxel = **vox_it; + const Index& coord = voxel.coord(); + + if (gradients.is_empty(coord)) + gradients(coord).reset(fibre); + + Image::Container::Voxel& gradient_voxel = gradients(coord); + + +#ifdef OPTIMISED + voxel.precalculate_interpolation_gradient(section); +#endif + + for (size_t encode_i = 0; encode_i < this->num_encodings(); encode_i++) { + + typename U::Section section_gradient; + + voxel[encode_i] += voxel.direction(encode_i).signal(section, section_gradient); + +#ifndef GRADIENT_NOT_REQUIRED + section_gradient.unnormalize_gradient(this->vox_lengths()); + gradient_voxel[encode_i].add_section_gradient(*section.parent, section, section_gradient); +#endif + + } + + } + + } + + } + + + template template void Buffer_tpl::expected_image(const typename U::Set& fibres, + typename Container::Buffer::Set& gradients) { + + + this->zero(); + + for (size_t fibre_i = 0; fibre_i < fibres.size(); fibre_i++) { + + if (gradients.size() <= fibre_i) + gradients.push_back(Container::Buffer (this->dimensions, this->num_encodings())); + else if (gradients[fibre_i].dims() != this->dims() || gradients[fibre_i].num_encodings() != this->num_encodings()) + gradients[fibre_i].reset(this->dimensions, this->num_encodings()); + else + //NB: This does not actually clear the voxels, but instead sets a flag that designates it them as being empty. + // Therefore the function 'Buffer_tpl::is_empty(const Image::Index&)' should be used to check before using a given voxel. + gradients[fibre_i].quick_clear(); + + + part_image(fibres[fibre_i], gradients[fibre_i]); + + + } + + + for (typename Buffer_tpl::iterator vox_it = this->begin(); vox_it != this->end(); ++vox_it) + for (size_t encode_i = 0; encode_i < num_encodings(); ++encode_i) + vox_it->second[encode_i] *= fibres.base_intensity(); + + + for (size_t fibre_i = 0; fibre_i < fibres.size(); ++fibre_i) + for (typename Buffer_tpl::iterator vox_it = this->begin(); vox_it != this->end(); ++vox_it) + for (size_t encode_i = 0; encode_i < num_encodings(); ++encode_i) + gradients[fibre_i](vox_it->first)[encode_i] *= fibres.base_intensity(); + + } + + + template template void Buffer_tpl::precalculate_section_weighting_gradients() { + + std::map >& sections = get_sections(U()); + + for (size_t fibre_i = 0; fibre_i < sections.size(); ++fibre_i) + for (size_t section_i = 0; section_i < sections[fibre_i].size(); ++section_i) + diffusion_model.precalculate_weightings_and_gradients(sections[fibre_i][section_i]); + + } + + + template template void Buffer_tpl::precalculate_section_weighting_gradients_and_hessians() { + + std::map >& sections = get_sections(U()); + + for (size_t fibre_i = 0; fibre_i < sections.size(); ++fibre_i) + for (size_t section_i = 0; section_i < sections[fibre_i].size(); ++section_i) + diffusion_model.precalculate_weightings_gradients_and_hessians(sections[fibre_i][section_i]); + + } + +//***********************************// +//********* Hessian Versions ********// +//***********************************// + + + + template template + void Buffer_tpl::part_image( const U& fibre, + Container::Buffer& gradients, + Container::Buffer& hessians) { + + + std::vector path; + + fibre.sections(path, num_len_sections, num_wth_sections, this->voxel_lengths, this->corner_offsets); + + for (typename std::vector::iterator section_it = path.begin(); section_it != path.end(); ++section_it) { + + typename U::Section& section = *section_it; + +#ifdef OPTIMISED + diffusion_model.precalculate_weightings_gradients_and_hessians(section); +#endif + + std::set neighbourhood = this->get_neighbourhood(section.position()); + + for (typename std::set::iterator vox_it = neighbourhood.begin(); vox_it != neighbourhood.end(); ++vox_it) { + + T& voxel = **vox_it; + const Index& coord = voxel.coord(); + + if (gradients.is_empty(coord)) + gradients(coord).reset(fibre); + + Image::Container::Voxel& gradient_voxel = gradients(coord); + + if (hessians.is_empty(coord)) + hessians(coord).reset(typename U::Tensor(fibre)); + + Image::Container::Voxel& hessian_voxel = hessians(coord); + + +#ifdef OPTIMISED + voxel.precalculate_interpolation_gradient_and_hessian(section); +#endif + + for (size_t encode_i = 0; encode_i < this->num_encodings(); encode_i++) { + + typename U::Section section_gradient; + typename U::Section::Tensor section_hessian; + + voxel[encode_i] += voxel.direction(encode_i).signal(section, section_gradient, section_hessian); + +#ifndef GRADIENT_NOT_REQUIRED + section_gradient.unnormalize_gradient(this->vox_lengths()); + gradient_voxel[encode_i].add_section_gradient(*section.parent, section, section_gradient); + +#ifndef HESSIAN_NOT_REQUIRED + section_hessian.unnormalise_hessian(this->vox_lengths()); + hessian_voxel[encode_i].add_section_hessian(*section.parent, section, section_gradient, section_hessian); +#endif + +#endif + + } + + } + + } + + } + + + template template + void Buffer_tpl::expected_image(const typename U::Set& fibres, + typename Container::Buffer::Set& gradients, + typename Container::Buffer::Set& hessians) { + + + this->zero(); + + for (size_t fibre_i = 0; fibre_i < fibres.size(); fibre_i++) { + + if (gradients.size() <= fibre_i) + gradients.push_back(Container::Buffer (this->dimensions, this->num_encodings())); + else if (gradients[fibre_i].dims() != this->dims() || gradients[fibre_i].num_encodings() != this->num_encodings()) + gradients[fibre_i].reset(this->dimensions, this->num_encodings()); + else + //NB: This does not actually clear the voxels, but instead sets a flag that designates it them as being empty. + // Therefore the function 'Buffer_tpl::is_empty(const Image::Index&)' should be used to check before using a given voxel. + gradients[fibre_i].quick_clear(); + + + if (hessians.size() <= fibre_i) + hessians.push_back(Container::Buffer (this->dimensions, this->num_encodings())); + else if (hessians[fibre_i].dims() != this->dims() || hessians[fibre_i].num_encodings() != this->num_encodings()) + hessians[fibre_i].reset(this->dimensions, this->num_encodings()); + else + //NB: This does not actually clear the voxels, but instead sets a flag that designates them as being empty. + // Therefore the function 'Buffer_tpl::is_empty(const Image::Index&)' should be used to check before using a given voxel. + hessians[fibre_i].quick_clear(); + + + part_image(fibres[fibre_i], gradients[fibre_i], hessians[fibre_i]); + + + } + + for (typename Buffer_tpl::iterator vox_it = this->begin(); vox_it != this->end(); ++vox_it) + for (size_t encode_i = 0; encode_i < num_encodings(); ++encode_i) + vox_it->second[encode_i] *= fibres.base_intensity(); + + + for (size_t fibre_i = 0; fibre_i < fibres.size(); ++fibre_i) + for (typename Buffer_tpl::iterator vox_it = this->begin(); vox_it != this->end(); ++vox_it) + for (size_t encode_i = 0; encode_i < num_encodings(); ++encode_i) { + gradients[fibre_i](vox_it->first)[encode_i] *= fibres.base_intensity(); + hessians[fibre_i](vox_it->first)[encode_i] *= fibres.base_intensity(); + } + + + } + + + template Buffer_tpl& Buffer_tpl::operator+=(const Expected::Buffer& buff) { + + if (this->dims() != buff.dims()) + throw Exception ("Buffer dimensions do not match, " + str(buff.dims()) + " and " + str(this->dims()) + "."); + + std::set non_empty = buff.non_empty(); + + for (std::set::iterator coord_it = non_empty.begin(); coord_it != non_empty.end(); ++coord_it) + this->operator()(*coord_it) += buff(*coord_it); + + return *this; + + } + + template Buffer_tpl& Buffer_tpl::operator-=(const Expected::Buffer& buff) { + + if (this->dims() != buff.dims()) + throw Exception ("Buffer dimensions do not match, " + str(buff.dims()) + " and " + str(this->dims()) + "."); + + std::set non_empty = buff.non_empty(); + + for (std::set::iterator coord_it = non_empty.begin(); coord_it != non_empty.end(); ++coord_it) + this->operator()(*coord_it) -= buff(*coord_it); + + return *this; + + } + + template std::set& Buffer_tpl::get_neighbourhood(const Coord& point) { + + Index centre_coord = voxel_centre_coord(point); + + std::set& neighbourhood = neighbourhoods[centre_coord]; + + if (!neighbourhood.size()) + neighbourhoods[centre_coord] = create_neighbourhood(centre_coord); + + return neighbourhood; + + } + + template template std::set Buffer_tpl::get_neighbourhood(const typename U::Section& section) { + + std::set whole_neighbourhood; + + std::vector extreme_points = T::extreme_points(section); + + for (std::vector::iterator point_it = extreme_points.begin(); point_it != extreme_points.end(); ++point_it) { + std::set point_neighbourhood = get_neighbourhood(voxel_centre_coord(*point_it)); + whole_neighbourhood.insert(point_neighbourhood.begin(), point_neighbourhood.end()); + } + + return whole_neighbourhood; + + } + + + template std::set Buffer_tpl::create_neighbourhood(const Index& coord) { + + std::set neighbourhood; + + // Loop through all voxels within the interpolation extent of the given voxel and add their address to the + // neighbourhood vector. + for (int z_neigh = coord[Z] - neigh_extent; z_neigh < coord[Z] + neigh_extent; z_neigh++) + for (int y_neigh = coord[Y] - neigh_extent; y_neigh < coord[Y] + neigh_extent; y_neigh++) + for (int x_neigh = coord[X] - neigh_extent; x_neigh < coord[X] + neigh_extent; x_neigh++) { + + Index coord(x_neigh, y_neigh, z_neigh); + + if (!this->enforce_bounds || this->in_bounds(coord)) + neighbourhood.insert(&(this->operator()(coord))); + + } + + return neighbourhood; + + } + + + template std::ostream& Buffer_tpl::to_stream (std::ostream& stream) const { + + this->Observed::Buffer_tpl::to_stream(stream); + + stream << "Diffusion model: " << diffusion_model << std::endl; + stream << "Num sections: " << num_len_sections << std::endl; + stream << "Num strands: " << num_wth_sections << std::endl; + stream << "Interpolation extent: " << interp_extent << std::endl; + stream << "Neighbourhood extent: " << neigh_extent << std::endl; + + stream << "Neighbourhoods: " << std::endl; + + for (typename std::map< Index, std::set >::const_iterator neigh_it = neighbourhoods.begin(); neigh_it != neighbourhoods.end(); ++neigh_it) { + + stream << neigh_it->first << std::endl; + + for (typename std::set::const_iterator vox_it = neigh_it->second.begin(); vox_it != neigh_it->second.end(); ++vox_it) + stream << " " << (*vox_it)->centre() << std::endl; + + } + + stream << std::endl << std::endl; + + return stream; + + } + + + template std::ostream& operator<< (std::ostream& stream, const Buffer_tpl& buffer) { + + return buffer.to_stream(stream); + + } + + } + + } + + +} + +#undef LOOP + + +#endif /* __bts_image_expected_buffer_tpl_cpp_h__ */ diff --git a/src/bts/image/expected/buffer_tpl.h b/src/bts/image/expected/buffer_tpl.h new file mode 100644 index 0000000..7a033ba --- /dev/null +++ b/src/bts/image/expected/buffer_tpl.h @@ -0,0 +1,284 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, Mar 15, 2011. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + + +#ifndef __bts_image_expected_buffertpl_h__ +#define __bts_image_expected_buffertpl_h__ + +namespace BTS { + + namespace Image { + + namespace Expected { + + template class Buffer_tpl; + + } + + } + +} + +#include "bts/common.h" + +#include "bts/image/observed/buffer.h" +#include "bts/image/index.h" +#include "bts/image/container/buffer.h" +#include "bts/image/reference/buffer.h" + +#include "bts/fibre/strand.h" +#include "bts/fibre/tractlet.h" + +#include "bts/diffusion/model.h" + +#include "math/matrix.h" + +#include "bts/common.h" + +#include "bts/image/index.h" +#include "bts/image/buffer.h" +#include "bts/fibre/strand.h" +#include "bts/fibre/tractlet.h" + +#include "bts/diffusion/model.h" + +#include "bts/image/observed/buffer.h" +#include "bts/image/container/buffer.h" +#include "bts/image/expected/buffer.h" + +#define LOOP(op) \ +for (size_t z = 0; z < this->dim(Z); z++) { \ + for (size_t y = 0; y < this->dim(Y); y++) { \ + for (size_t x = 0; x < this->dim(X); x++) { \ + op \ + } \ + } \ +} + +namespace BTS { + + namespace Image { + + namespace Expected { + + template class Buffer_tpl: public Observed::Buffer_tpl { + + protected: + + Diffusion::Model diffusion_model; + + size_t num_len_sections; + size_t num_wth_sections; + + double interp_extent; + int neigh_extent; + + std::map > neighbourhoods; + + public: + //Holds all strand or tractlet sections used to generate the image. Storage here allows data structures to be + //reused between image generations. The size_t index indicates the strand index + std::map > strand_sections; + std::map > + tractlet_sections; + + //Holds all strand or tractlet sections used to generate the image. Storage here allows data structures to be + //reused between image generations. + Reference::Buffer::Set + strand_section_references; + Reference::Buffer::Set + tractlet_section_references; + + public: + + size_t num_length_sections() const { + return num_len_sections; + } + + size_t num_width_sections() const { + return num_wth_sections; + } + + template void expected_image( + const typename U::Set& fibres); + + template void part_image(const U& fibre); + + template typename Image::Reference::Buffer< + typename U::Section>::Set& expected_image_with_references( + const typename U::Set& fibres); + + template void part_image(const U& fibre, std::vector< + typename U::Section>& path, Image::Reference::Buffer< + typename U::Section>& section_reference); + + template void expected_image( + const typename U::Set& fibres, + typename Container::Buffer::Set& gradients); + + template void part_image(const U& fibre, + Container::Buffer& gradients); + + template void expected_image( + const typename U::Set& fibres, + typename Container::Buffer::Set& gradients, + typename Container::Buffer::Set& hessians); + + template void part_image(const U& fibre, + Container::Buffer& gradients, Container::Buffer< + typename U::Tensor>& hessians); + + template void precalculate_section_weighting_gradients(); + + template void + precalculate_section_weighting_gradients_and_hessians(); + + const Diffusion::Model& get_diffusion_model() const { + return diffusion_model; + } + + double get_extent() { + return interp_extent; + } + + void set_extent(double interp_extent) { + this->interp_extent = interp_extent; + neigh_extent = (size_t) std::ceil(interp_extent); + neighbourhoods.clear(); + } + + Buffer_tpl& clear() { + Image::Buffer_tpl::clear(); + neighbourhoods.clear(); + return *this; + } + + size_t num_encodings() const { + return diffusion_model.num_encodings(); + } + + const Diffusion::Encoding& encoding(size_t index) const { + return diffusion_model[index]; + } + + protected: + + Buffer_tpl(bool enforce_bounds = true) : + Observed::Buffer_tpl(enforce_bounds), num_len_sections(0), + num_wth_sections(0), interp_extent(0.0), neigh_extent(0) { + } + + Buffer_tpl(const Triple& dimensions, + const Triple& voxel_sizes, + const Diffusion::Model& diffusion_model, + size_t number_length_sections, size_t number_width_sections, + double interp_extent, const Triple& corner_offsets, + bool enforce_bounds) : + Observed::Buffer_tpl(dimensions, voxel_sizes, corner_offsets, + enforce_bounds), diffusion_model(diffusion_model), + num_len_sections(number_length_sections), num_wth_sections( + number_width_sections) + + { + + if (!number_length_sections) + throw Exception( + "Number of length sections in image cannot be zero."); + + if (!number_width_sections) + throw Exception( + "Number of length sections in image cannot be zero."); + + set_extent(interp_extent); + + } + + Buffer_tpl(const Buffer_tpl& bt) : + Observed::Buffer_tpl(bt), diffusion_model(bt.diffusion_model), + num_len_sections(bt.num_len_sections), num_wth_sections( + bt.num_wth_sections) + + { + set_extent(bt.interp_extent); + } + + virtual ~Buffer_tpl() { + } + + // Returns the 'neighbourhood' coordinate that the point lies in. The 'neighbourhood' coordinate is the coordinate + // that the point + [0.5,0.5,0.5] lies in. This is used to map the neighbourhood of voxels that lie + // within the interpolation extent about the given point (see set and get neighbourhoods). + Index voxel_centre_coord(const Coord& point) { + Coord offset_point = point + Coord::Halves; + Index coord((int) floor(offset_point[X]), (int) floor( + offset_point[Y]), (int) floor(offset_point[Z])); + return coord; + } + + std::set create_neighbourhood(const Index& coord); + + std::set& get_neighbourhood(const Coord& point); + + template std::set get_neighbourhood( + const typename U::Section& section); + + std::ostream& to_stream(std::ostream& stream) const; + + //The dummy arguments to the following functions is used in template functions to specify which type of section + //to return. + + std::map >& get_sections( + const Fibre::Strand& dummy) { + return strand_sections; + } + + std::map >& get_sections( + const Fibre::Tractlet& dummy) { + return tractlet_sections; + } + + Reference::Buffer::Set& get_section_references( + const Fibre::Strand& dummy) { + return strand_section_references; + } + + Reference::Buffer::Set& get_section_references( + const Fibre::Tractlet& dummy) { + return tractlet_section_references; + } + + + Buffer_tpl& operator+=(const Expected::Buffer& buffer); + + Buffer_tpl& operator-=(const Expected::Buffer& buffer); + + }; + + } + + } + +} + +#undef LOOP + +#endif /* */ diff --git a/src/bts/image/expected/direction.cpp.h b/src/bts/image/expected/direction.cpp.h new file mode 100644 index 0000000..c8bad1f --- /dev/null +++ b/src/bts/image/expected/direction.cpp.h @@ -0,0 +1,327 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, 17/06/2010. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + +#ifndef __bts_image_expected_direction_cpp_h__ +#define __bts_image_expected_direction_cpp_h__ + +#include "bts/image/expected/voxel.h" + +namespace BTS { + + namespace Image { + + + template double Expected::Direction::signal_tpl (const T& section) { + + //OPTIMISED makes use of the fact that each section is processed sequentially, allowing the weighting and interpolation to be + //precalculated and stored within the Diffusion::Response and Fabricated::Voxel objects respectively. Then quickly combined + //for all of the diffusion-weighting/voxel combinations. +#ifdef OPTIMISED + + double diffusion_weighting = section.precalc_weightings[response->get_index()]; + double interpolation_weighting = section.precalc_interpolation; + +#else //ifndef OPTIMISED + + double diffusion_weighting = response->weighting (section.tangent()); + double interpolation_weighting = voxel->interpolate(section); + +#endif + + + return section.intensity() * diffusion_weighting * interpolation_weighting; + + } + + template double Expected::Direction::signal_tpl (const T& section, Fibre::Strand::BasicSection& gradient) { + + //NB: diffusion gradient refers to the gradient of the section tangent + //w.r.t. the diffusion weighting, as opposed to the direction of the + //magnetic field "gradient". + + + //OPTIMISED makes use of the fact that each section is processed sequentially, allowing the weighting and interpolation to be + //precalculated and stored within the Diffusion::Response and Fabricated::Voxel objects respectively. Then quickly combined + //for all of the diffusion-weighting/voxel combinations. +#ifdef OPTIMISED + + double diffusion_weighting = section.precalc_weightings[response->get_index()]; + double interpolation_weighting = section.precalc_interpolation; + +#ifndef GRADIENT_NOT_REQUIRED + const Triple& diffusion_gradient = section.precalc_weight_gradients[response->get_index()]; + const Fibre::Strand::BasicSection& interpolation_gradient = section.precalc_interp_gradient; +#endif + +#else //ifndef OPTIMISED + + Coord diffusion_gradient; + T interpolation_gradient; + + double diffusion_weighting = response->weighting (section.tangent(), diffusion_gradient); + double interpolation_weighting = voxel->interpolate(section, interpolation_gradient); + +#endif + + +#ifndef GRADIENT_NOT_REQUIRED + signal_gradient(section, gradient, diffusion_weighting, interpolation_weighting, diffusion_gradient, interpolation_gradient); +#endif + + return section.intensity() * diffusion_weighting * interpolation_weighting; + + } + + + + + template double Expected::Direction::signal_tpl (const T& section, Fibre::Strand::BasicSection& gradient, typename T::Tensor& hessian) { + + + //NB: diffusion gradient refers to the gradient of the section tangent + //w.r.t. the diffusion weighting, as opposed to the direction of the + //magnetic field "gradient". + + + //OPTIMISED makes use of the fact that each section is processed sequentially, allowing the weighting and interpolation to be + //precalculated and stored within the Diffusion::Response and Fabricated::Voxel objects respectively. Then quickly combined + //for all of the diffusion-weighting/voxel combinations. +#ifdef OPTIMISED + + double diffusion_weighting = section.precalc_weightings[response->get_index()]; + double interpolation_weighting = section.precalc_interpolation; + +#ifndef GRADIENT_NOT_REQUIRED + const Triple& diffusion_gradient = section.precalc_weight_gradients[response->get_index()]; + const Fibre::Strand::BasicSection& interpolation_gradient = section.precalc_interp_gradient; + +#ifndef HESSIAN_NOT_REQUIRED + const Coord::Tensor& diffusion_hessian = section.precalc_weight_hessians[response->get_index()]; + const typename T::Tensor& interpolation_hessian = section.precalc_interp_hessian; +#endif + +#endif + +#else //ifndef OPTIMISED + + +#ifndef GRADIENT_NOT_REQUIRED + + Coord diffusion_gradient; + T interpolation_gradient; + +#ifndef HESSIAN_NOT_REQUIRED + + typename T::Tensor interpolation_hessian; + Coord::Tensor diffusion_hessian; + + double diffusion_weighting = response->weighting (section.tangent(), diffusion_gradient, diffusion_hessian); + double interpolation_weighting = voxel->interpolate(section, interpolation_gradient, interpolation_hessian); + +#else + + double diffusion_weighting = response->weighting (section.tangent, diffusion_gradient); + double interpolation_weighting = voxel->interpolate(section, interpolation_gradient); + +#endif + +#else + + double diffusion_weighting = response->weighting(section.tangent); + double interpolation_weighting = voxel->interpolate(section); + +#endif + +#endif + + +#ifndef GRADIENT_NOT_REQUIRED + signal_gradient(section, gradient, diffusion_weighting, interpolation_weighting, diffusion_gradient, interpolation_gradient); + +#ifndef HESSIAN_NOT_REQUIRED + signal_hessian(section, hessian, diffusion_weighting, interpolation_weighting, diffusion_gradient, interpolation_gradient, diffusion_hessian, interpolation_hessian); +#endif + +#endif + + return section.intensity() * diffusion_weighting * interpolation_weighting; + + + } + + + + inline void Expected::Direction::signal_gradient(const Fibre::Strand::Section& section, + Fibre::Strand::BasicSection& gradient, + double diffusion_weighting, + double interpolation_weighting, + const Triple& diffusion_gradient, + const Fibre::Strand::BasicSection& interpolation_gradient) { + + gradient.tangent() = (Coord)diffusion_gradient * (section.intensity() * interpolation_weighting) + interpolation_gradient.tangent() * (section.intensity() * diffusion_weighting); + + gradient.position() = interpolation_gradient.position() * (section.intensity() * diffusion_weighting); + + gradient.intensity() = diffusion_weighting * interpolation_weighting; + + + } + + inline void Expected::Direction::signal_gradient(const Fibre::Tractlet::Section& section, + Fibre::Strand::BasicSection& gradient, + double diffusion_weighting, + double interpolation_weighting, + const Triple& diffusion_gradient, + const Fibre::Strand::BasicSection& interpolation_gradient) { + + + //Call the Fibre::Strand::Section version of the function first, then process the additional parameters. + signal_gradient ((const Fibre::Strand::Section&)section, (Fibre::Strand::BasicSection&)gradient, diffusion_weighting, interpolation_weighting, diffusion_gradient, (const Fibre::Strand::BasicSection&)interpolation_gradient); + +// //Check to see if the tractlet section 'width' is used in the interpolation calculation. +// if (!interpolation_gradient.width1 || !interpolation_gradient.width2) { +// gradient.width1 = Triple::Zeros; +// gradient.width2 = Triple::Zeros; +// } else { +// gradient.width1 = interpolation_gradient.width1 * (section.intensity() * diffusion_weighting); +// gradient.width2 = interpolation_gradient.width2 * (section.intensity() * diffusion_weighting); +// } + + } + + + inline void Expected::Direction::signal_hessian(const Fibre::Strand::Section& section, + Fibre::Strand::BasicSection::Tensor& hessian, + double diff_weighting, + double interp_weighting, + const Triple& diff_gradient, + const Fibre::Strand::BasicSection& interp_gradient, + const Coord::Tensor& diff_hessian, + const Fibre::Strand::BasicSection::Tensor& interp_hessian) { + + //Set hessian intensity elements. + + hessian.intensity().intensity() = 0.0; + + hessian.intensity().tangent() = (Coord)diff_gradient * interp_weighting + interp_gradient.tangent() * diff_weighting; + hessian.intensity().position() = interp_gradient.position() * diff_weighting; + + //TODO: reformulate this code in terms of MR::Math::Matrix::sub + hessian.position(X).intensity() = hessian.intensity().position(X); + hessian.position(Y).intensity() = hessian.intensity().position(Y); + hessian.position(Z).intensity() = hessian.intensity().position(Z); + + hessian.tangent(X).intensity() = hessian.intensity().tangent(X); + hessian.tangent(Y).intensity() = hessian.intensity().tangent(Y); + hessian.tangent(Z).intensity() = hessian.intensity().tangent(Z); + + + //Set hessian position()-position() elements. + + hessian.position(X).position() = interp_hessian.position(X).position() * diff_weighting * section.intensity(); + hessian.position(Y).position() = interp_hessian.position(Y).position() * diff_weighting * section.intensity(); + hessian.position(Z).position() = interp_hessian.position(Z).position() * diff_weighting * section.intensity(); + + + //Set hessian tangent()-tangent() elements. + + Coord::Tensor tangent_hessian = section.intensity() * ( + diff_hessian * interp_weighting // FIXME: add a operator*(double) function for Coord::Tensor + + interp_gradient.tangent().outer(diff_gradient) + + ((Coord)diff_gradient).outer(interp_gradient.tangent()) + + interp_hessian.tangent() * diff_weighting); // FIXME: Make a tangent() function of BasicSection::Tensor + + hessian.tangent(X).tangent() = tangent_hessian[X]; + hessian.tangent(Y).tangent() = tangent_hessian[Y]; + hessian.tangent(Z).tangent() = tangent_hessian[Z]; + + + //Set hessian position()-tangent() and vice-versa elements. + + Coord::Tensor cross_hessian = section.intensity() * ( + interp_gradient.position().outer(diff_gradient) + + interp_hessian.position_tangent() * diff_weighting); // FIXME: Make a cross() function of BasicSection::Tensor + + + hessian.position(X).tangent() = cross_hessian[X]; + hessian.position(Y).tangent() = cross_hessian[Y]; + hessian.position(Z).tangent() = cross_hessian[Z]; + + hessian.tangent(X).position(X) = cross_hessian[X][X]; + hessian.tangent(X).position(Y) = cross_hessian[Y][X]; + hessian.tangent(X).position(Z) = cross_hessian[Z][X]; + + + hessian.tangent(Y).position(X) = cross_hessian[X][Y]; + hessian.tangent(Y).position(Y) = cross_hessian[Y][Y]; + hessian.tangent(Y).position(Z) = cross_hessian[Z][Y]; + + hessian.tangent(Z).position(X) = cross_hessian[X][Z]; + hessian.tangent(Z).position(Y) = cross_hessian[Y][Z]; + hessian.tangent(Z).position(Z) = cross_hessian[Z][Z]; + + } + + + + inline void Expected::Direction::signal_hessian(const Fibre::Tractlet::Section& section, + Fibre::Strand::BasicSection::Tensor& hessian, + double diffusion_weighting, + double interpolation_weighting, + const Triple& diffusion_gradient, + const Fibre::Strand::BasicSection& interpolation_gradient, + const Coord::Tensor& diffusion_hessian, + const Fibre::Strand::BasicSection::Tensor& interpolation_hessian) { + + + //Call the Fibre::Strand::Section version of the function first, then process the additional parameters. + signal_hessian ( (const Fibre::Strand::Section&)section, + (Fibre::Strand::BasicSection::Tensor&)hessian, + diffusion_weighting, + interpolation_weighting, + diffusion_gradient, + (const Fibre::Strand::Section&)interpolation_gradient, + diffusion_hessian, + (const Fibre::Strand::BasicSection::Tensor&)interpolation_hessian); + + //Check to see if the tractlet section 'width' is used in the interpolation calculation. + //TODO: Note Nonzero Tractlet::Section widths are not currently handled in Hessian calculation. + + } + + + + inline std::ostream& operator<<(std::ostream& stream, const Expected::Direction& direction) { + + stream << "Voxel: " << direction.voxel << ", Response: " << direction.response << std::endl; + + return stream; + + } + + } + +} + + + +#endif /* __bts_image_expected_direction_cpp_h__ */ diff --git a/src/bts/image/expected/direction.h b/src/bts/image/expected/direction.h new file mode 100644 index 0000000..b710add --- /dev/null +++ b/src/bts/image/expected/direction.h @@ -0,0 +1,149 @@ +/* + Copyright 2010 Brain Research Institute/National ICT Australia (NICTA), Melbourne, Australia + + Written by Voxelhomas G Close, 5/05/09. + + Voxelhis file is part of BTS. + + BTS 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. + + BTS is distributed in the hope that it will be useful, + but WIVoxelHOUVoxel ANY WARRANVoxelY; without even the implied warranty of + MERCHANVoxelABILIVoxelY or FIVoxelNESS FOR A PARVoxelICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with BTS. If not, see . + +*/ + +#ifndef __bts_image_expected_direction_h__ +#define __bts_image_expected_direction_h__ + +namespace BTS { + + namespace Image { + + namespace Expected { + + class Direction; + + } + + } + +} + +#include "bts/common.h" + +#include "bts/image/expected/voxel.h" +#include "bts/diffusion/response.h" + +#include "bts/triple.h" +#include "bts/fibre/strand/section.h" + + + +namespace BTS { + + namespace Image { + + namespace Expected { + + class Direction { + + //Public members + public: + + Voxel* voxel; + Diffusion::Response* response; + + //Public methods + public: + + Direction(Voxel& voxel, Diffusion::Response& response) + : voxel(&voxel), response(&response) {} + + ~Direction() {} + + //'signal' functions have explicit Fibre::Strand::Section and Fibre::Tractlet::Section arguments in favour of using + // the template directly so that their function signature can be passed as a pointer to GradientTester. + double signal(const Fibre::Strand::Section& section) + { return signal_tpl(section); } + + double signal(const Fibre::Tractlet::Section& section) + { return signal_tpl(section); } + + double signal(const Fibre::Strand::Section& section, Fibre::Strand::BasicSection& gradient) + { return signal_tpl(section,gradient); } + + double signal(const Fibre::Tractlet::Section& section, Fibre::Strand::BasicSection& gradient) + { return signal_tpl(section,gradient); } + + double signal(const Fibre::Strand::Section& section, Fibre::Strand::BasicSection& gradient, Fibre::Strand::BasicSection::Tensor& hessian) + { return signal_tpl(section,gradient,hessian); } + + double signal(const Fibre::Tractlet::Section& section, Fibre::Strand::BasicSection& gradient, Fibre::Strand::BasicSection::Tensor& hessian) + { return signal_tpl(section,gradient,hessian); } + + double b_value() const + { return response->b_value(); } + + const Diffusion::Encoding& encoding() const + { return *response; } + + protected: + + template double signal_tpl (const T& section); + + template double signal_tpl (const T& section, Fibre::Strand::BasicSection& gradient); + + template double signal_tpl (const T& section, Fibre::Strand::BasicSection& gradient, typename T::Tensor& hessian); + + static void signal_gradient(const Fibre::Strand::Section& section, + Fibre::Strand::BasicSection& gradient, + double diffusion_weighting, + double interpolation_weighting, + const Triple& diffusion_gradient, + const Fibre::Strand::BasicSection& interpolation_gradient); + + static void signal_gradient(const Fibre::Tractlet::Section& section, + Fibre::Strand::BasicSection& gradient, + double diffusion_weighting, + double interpolation_weighting, + const Triple& diffusion_gradient, + const Fibre::Strand::BasicSection& interpolation_gradient); + + static void signal_hessian(const Fibre::Strand::Section& section, + Fibre::Strand::BasicSection::Tensor& hessian, + double diffusion_weighting, + double interpolation_weighting, + const Triple& diffusion_gradient, + const Fibre::Strand::BasicSection& interpolation_gradient, + const Coord::Tensor& diffusion_hessian, + const Fibre::Strand::BasicSection::Tensor& interpolation_hessian); + + static void signal_hessian(const Fibre::Tractlet::Section& section, + Fibre::Strand::BasicSection::Tensor& hessian, + double diffusion_weighting, + double interpolation_weighting, + const Triple& diffusion_gradient, + const Fibre::Strand::BasicSection& interpolation_gradient, + const Coord::Tensor& diffusion_hessian, + const Fibre::Strand::BasicSection::Tensor& interpolation_hessian); + + + friend std::ostream& operator<< (std::ostream& stream, const Direction& direction); + + }; + + } + + } + +} + +#endif diff --git a/src/bts/image/expected/gaussian/buffer.cpp b/src/bts/image/expected/gaussian/buffer.cpp new file mode 100644 index 0000000..5da14f8 --- /dev/null +++ b/src/bts/image/expected/gaussian/buffer.cpp @@ -0,0 +1,74 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + +#include "bts/image/expected/gaussian/buffer.h" +#include "bts/image/expected/gaussian/voxel.h" + +#include "bts/fibre/strand/tensor.h" +#include "bts/fibre/tractlet/tensor.h" + +#include "bts/image/inline_functions.h" +#include "bts/diffusion/inline_functions.h" + + + +namespace BTS { + + namespace Image { + + namespace Expected { + + namespace Gaussian { + + const std::string Buffer::SHORT_NAME = "gaussian"; + + + Buffer::Buffer( const Triple& dimensions, + const Triple& voxel_sizes, + const Diffusion::Model& diffusion_model, + size_t num_sections, + size_t num_strands, + double extent, + double half_width, + const Triple& corner_offset, + bool enforce_bounds) + + : Buffer_tpl(dimensions, voxel_sizes, diffusion_model, num_sections, num_strands, extent, corner_offset, enforce_bounds), variance(half_width / (SQRT_LOG_2 * SQRT_2)) + { name_init(); } + + + Buffer::Buffer(const Buffer& buffer) + : Buffer_tpl(buffer), variance(buffer.variance) + { name_init(); } + + + std::ostream& operator<< (std::ostream& stream, const Buffer& buffer) + { return buffer.to_stream(stream); } + + } + + } + + } + +} + diff --git a/src/bts/image/expected/gaussian/buffer.h b/src/bts/image/expected/gaussian/buffer.h new file mode 100644 index 0000000..b2fe916 --- /dev/null +++ b/src/bts/image/expected/gaussian/buffer.h @@ -0,0 +1,95 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + +#include "bts/image/expected/gaussian/voxel.h" + +#ifndef __bts_image_expected_gaussian_buffer_h__ +#define __bts_image_expected_gaussian_buffer_h__ + + +#include "bts/image/expected/buffer.h" +#include "bts/image/expected/buffer_tpl.h" + + + +namespace BTS { + + namespace Image { + + namespace Expected { + + namespace Gaussian { + + class Buffer : public Expected::Buffer, public Expected::Buffer_tpl { + + //Public static constants + public: + + const static std::string SHORT_NAME; + + //Protected member variables + protected: + + double variance; + + public: + + Buffer() : Buffer_tpl(this) {} + + Buffer( const Triple& dimensions, + const Triple& voxel_sizes, + const Diffusion::Model& diffusion_model, + size_t num_sections = Expected::Buffer::NUM_LENGTH_SECTIONS_DEFAULT, + size_t num_strands = Expected::Buffer::NUM_WIDTH_SECTIONS_DEFAULT, + double interp_extent = Expected::Buffer::INTERP_EXTENT_DEFAULT, + double half_width = Expected::Buffer::HALF_WIDTH_DEFAULT, + const Triple& corner_offset = Triple(), + bool enforce_bounds = true + ); + + + Buffer(const Buffer& buffer); + + + ~Buffer() {} + + double gauss_exp_var() + { return variance; } + + EXPECTED_BUFFER_FUNCTIONS; + + }; + + + + std::ostream& operator<< (std::ostream& stream, const Buffer& buffer); + + } + + } + + } + +} + + +#endif diff --git a/src/bts/image/expected/gaussian/voxel.cpp b/src/bts/image/expected/gaussian/voxel.cpp new file mode 100644 index 0000000..924782e --- /dev/null +++ b/src/bts/image/expected/gaussian/voxel.cpp @@ -0,0 +1,84 @@ +/* + Copyright 2010 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close on May 19, 2010. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + +*/ + +#include "bts/image/expected/gaussian/voxel.h" +#include "bts/image/expected/gaussian/buffer.h" + +#include "bts/image/inline_functions.h" +#include "bts/diffusion/inline_functions.h" + + +namespace BTS { + + namespace Image { + + namespace Expected { + + namespace Gaussian { + + Voxel::Voxel(Buffer& buffer, const Index& coord) + : Expected::Voxel(buffer, coord, buffer.diffusion_model), image(&buffer) {} + + + double Voxel::interpolate(const Coord& pos) { + + Coord disp = pos - centre(); + + Coord interpolate ( exp(- MR::Math::pow2(disp[X]) / (2.0 * image->gauss_exp_var())), exp(- MR::Math::pow2(disp[Y]) / (2.0 * image->gauss_exp_var())), exp(- MR::Math::pow2(disp[Z]) / (2.0 * image->gauss_exp_var()))); + + interpolate /= sqrt( 2.0 * M_PI * image->gauss_exp_var()); + + return interpolate[X] * interpolate[Y] * interpolate[Z]; + + } + + + double Voxel::interpolate(const Coord& pos, Coord& pos_gradient) { + + Coord disp = pos - centre(); + + Coord interpolate ( exp(- MR::Math::pow2(disp[X]) / (2.0 * image->gauss_exp_var())), exp(- MR::Math::pow2(disp[Y]) / (2.0 * image->gauss_exp_var())), exp(- MR::Math::pow2(disp[Z]) / (2.0 * image->gauss_exp_var()))); + + interpolate /= sqrt( 2.0 * M_PI * image->gauss_exp_var()); + + double scalar; + + scalar = interpolate[X] * interpolate[Y] * interpolate[Z]; + + pos_gradient[X] = - disp[X] * scalar / image->gauss_exp_var(); + pos_gradient[Y] = - disp[Y] * scalar / image->gauss_exp_var(); + pos_gradient[Z] = - disp[Z] * scalar / image->gauss_exp_var(); + + return scalar; + + } + + + } + + } + + + } + +} + diff --git a/src/bts/image/expected/gaussian/voxel.h b/src/bts/image/expected/gaussian/voxel.h new file mode 100644 index 0000000..9f4c978 --- /dev/null +++ b/src/bts/image/expected/gaussian/voxel.h @@ -0,0 +1,102 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + + +#ifndef __bts_image_expected_gaussian_voxel_h__ +#define __bts_image_expected_gaussian_voxel_h__ + + +#include "bts/common.h" + +#include "bts/triple.h" + + + +#include "bts/image/expected/buffer.h" +#include "bts/image/observed/buffer.h" +#include "bts/image/expected/voxel.h" +#include "bts/image/expected/direction.h" + +#include "bts/diffusion/model.h" + + +namespace BTS { + + namespace Image { + + namespace Expected { + + namespace Gaussian { + + class Voxel : public Expected::Voxel { + + public: + + typedef Gaussian::Buffer Buffer; + + protected: + + Buffer* image; + + public: + + Voxel() {} + + + Voxel(Buffer& buffer, const Index& coord); + + + Voxel(const Voxel& voxel) + : Expected::Voxel(voxel), image(voxel.image) {} + + + Voxel& operator= (const Voxel& v) + { Expected::Voxel::operator=(v); image = v.image; return *this; } + + + ~Voxel() {} + + + // protected: + + double interpolate(const Coord& pos); + + double interpolate(const Coord& pos, Coord& gradient); + + double interpolate(const Coord& triple, Coord& gradient, Coord::Tensor& hessian) + { throw Exception ("Not implemented yet."); } + + + + + }; + + } + + } + + } + +} + + +#endif diff --git a/src/bts/image/expected/quartic/buffer.cpp b/src/bts/image/expected/quartic/buffer.cpp new file mode 100644 index 0000000..a924073 --- /dev/null +++ b/src/bts/image/expected/quartic/buffer.cpp @@ -0,0 +1,83 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + +#include "bts/image/expected/quartic/buffer.h" +#include "bts/image/expected/quartic/voxel.h" + +#include "bts/fibre/strand/tensor.h" +#include "bts/fibre/tractlet/tensor.h" + +#include "bts/image/inline_functions.h" +#include "bts/diffusion/inline_functions.h" + + +#define LOOP(op) \ +for (size_t z = 0; z < this->dim(Z); z++) { \ + for (size_t y = 0; y < this->dim(Y); y++) { \ + for (size_t x = 0; x < this->dim(X); x++) { \ + op \ + } \ + } \ +} + +namespace BTS { + + namespace Image { + + namespace Expected { + + namespace Quartic { + + + const std::string Buffer::SHORT_NAME = "quartic"; + + Buffer::Buffer( const Triple& dimensions, + const Triple& voxel_sizes, + const Diffusion::Model& diffusion_model, + size_t num_sections, + size_t num_strands, + double extent, + const Triple& corner_offset, + bool enforce_bounds) + + : Buffer_tpl(dimensions, voxel_sizes, diffusion_model, num_sections, num_strands, extent, corner_offset, enforce_bounds) + { name_init(); } + + + Buffer::Buffer(const Buffer& buffer) + : Buffer_tpl(buffer) + { name_init(); } + + + std::ostream& operator<< (std::ostream& stream, const Buffer& buffer) + { return buffer.to_stream(stream); } + + + } + + } + + } + +} + +#undef LOOP diff --git a/src/bts/image/expected/quartic/buffer.h b/src/bts/image/expected/quartic/buffer.h new file mode 100644 index 0000000..fb99cde --- /dev/null +++ b/src/bts/image/expected/quartic/buffer.h @@ -0,0 +1,87 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + +#include "bts/image/expected/quartic/voxel.h" + +#ifndef __bts_image_expected_quartic_buffer_h__ +#define __bts_image_expected_quartic_buffer_h__ + +#include "bts/image/expected/buffer.h" +#include "bts/image/expected/buffer_tpl.h" + + +namespace BTS { + + namespace Image { + + namespace Expected { + + namespace Quartic { + + + class Buffer : public Expected::Buffer, public Expected::Buffer_tpl { + + //Public static constants + public: + + const static std::string SHORT_NAME; + + public: + + Buffer() : Buffer_tpl(this) {} + + Buffer( const Triple& dimensions, + const Triple& voxel_sizes, + const Diffusion::Model& diffusion_model, + size_t num_sections = Expected::Buffer::NUM_LENGTH_SECTIONS_DEFAULT, + size_t num_strands = Expected::Buffer::NUM_WIDTH_SECTIONS_DEFAULT, + double extent = Expected::Buffer::INTERP_EXTENT_DEFAULT, + const Triple& corner_offset = Triple (), + bool enforce_bounds = true + ); + + + Buffer(const Buffer& buffer); + + + ~Buffer() {} + + + EXPECTED_BUFFER_FUNCTIONS; + + }; + + + + std::ostream& operator<< (std::ostream& stream, const Buffer& buffer); + + + } + + } + + } + +} + + +#endif diff --git a/src/bts/image/expected/quartic/voxel.cpp b/src/bts/image/expected/quartic/voxel.cpp new file mode 100644 index 0000000..194cae5 --- /dev/null +++ b/src/bts/image/expected/quartic/voxel.cpp @@ -0,0 +1,249 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + +#include "bts/image/expected/quartic/voxel.h" +#include "bts/image/expected/quartic/buffer.h" + + +#include "bts/fibre/strand/basic_section/tensor.h" +#include "bts/fibre/tractlet/section/tensor.h" + +#include "bts/image/inline_functions.h" +#include "bts/diffusion/inline_functions.h" + + +namespace BTS { + + namespace Image { + + namespace Expected { + + namespace Quartic { + + + Voxel::Voxel(Buffer& buffer, const Index& coord) + : Expected::Voxel(buffer, coord, buffer.diffusion_model), image(&buffer) {} + + + + +//----------------------// +// Non Hessian versions // +//----------------------// + + + double Voxel::interpolate(const Coord& pos) { + + Coord disp = pos - this->centre(); + + Coord interpolate; + + double interpolation; + + if (disp.lower_bounded(-1.0) && disp.upper_bounded(1.0)) { + + for (size_t dim_i = 0; dim_i < 3; ++dim_i) + interpolate[dim_i] = MR::Math::pow4(disp[dim_i]) - 2.0 * MR::Math::pow2(disp[dim_i]) + 1; + + interpolation = interpolate[X] * interpolate[Y] * interpolate[Z]; + + } else { + interpolation = 0.0; + } + + return interpolation; + + } + + + double Voxel::interpolate(const Coord& pos, Coord& pos_gradient) { + + Coord disp = pos - this->centre(); + + Coord interpolate; + + double interpolation; + + if (disp.lower_bounded(-1.0) && disp.upper_bounded(1.0)) { + + for (size_t dim_i = 0; dim_i < 3; ++dim_i) + interpolate[dim_i] = MR::Math::pow4(disp[dim_i]) - 2.0 * MR::Math::pow2(disp[dim_i]) + 1; + + interpolation = interpolate[X] * interpolate[Y] * interpolate[Z]; + +#ifndef GRADIENT_NOT_REQUIRED + pos_gradient[X] = (4.0 * MR::Math::pow3(disp[X]) - 4.0 * disp[X]) * interpolate[Y] * interpolate[Z]; + pos_gradient[Y] = (4.0 * MR::Math::pow3(disp[Y]) - 4.0 * disp[Y]) * interpolate[X] * interpolate[Z]; + pos_gradient[Z] = (4.0 * MR::Math::pow3(disp[Z]) - 4.0 * disp[Z]) * interpolate[X] * interpolate[Y]; +#endif //GRADIENT_NOT_REQUIRED not defined + + } else { + interpolation = 0.0; + pos_gradient = Coord::Zeros; + } + + return interpolation; + + } + + + double Voxel::interpolate(const Fibre::Strand::BasicSection& section) { + + double pos_interp = interpolate(section.position()); + double tan_norm = section.tangent().norm(); + + return pos_interp * tan_norm; + + } + + double Voxel::interpolate(const Fibre::Strand::BasicSection& section, Fibre::Strand::BasicSection& gradient) { + + Coord pos_interp_gradient; + Coord tan_norm_gradient; + + double pos_interp = interpolate(section.position(), pos_interp_gradient); + double tan_norm = section.tangent().norm(tan_norm_gradient); + + gradient.zero(); + + gradient.position() = tan_norm * pos_interp_gradient; + gradient.tangent() = pos_interp * tan_norm_gradient; + + return pos_interp * tan_norm; + + } + + + + +//------------------// +// Hessian versions // +//------------------// + + + + double Voxel::interpolate(const Coord& pos, Coord& gradient, Coord::Tensor& hessian) { + + + Coord disp = pos - this->centre(); + + Coord interpolate; + + double interpolation; + + if (disp.lower_bounded(-1.0) && disp.upper_bounded(1.0)) { + + for (size_t dim_i = 0; dim_i < 3; ++dim_i) + interpolate[dim_i] = MR::Math::pow4(disp[dim_i]) - 2.0 * MR::Math::pow2(disp[dim_i]) + 1; + + interpolation = interpolate[X] * interpolate[Y] * interpolate[Z]; + + Coord partial; + + partial[X] = (4.0 * MR::Math::pow3(disp[X]) - 4.0 * disp[X]); + partial[Y] = (4.0 * MR::Math::pow3(disp[Y]) - 4.0 * disp[Y]); + partial[Z] = (4.0 * MR::Math::pow3(disp[Z]) - 4.0 * disp[Z]); + + gradient[X] = partial[X] * interpolate[Y] * interpolate[Z]; + gradient[Y] = interpolate[X] * partial[Y] * interpolate[Z]; + gradient[Z] = interpolate[X] * interpolate[Y] * partial[Z]; + + hessian[X][X] = (12.0 * MR::Math::pow2(disp[X]) - 4.0) * interpolate[Y] * interpolate[Z]; + hessian[X][Y] = hessian[Y][X] = partial[X] * partial[Y] * interpolate[Z]; + hessian[X][Z] = hessian[Z][X] = partial[X] * interpolate[Y] * partial[Z]; + + hessian[Y][Y] = interpolate[X] * (12.0 * MR::Math::pow2(disp[Y]) - 4.0) * interpolate[Z]; + hessian[Y][Z] = hessian[Z][Y] = interpolate[X] * partial[Y] * partial[Z]; + + hessian[Z][Z] = interpolate[X] * interpolate[Y] * (12.0 * MR::Math::pow2(disp[Z]) - 4.0); + + + } else { + interpolation = 0.0; + gradient.zero(); + hessian.zero(); + } + + return interpolation; + + } + + + + + double Voxel::interpolate(const Fibre::Strand::BasicSection& section, Fibre::Strand::BasicSection& gradient, Fibre::Strand::BasicSection::Tensor& hessian) { + + Coord pos_interp_gradient; + Coord tan_norm_gradient; + Coord::Tensor interp_hessian; + Coord::Tensor norm_hessian; + + double pos_interp = interpolate(section.position(), pos_interp_gradient, interp_hessian); + double tan_norm = section.tangent().norm(tan_norm_gradient, norm_hessian); + + gradient.zero(); + + gradient.position() = tan_norm * pos_interp_gradient; + gradient.tangent() = pos_interp * tan_norm_gradient; + + + hessian.zero(); + + hessian.position(X).position() = tan_norm * interp_hessian[X]; + hessian.position(Y).position() = tan_norm * interp_hessian[Y]; + hessian.position(Z).position() = tan_norm * interp_hessian[Z]; + + hessian.position(X).tangent() = pos_interp_gradient[X] * tan_norm_gradient; + hessian.position(Y).tangent() = pos_interp_gradient[Y] * tan_norm_gradient; + hessian.position(Z).tangent() = pos_interp_gradient[Z] * tan_norm_gradient; + + hessian.tangent(X).tangent() = pos_interp * norm_hessian[X]; + hessian.tangent(Y).tangent() = pos_interp * norm_hessian[Y]; + hessian.tangent(Z).tangent() = pos_interp * norm_hessian[Z]; + + hessian.tangent(X).position() = pos_interp_gradient * tan_norm_gradient[X]; + hessian.tangent(Y).position() = pos_interp_gradient * tan_norm_gradient[Y]; + hessian.tangent(Z).position() = pos_interp_gradient * tan_norm_gradient[Z]; + + return pos_interp * tan_norm; + + } + + double Voxel::interpolate(const Fibre::Tractlet::Section& section, Fibre::Tractlet::Section& gradient, Fibre::Tractlet::Section::Tensor& hessian) { + + Fibre::Strand::BasicSection::Tensor strand_hessian; + + double interp = interpolate((const Fibre::Strand::BasicSection&)section, (Fibre::Strand::BasicSection&)gradient, strand_hessian); + + hessian = strand_hessian; + + return interp; + + } + + } + + } + + } + +} diff --git a/src/bts/image/expected/quartic/voxel.h b/src/bts/image/expected/quartic/voxel.h new file mode 100644 index 0000000..92b0776 --- /dev/null +++ b/src/bts/image/expected/quartic/voxel.h @@ -0,0 +1,115 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + + +#ifndef __bts_image_expected_quartic_voxel_h__ +#define __bts_image_expected_quartic_voxel_h__ + + +#include "bts/common.h" + +#include "bts/triple.h" + +#include "bts/image/expected/buffer.h" +#include "bts/image/observed/buffer.h" +#include "bts/image/expected/voxel.h" +#include "bts/image/expected/direction.h" + +#include "bts/diffusion/model.h" + + +namespace BTS { + + namespace Image { + + namespace Expected { + + namespace Quartic { + + class Voxel : public Expected::Voxel { + + public: + + typedef Quartic::Buffer Buffer; + + protected: + + Buffer* image; + + public: + + Voxel() {} + + + Voxel(Buffer& buffer, const Index& coord); + + //! doesn't copy across the parent image. + Voxel(const Voxel& v) + : Expected::Voxel(v), image(v.image) {} + + //! doesn't copy across the parent image. + Voxel& operator= (const Voxel& v) + { Expected::Voxel::operator=(v); image = v.image; return *this; } + + ~Voxel() {} + + + void set_image(Buffer* image) + { this->image = image; } + + double interpolate(const Fibre::Strand::BasicSection& section); + + /*!The Strand::Section and Tractlet::Section interpolation methods are not strictly necessary as they copy virtual functions from the Expected::Voxel base class. + However they will allow the interpolate functions to be inlined and since this is an inner loop it could be critical.*/ + double interpolate(const Fibre::Strand::BasicSection& section, Fibre::Strand::BasicSection& gradient); + + + double interpolate(const Fibre::Strand::BasicSection& section, Fibre::Strand::BasicSection& gradient, Fibre::Strand::BasicSection::Tensor& hessian); + + + double interpolate(const Fibre::Tractlet::Section& section, Fibre::Tractlet::Section& gradient) + { return interpolate((const Fibre::Strand::BasicSection&)section, (Fibre::Strand::BasicSection&)gradient); } + + + double interpolate(const Fibre::Tractlet::Section& section, Fibre::Tractlet::Section& gradient, Fibre::Tractlet::Section::Tensor& hessian); + + // protected: + + double interpolate(const Coord& pos); + + double interpolate(const Coord& pos, Coord& gradient); + + double interpolate(const Coord& triple, Coord& gradient, Coord::Tensor& hessian); + + + }; + + } + + } + + } + +} + + +#endif diff --git a/src/bts/image/expected/realistic/buffer.cpp b/src/bts/image/expected/realistic/buffer.cpp new file mode 100644 index 0000000..291d39f --- /dev/null +++ b/src/bts/image/expected/realistic/buffer.cpp @@ -0,0 +1,82 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + +#include "bts/image/expected/realistic/buffer.h" +#include "bts/image/expected/realistic/voxel.h" + +#include "bts/fibre/strand/tensor.h" +#include "bts/fibre/tractlet/tensor.h" + +#include "bts/image/inline_functions.h" +#include "bts/diffusion/inline_functions.h" + + +#define LOOP(op) \ +for (size_t z = 0; z < this->dim(Z); z++) { \ + for (size_t y = 0; y < this->dim(Y); y++) { \ + for (size_t x = 0; x < this->dim(X); x++) { \ + op \ + } \ + } \ +} + +namespace BTS { + + namespace Image { + + namespace Expected { + + namespace Realistic { + + const std::string Buffer::SHORT_NAME = "realistic"; + + + Buffer::Buffer( const Triple& dimensions, + const Triple& voxel_sizes, + const Diffusion::Model& diffusion_model, + size_t num_sections, + size_t num_strands, + double extent, + const Triple& corner_offset, + bool enforce_bounds) + : Buffer_tpl(dimensions, voxel_sizes, diffusion_model, num_sections, num_strands, extent, corner_offset, enforce_bounds) + { name_init(); } + + + Buffer::Buffer(const Buffer& buffer) + : Buffer_tpl(buffer) + { name_init(); } + + + std::ostream& operator<< (std::ostream& stream, const Buffer& buffer) + { return buffer.to_stream(stream); } + + } + + } + + + } + +} + +#undef LOOP diff --git a/src/bts/image/expected/realistic/buffer.h b/src/bts/image/expected/realistic/buffer.h new file mode 100644 index 0000000..ceb5c33 --- /dev/null +++ b/src/bts/image/expected/realistic/buffer.h @@ -0,0 +1,85 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + +#include "bts/image/expected/realistic/voxel.h" + +#ifndef __bts_image_expected_realistic_buffer_h__ +#define __bts_image_expected_realistic_buffer_h__ + +#include "bts/image/expected/buffer.h" +#include "bts/image/expected/buffer_tpl.h" + + +namespace BTS { + + namespace Image { + + namespace Expected { + + namespace Realistic { + + class Buffer : public Expected::Buffer, public Expected::Buffer_tpl { + + //Public static constants + public: + + const static std::string SHORT_NAME; + + public: + + Buffer() : Buffer_tpl(this) {} + + Buffer( const Triple& dimensions, + const Triple& voxel_sizes, + const Diffusion::Model& diffusion_model, + size_t num_sections = NUM_LENGTH_SECTIONS_DEFAULT, + size_t num_strands = NUM_WIDTH_SECTIONS_DEFAULT, + double extent = INTERP_EXTENT_DEFAULT, + const Triple& corner_offset = Triple (), + bool enforce_bounds = true + ); + + + Buffer(const Buffer& buffer); + + + ~Buffer() {} + + + EXPECTED_BUFFER_FUNCTIONS;; + + }; + + + + std::ostream& operator<< (std::ostream& stream, const Buffer& buffer); + + } + + } + + } + +} + + +#endif diff --git a/src/bts/image/expected/realistic/voxel.cpp b/src/bts/image/expected/realistic/voxel.cpp new file mode 100644 index 0000000..bd9390e --- /dev/null +++ b/src/bts/image/expected/realistic/voxel.cpp @@ -0,0 +1,89 @@ +/* + Copyright 2010 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close on May 19, 2010. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + +*/ + +#include "bts/image/expected/realistic/voxel.h" +#include "bts/image/expected/realistic/buffer.h" + +#include "bts/image/inline_functions.h" +#include "bts/diffusion/inline_functions.h" + +namespace BTS { + + namespace Image { + + namespace Expected { + + namespace Realistic { + + Voxel::Voxel(Buffer& buffer, const Index& coord) + : Expected::Voxel(buffer, coord, buffer.diffusion_model), image(&buffer) {} + + + double Expected::Realistic::Voxel::interpolate(const Coord& pos) { + + Coord disp = pos - this->centre(); + + Coord interpolate; + + double interpolation; + + //Truncate the sinc function at a consitent distance from the voxel centre. + if (disp.lower_bounded(-image->get_extent()) && disp.upper_bounded(image->get_extent())) { + + //Do X and Y as a Sinc + for (size_t dim_i = 0; dim_i < 2; ++dim_i) { + + if (disp[dim_i] == 0.0) + interpolate[dim_i] = 1.0; + else + interpolate[dim_i] = MR::Math::sin(M_PI * disp[dim_i]) / (M_PI * disp[dim_i]); + } + + if ((disp[Z] < 1) && (disp[Z] > -1)) + interpolate[Z] = (MR::Math::pow4(disp[Z]) - 2.0 * MR::Math::pow2(disp[Z]) + 1); + else + interpolate[Z] = 0.0; + + interpolation = interpolate[X] * interpolate[Y] * interpolate[Z]; + + } else + interpolation = 0.0; + + return interpolation; + + } + + + double Expected::Realistic::Voxel::interpolate(const Coord& pos, Coord& pos_gradient) { + + throw Exception ("Expected::Realistic::Voxel::interpolate(const Coord&, Coord&) not implemented yet."); + + } + + } + + } + + } + +} + diff --git a/src/bts/image/expected/realistic/voxel.h b/src/bts/image/expected/realistic/voxel.h new file mode 100644 index 0000000..6665d03 --- /dev/null +++ b/src/bts/image/expected/realistic/voxel.h @@ -0,0 +1,94 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + + +#ifndef __bts_image_expected_realistic_voxel_h__ +#define __bts_image_expected_realistic_voxel_h__ + +#include "bts/common.h" + +#include "bts/triple.h" + +#include "bts/image/expected/buffer.h" +#include "bts/image/observed/buffer.h" +#include "bts/image/expected/voxel.h" +#include "bts/image/expected/direction.h" + +#include "bts/diffusion/model.h" + + + +namespace BTS { + + namespace Image { + + namespace Expected { + + namespace Realistic { + + class Voxel : public Expected::Voxel { + + public: + + typedef Realistic::Buffer Buffer; + + protected: + + Buffer* image; + + public: + + Voxel() {} + + Voxel(Buffer& buffer, const Index& coord); + + Voxel(const Voxel& voxel) + : Expected::Voxel(voxel), image(voxel.image) {} + + Voxel& operator= (const Voxel& v) + { Expected::Voxel::operator=(v); image = v.image; return *this; } + + ~Voxel() {} + + + // protected: + + double interpolate(const Coord& pos); + + double interpolate(const Coord& pos, Coord& gradient); + + double interpolate(const Coord& triple, Coord& gradient, Coord::Tensor& hessian) + { throw Exception ("Gradient is not defined for Top-hat interpolation."); } + + + }; + + } + + } + + } + +} + + +#endif diff --git a/src/bts/image/expected/reverse_sqrt/buffer.cpp b/src/bts/image/expected/reverse_sqrt/buffer.cpp new file mode 100644 index 0000000..cbbadd7 --- /dev/null +++ b/src/bts/image/expected/reverse_sqrt/buffer.cpp @@ -0,0 +1,82 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + +#include "bts/image/expected/reverse_sqrt/buffer.h" +#include "bts/image/expected/reverse_sqrt/voxel.h" + +#include "bts/fibre/strand/tensor.h" +#include "bts/fibre/tractlet/tensor.h" + +#include "bts/image/inline_functions.h" +#include "bts/diffusion/inline_functions.h" + + +#define LOOP(op) \ +for (size_t z = 0; z < this->dim(Z); z++) { \ + for (size_t y = 0; y < this->dim(Y); y++) { \ + for (size_t x = 0; x < this->dim(X); x++) { \ + op \ + } \ + } \ +} + +namespace BTS { + + namespace Image { + + namespace Expected { + + namespace ReverseSqrt { + + const std::string Buffer::SHORT_NAME = "reverse_sqrt"; + + + Buffer::Buffer( const Triple& dimensions, + const Triple& voxel_sizes, + const Diffusion::Model& diffusion_model, + size_t num_sections, + size_t num_strands, + double extent, + const Triple& corner_offset, + bool enforce_bounds) + : Buffer_tpl(dimensions, voxel_sizes, diffusion_model, num_sections, num_strands, extent, corner_offset, enforce_bounds) + { name_init(); } + + + Buffer::Buffer(const Buffer& buffer) + : Buffer_tpl(buffer) + { name_init(); } + + + std::ostream& operator<< (std::ostream& stream, const Buffer& buffer) + { return buffer.to_stream(stream); } + + } + + } + + + } + +} + +#undef LOOP diff --git a/src/bts/image/expected/reverse_sqrt/buffer.h b/src/bts/image/expected/reverse_sqrt/buffer.h new file mode 100644 index 0000000..d14597a --- /dev/null +++ b/src/bts/image/expected/reverse_sqrt/buffer.h @@ -0,0 +1,85 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + +#include "bts/image/expected/reverse_sqrt/voxel.h" + +#ifndef __bts_image_expected_reversesqrt_buffer_h__ +#define __bts_image_expected_reversesqrt_buffer_h__ + +#include "bts/image/expected/buffer.h" +#include "bts/image/expected/buffer_tpl.h" + + +namespace BTS { + + namespace Image { + + namespace Expected { + + namespace ReverseSqrt { + + class Buffer : public Expected::Buffer, public Expected::Buffer_tpl { + + //Public static constants + public: + + const static std::string SHORT_NAME; + + public: + + Buffer() : Buffer_tpl(this) {} + + Buffer( const Triple& dimensions, + const Triple& voxel_sizes, + const Diffusion::Model& diffusion_model, + size_t num_sections = NUM_LENGTH_SECTIONS_DEFAULT, + size_t num_strands = NUM_WIDTH_SECTIONS_DEFAULT, + double extent = INTERP_EXTENT_DEFAULT, + const Triple& corner_offset = Triple (), + bool enforce_bounds = true + ); + + + Buffer(const Buffer& buffer); + + + ~Buffer() {} + + + EXPECTED_BUFFER_FUNCTIONS; + + }; + + + + std::ostream& operator<< (std::ostream& stream, const Buffer& buffer); + + } + + } + + } + +} + + +#endif diff --git a/src/bts/image/expected/reverse_sqrt/voxel.cpp b/src/bts/image/expected/reverse_sqrt/voxel.cpp new file mode 100644 index 0000000..0c1d7f3 --- /dev/null +++ b/src/bts/image/expected/reverse_sqrt/voxel.cpp @@ -0,0 +1,73 @@ +/* + Copyright 2010 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close on May 19, 2010. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + +*/ + +#include "bts/image/expected/reverse_sqrt/voxel.h" +#include "bts/image/expected/reverse_sqrt/buffer.h" + +#include "bts/image/inline_functions.h" +#include "bts/diffusion/inline_functions.h" + +namespace BTS { + + namespace Image { + + namespace Expected { + + namespace ReverseSqrt { + + Voxel::Voxel(Buffer& buffer, const Index& coord) + : Expected::Voxel(buffer, coord, buffer.diffusion_model), image(&buffer) {} + + + double Expected::ReverseSqrt::Voxel::interpolate(const Coord& pos) { + + Coord disp = pos - centre(); + + double scalar = 1.0; + + if (disp.upper_bounded(1.0) && disp.lower_bounded(-1.0)) { + + for (size_t dim_i = 0; dim_i < 3; dim_i++) + scalar *= MR::Math::sqrt(1.0 - MR::Math::abs(disp[dim_i]));// * 3.0 / 2.0; + + } else + scalar = 0.0; + + return scalar; + + } + + + double Expected::ReverseSqrt::Voxel::interpolate(const Coord& pos, Coord& pos_gradient) { + + throw Exception ("Expected::ReverseSqrt::Voxel::interpolate(const Coord&, Coord&) not implemented yet."); + + } + + } + + } + + } + +} + diff --git a/src/bts/image/expected/reverse_sqrt/voxel.h b/src/bts/image/expected/reverse_sqrt/voxel.h new file mode 100644 index 0000000..5e499c6 --- /dev/null +++ b/src/bts/image/expected/reverse_sqrt/voxel.h @@ -0,0 +1,94 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + + +#ifndef __bts_image_expected_reversesqrt_voxel_h__ +#define __bts_image_expected_reversesqrt_voxel_h__ + +#include "bts/common.h" + +#include "bts/triple.h" + +#include "bts/image/expected/buffer.h" +#include "bts/image/observed/buffer.h" +#include "bts/image/expected/voxel.h" +#include "bts/image/expected/direction.h" + +#include "bts/diffusion/model.h" + + + +namespace BTS { + + namespace Image { + + namespace Expected { + + namespace ReverseSqrt { + + class Voxel : public Expected::Voxel { + + public: + + typedef ReverseSqrt::Buffer Buffer; + + protected: + + Buffer* image; + + public: + + Voxel() {} + + Voxel(Buffer& buffer, const Index& coord); + + Voxel(const Voxel& voxel) + : Expected::Voxel(voxel), image(voxel.image) {} + + Voxel& operator= (const Voxel& v) + { Expected::Voxel::operator=(v); image = v.image; return *this; } + + ~Voxel() {} + + + // protected: + + double interpolate(const Coord& pos); + + double interpolate(const Coord& pos, Coord& gradient); + + double interpolate(const Coord& triple, Coord& gradient, Coord::Tensor& hessian) + { throw Exception ("Gradient is not defined for Top-hat interpolation."); } + + + }; + + } + + } + + } + +} + + +#endif diff --git a/src/bts/image/expected/sinc/buffer.cpp b/src/bts/image/expected/sinc/buffer.cpp new file mode 100644 index 0000000..9bfe7e6 --- /dev/null +++ b/src/bts/image/expected/sinc/buffer.cpp @@ -0,0 +1,82 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + +#include "bts/image/expected/sinc/buffer.h" +#include "bts/image/expected/sinc/voxel.h" + +#include "bts/fibre/strand/tensor.h" +#include "bts/fibre/tractlet/tensor.h" + +#include "bts/image/inline_functions.h" +#include "bts/diffusion/inline_functions.h" + + +#define LOOP(op) \ +for (size_t z = 0; z < this->dim(Z); z++) { \ + for (size_t y = 0; y < this->dim(Y); y++) { \ + for (size_t x = 0; x < this->dim(X); x++) { \ + op \ + } \ + } \ +} + +namespace BTS { + + namespace Image { + + namespace Expected { + + namespace Sinc { + + + const std::string Buffer::SHORT_NAME = "sinc"; + + Buffer::Buffer( const Triple& dimensions, + const Triple& voxel_sizes, + const Diffusion::Model& diffusion_model, + size_t num_sections, + size_t num_strands, + double extent, + const Triple& corner_offset, + bool enforce_bounds) + + : Buffer_tpl(dimensions, voxel_sizes, diffusion_model, num_sections, num_strands, extent, corner_offset, enforce_bounds) + { name_init(); } + + + Buffer::Buffer(const Buffer& buffer) + : Buffer_tpl(buffer) + { name_init(); } + + std::ostream& operator<< (std::ostream& stream, const Buffer& buffer) + { return buffer.to_stream(stream); } + + + } + + } + + } + +} + +#undef LOOP diff --git a/src/bts/image/expected/sinc/buffer.h b/src/bts/image/expected/sinc/buffer.h new file mode 100644 index 0000000..71d7fc5 --- /dev/null +++ b/src/bts/image/expected/sinc/buffer.h @@ -0,0 +1,85 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + +#include "bts/image/expected/sinc/voxel.h" + +#ifndef __bts_image_expected_sinc_buffer_h__ +#define __bts_image_expected_sinc_buffer_h__ + +#include "bts/image/expected/buffer.h" +#include "bts/image/expected/buffer_tpl.h" + + +namespace BTS { + + namespace Image { + + namespace Expected { + + namespace Sinc { + + class Buffer : public Expected::Buffer, public Expected::Buffer_tpl { + + //Public static constants + public: + + const static std::string SHORT_NAME; + + public: + + Buffer() : Buffer_tpl(this) {} + + Buffer( const Triple& dimensions, + const Triple& voxel_sizes, + const Diffusion::Model& diffusion_model, + size_t num_sections = Expected::Buffer::NUM_LENGTH_SECTIONS_DEFAULT, + size_t num_strands = Expected::Buffer::NUM_WIDTH_SECTIONS_DEFAULT, + double extent = Expected::Buffer::INTERP_EXTENT_DEFAULT, + const Triple& corner_offset = Triple (), + bool enforce_bounds = true + ); + + + Buffer(const Buffer& buffer); + + + ~Buffer() {} + + EXPECTED_BUFFER_FUNCTIONS; + + }; + + + + std::ostream& operator<< (std::ostream& stream, const Buffer& buffer); + + + } + + } + + } + +} + + +#endif diff --git a/src/bts/image/expected/sinc/voxel.cpp b/src/bts/image/expected/sinc/voxel.cpp new file mode 100644 index 0000000..bab1de9 --- /dev/null +++ b/src/bts/image/expected/sinc/voxel.cpp @@ -0,0 +1,83 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + +#include "bts/image/expected/sinc/voxel.h" +#include "bts/image/expected/sinc/buffer.h" + + +#include "bts/fibre/strand/basic_section/tensor.h" +#include "bts/fibre/tractlet/section/tensor.h" + +#include "bts/image/inline_functions.h" +#include "bts/diffusion/inline_functions.h" + + +namespace BTS { + + namespace Image { + + namespace Expected { + + namespace Sinc { + + + Voxel::Voxel(Buffer& buffer, const Index& coord) + : Expected::Voxel(buffer, coord, buffer.diffusion_model), image(&buffer) {} + + + double Voxel::interpolate(const Coord& pos) { + + Coord disp = pos - centre(); + + Coord interpolate; + + double interpolation; + + //Truncate the sinc function at a consitent distance from the voxel centre. + if (disp.lower_bounded(-image->get_extent()) && disp.upper_bounded(image->get_extent())) { + + for (size_t dim_i = 0; dim_i < 3; ++dim_i) { + + if (disp[dim_i] == 0.0) + interpolate[dim_i] = 1.0; + else + interpolate[dim_i] = MR::Math::sin(M_PI * disp[dim_i]) / (M_PI * disp[dim_i]); + } + + interpolation = interpolate[X] * interpolate[Y] * interpolate[Z]; + + } else + interpolation = 0.0; + + + return interpolation; + + } + + + } + + } + + } + +} diff --git a/src/bts/image/expected/sinc/voxel.h b/src/bts/image/expected/sinc/voxel.h new file mode 100644 index 0000000..053b779 --- /dev/null +++ b/src/bts/image/expected/sinc/voxel.h @@ -0,0 +1,100 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + + +#ifndef __bts_image_expected_sinc_voxel_h__ +#define __bts_image_expected_sinc_voxel_h__ + + +#include "bts/common.h" + +#include "bts/triple.h" + +#include "bts/image/expected/buffer.h" +#include "bts/image/observed/buffer.h" +#include "bts/image/expected/voxel.h" +#include "bts/image/expected/direction.h" + +#include "bts/diffusion/model.h" + + +namespace BTS { + + namespace Image { + + namespace Expected { + + namespace Sinc { + + class Voxel : public Expected::Voxel { + + public: + + typedef Sinc::Buffer Buffer; + + protected: + + Buffer* image; + + public: + + Voxel() {} + + + Voxel(Buffer& buffer, const Index& coord); + + //! doesn't copy across the parent image. + Voxel(const Voxel& v) + : Expected::Voxel(v), image(v.image) {} + + //! doesn't copy across the parent image. + Voxel& operator= (const Voxel& v) + { Expected::Voxel::operator=(v); image = v.image; return *this; } + + ~Voxel() {} + + void set_image(Buffer* image) + { this->image = image; } + + +// protected: + + double interpolate(const Coord& pos); + + double interpolate(const Coord& pos, Coord& gradient) + { throw Exception ("Not implemented yet."); } + + double interpolate(const Coord& triple, Coord& gradient, Coord::Tensor& hessian) + { throw Exception ("Not implemented yet."); } + + }; + + } + + } + + } + +} + + +#endif diff --git a/src/bts/image/expected/top_hat/buffer.cpp b/src/bts/image/expected/top_hat/buffer.cpp new file mode 100644 index 0000000..dd17334 --- /dev/null +++ b/src/bts/image/expected/top_hat/buffer.cpp @@ -0,0 +1,81 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + +#include "bts/image/expected/top_hat/buffer.h" +#include "bts/image/expected/top_hat/voxel.h" + +#include "bts/fibre/strand/tensor.h" +#include "bts/fibre/tractlet/tensor.h" + +#include "bts/image/inline_functions.h" +#include "bts/diffusion/inline_functions.h" + + +#define LOOP(op) \ +for (size_t z = 0; z < this->dim(Z); z++) { \ + for (size_t y = 0; y < this->dim(Y); y++) { \ + for (size_t x = 0; x < this->dim(X); x++) { \ + op \ + } \ + } \ +} + +namespace BTS { + + namespace Image { + + namespace Expected { + + namespace TopHat { + + + const std::string Buffer::SHORT_NAME = "top_hat"; + + + Buffer::Buffer( const Triple& dimensions, + const Triple& voxel_sizes, + const Diffusion::Model& diffusion_model, + size_t num_sections, + size_t num_strands, + double extent, + const Triple& corner_offset, + bool enforce_bounds) + : Buffer_tpl(dimensions, voxel_sizes, diffusion_model, num_sections, num_strands, extent, corner_offset, enforce_bounds) + { name_init(); } + + + Buffer::Buffer(const Buffer& buffer) + : Buffer_tpl(buffer) + { name_init(); } + + + std::ostream& operator<< (std::ostream& stream, const Buffer& buffer) + { return buffer.to_stream(stream); } + } + + } + + } + +} + +#undef LOOP diff --git a/src/bts/image/expected/top_hat/buffer.h b/src/bts/image/expected/top_hat/buffer.h new file mode 100644 index 0000000..079d0b1 --- /dev/null +++ b/src/bts/image/expected/top_hat/buffer.h @@ -0,0 +1,84 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + +#include "bts/image/expected/top_hat/voxel.h" + +#ifndef __bts_image_expected_tophat_buffer_h__ +#define __bts_image_expected_tophat_buffer_h__ + +#include "bts/image/expected/buffer.h" +#include "bts/image/expected/buffer_tpl.h" + + +namespace BTS { + + namespace Image { + + namespace Expected { + + namespace TopHat { + + class Buffer : public Expected::Buffer, public Expected::Buffer_tpl { + + //Public static constants + public: + + const static std::string SHORT_NAME; + + public: + + Buffer() : Buffer_tpl(this) {} + + Buffer( const Triple& dimensions, + const Triple& voxel_sizes, + const Diffusion::Model& diffusion_model, + size_t num_sections = NUM_LENGTH_SECTIONS_DEFAULT, + size_t num_strands = NUM_WIDTH_SECTIONS_DEFAULT, + double extent = INTERP_EXTENT_DEFAULT, + const Triple& corner_offset = Triple (), + bool enforce_bounds = true + ); + + + Buffer(const Buffer& buffer); + + + ~Buffer() {} + + + EXPECTED_BUFFER_FUNCTIONS; + + }; + + + std::ostream& operator<< (std::ostream& stream, const Buffer& buffer); + + } + + } + + } + +} + + +#endif diff --git a/src/bts/image/expected/top_hat/voxel.cpp b/src/bts/image/expected/top_hat/voxel.cpp new file mode 100644 index 0000000..623adc9 --- /dev/null +++ b/src/bts/image/expected/top_hat/voxel.cpp @@ -0,0 +1,62 @@ +/* + Copyright 2010 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close on May 19, 2010. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + +*/ + +#include "bts/image/expected/top_hat/voxel.h" +#include "bts/image/expected/top_hat/buffer.h" + +#include "bts/image/inline_functions.h" +#include "bts/diffusion/inline_functions.h" + +namespace BTS { + + namespace Image { + + namespace Expected { + + namespace TopHat { + + Voxel::Voxel(Buffer& buffer, const Index& index) + : Expected::Voxel(buffer, index, buffer.diffusion_model), image(&buffer) {} + + double Voxel::interpolate(const Coord& pos) { + + Coord disp = pos - centre(); + + double scalar; + + if (disp.upper_bounded(0.5) && disp.lower_bounded(-0.5)) + scalar = 1.0; + else + scalar = 0.0; + + return scalar; + + } + + } + + } + + } + +} + diff --git a/src/bts/image/expected/top_hat/voxel.h b/src/bts/image/expected/top_hat/voxel.h new file mode 100644 index 0000000..35d248c --- /dev/null +++ b/src/bts/image/expected/top_hat/voxel.h @@ -0,0 +1,98 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + + +#ifndef __bts_image_expected_tophat_voxel_h__ +#define __bts_image_expected_tophat_voxel_h__ + +#include "bts/common.h" + +#include "bts/triple.h" + +#include "bts/image/expected/buffer.h" +#include "bts/image/observed/buffer.h" +#include "bts/image/expected/voxel.h" +#include "bts/image/expected/direction.h" + +#include "bts/diffusion/model.h" + + + +namespace BTS { + + namespace Image { + + namespace Expected { + + namespace TopHat { + + class Voxel : public Expected::Voxel { + + public: + + //TODO: Use this typedef to try to move set_image out of derived voxel classes and into Expected::Voxel class. + typedef TopHat::Buffer Buffer; + + protected: + + Buffer* image; + + public: + + Voxel() {} + + Voxel(Buffer& buffer, const Index& index); + + Voxel(const Voxel& voxel) + : Expected::Voxel(voxel), image(voxel.image) {} + + Voxel& operator= (const Voxel& v) + { Expected::Voxel::operator=(v); image = v.image; return *this; } + + ~Voxel() {} + + void set_image(Buffer* image) + { this->image = image; } + + + // protected: + + double interpolate(const Coord& pos); + + double interpolate(const Coord& pos, Coord& gradient) + { throw Exception ("Gradient is not defined for Top-hat interpolation."); } + + double interpolate(const Coord& triple, Coord& gradient, Coord::Tensor& hessian) + { throw Exception ("Gradient is not defined for Top-hat interpolation."); } + + }; + + } + + } + + } + +} + + +#endif diff --git a/src/bts/image/expected/trilinear/buffer.cpp b/src/bts/image/expected/trilinear/buffer.cpp new file mode 100644 index 0000000..4d58a0a --- /dev/null +++ b/src/bts/image/expected/trilinear/buffer.cpp @@ -0,0 +1,83 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + +#include "bts/image/expected/trilinear/buffer.h" +#include "bts/image/expected/trilinear/voxel.h" + +#include "bts/fibre/strand/tensor.h" +#include "bts/fibre/tractlet/tensor.h" + +#include "bts/image/inline_functions.h" +#include "bts/diffusion/inline_functions.h" + + +#define LOOP(op) \ +for (size_t z = 0; z < this->dim(Z); z++) { \ + for (size_t y = 0; y < this->dim(Y); y++) { \ + for (size_t x = 0; x < this->dim(X); x++) { \ + op \ + } \ + } \ +} + +namespace BTS { + + namespace Image { + + namespace Expected { + + namespace Trilinear { + + const std::string Buffer::SHORT_NAME = "trilinear"; + + + + Buffer::Buffer( const Triple& dimensions, + const Triple& voxel_sizes, + const Diffusion::Model& diffusion_model, + size_t num_sections, + size_t num_strands, + double extent, + const Triple& corner_offset, + bool enforce_bounds) + : Buffer_tpl(dimensions, voxel_sizes, diffusion_model, num_sections, num_strands, extent, corner_offset, enforce_bounds) + { name_init(); } + + + Buffer::Buffer(const Buffer& buffer) + : Buffer_tpl(buffer) + { name_init(); } + + + std::ostream& operator<< (std::ostream& stream, const Buffer& buffer) + { return buffer.to_stream(stream); } + + } + + } + + + } + +} + +#undef LOOP diff --git a/src/bts/image/expected/trilinear/buffer.h b/src/bts/image/expected/trilinear/buffer.h new file mode 100644 index 0000000..b1a18b0 --- /dev/null +++ b/src/bts/image/expected/trilinear/buffer.h @@ -0,0 +1,85 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + +#include "bts/image/expected/trilinear/voxel.h" + +#ifndef __bts_image_expected_trilinear_buffer_h__ +#define __bts_image_expected_trilinear_buffer_h__ + +#include "bts/image/expected/buffer.h" +#include "bts/image/expected/buffer_tpl.h" + + +namespace BTS { + + namespace Image { + + namespace Expected { + + namespace Trilinear { + + class Buffer : public Expected::Buffer, public Expected::Buffer_tpl { + + //Public static constants + public: + + const static std::string SHORT_NAME; + + public: + + Buffer() : Buffer_tpl(this) {} + + Buffer( const Triple& dimensions, + const Triple& voxel_sizes, + const Diffusion::Model& diffusion_model, + size_t num_sections = NUM_LENGTH_SECTIONS_DEFAULT, + size_t num_strands = NUM_WIDTH_SECTIONS_DEFAULT, + double extent = INTERP_EXTENT_DEFAULT, + const Triple& corner_offset = Triple (), + bool enforce_bounds = true + ); + + + Buffer(const Buffer& buffer); + + + ~Buffer() {} + + + EXPECTED_BUFFER_FUNCTIONS; + + }; + + + + std::ostream& operator<< (std::ostream& stream, const Buffer& buffer); + + } + + } + + } + +} + + +#endif diff --git a/src/bts/image/expected/trilinear/voxel.cpp b/src/bts/image/expected/trilinear/voxel.cpp new file mode 100644 index 0000000..30bed11 --- /dev/null +++ b/src/bts/image/expected/trilinear/voxel.cpp @@ -0,0 +1,105 @@ +/* + Copyright 2010 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close on May 19, 2010. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + +*/ + +#include "bts/image/expected/trilinear/voxel.h" +#include "bts/image/expected/trilinear/buffer.h" + +#include "bts/image/inline_functions.h" +#include "bts/diffusion/inline_functions.h" + +namespace BTS { + + namespace Image { + + namespace Expected { + + namespace Trilinear { + + Voxel::Voxel(Buffer& buffer, const Index& coord) + : Expected::Voxel(buffer, coord, buffer.diffusion_model), image(&buffer) {} + + + double Expected::Trilinear::Voxel::interpolate(const Coord& pos) { + + Coord disp = pos - centre(); + Coord interpolate = Coord::Ones - disp.abs(); + + double scalar; + + if (interpolate.non_negative()) { + + scalar = interpolate[X] * interpolate[Y] * interpolate[Z]; + + } else { + + scalar = 0.0; + } + + return scalar; + + } + + + double Expected::Trilinear::Voxel::interpolate(const Coord& pos, Coord& pos_gradient) { + + Coord disp = pos - centre(); + + Coord interpolate = Coord::Ones - disp.abs(); + +#ifndef GRADIENT_NOT_REQUIRED + Coord disp_sign = disp.sign(); +#endif + + double scalar; + + if (interpolate.non_negative()) { + + scalar = interpolate[X] * interpolate[Y] * interpolate[Z]; + +#ifndef GRADIENT_NOT_REQUIRED + pos_gradient[X] = - disp_sign[X] * interpolate[Y] * interpolate[Z]; + pos_gradient[Y] = - disp_sign[Y] * interpolate[X] * interpolate[Z]; + pos_gradient[Z] = - disp_sign[Z] * interpolate[X] * interpolate[Y]; +#endif + + } else { + + scalar = 0.0; + +#ifndef GRADIENT_NOT_REQUIRED + pos_gradient.zero(); +#endif + + } + + return scalar; + + } + + } + + } + + } + +} + diff --git a/src/bts/image/expected/trilinear/voxel.h b/src/bts/image/expected/trilinear/voxel.h new file mode 100644 index 0000000..d42104f --- /dev/null +++ b/src/bts/image/expected/trilinear/voxel.h @@ -0,0 +1,94 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + + +#ifndef __bts_image_expected_trilinear_voxel_h__ +#define __bts_image_expected_trilinear_voxel_h__ + +#include "bts/common.h" + +#include "bts/triple.h" + +#include "bts/image/expected/buffer.h" +#include "bts/image/observed/buffer.h" +#include "bts/image/expected/voxel.h" +#include "bts/image/expected/direction.h" + +#include "bts/diffusion/model.h" + + + +namespace BTS { + + namespace Image { + + namespace Expected { + + namespace Trilinear { + + class Voxel : public Expected::Voxel { + + public: + + typedef Trilinear::Buffer Buffer; + + protected: + + Buffer* image; + + public: + + Voxel() {} + + Voxel(Buffer& buffer, const Index& coord); + + Voxel(const Voxel& voxel) + : Expected::Voxel(voxel), image(voxel.image) {} + + Voxel& operator= (const Voxel& v) + { Expected::Voxel::operator=(v); image = v.image; return *this; } + + ~Voxel() {} + + + // protected: + + double interpolate(const Coord& pos); + + double interpolate(const Coord& pos, Coord& gradient); + + double interpolate(const Coord& triple, Coord& gradient, Coord::Tensor& hessian) + { throw Exception ("Gradient is not defined for Top-hat interpolation."); } + + + }; + + } + + } + + } + +} + + +#endif diff --git a/src/bts/image/expected/voxel.cpp b/src/bts/image/expected/voxel.cpp new file mode 100644 index 0000000..9c5be7b --- /dev/null +++ b/src/bts/image/expected/voxel.cpp @@ -0,0 +1,161 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + +#include "bts/image/expected/voxel.h" +#include "bts/fibre/strand/basic_section/tensor.h" +#include "bts/fibre/tractlet/section/tensor.h" +#include "bts/coord/tensor.h" + +#include "bts/image/inline_functions.h" + +namespace BTS { + + namespace Image { + + namespace Expected { + + Voxel::Voxel(Expected::Buffer& exp_image, const Index& coord, Diffusion::Model& diffusion_model) + : Observed::Voxel(diffusion_model.num_encodings(), coord), precalc_interpolation(NAN) { + + for (size_t encode_i = 0; encode_i < this->num_encodings(); encode_i++) + directions.push_back(Direction(*this, diffusion_model[encode_i])); + + } + + + Voxel::Voxel(const Voxel& v) + : Observed::Voxel(v), precalc_interpolation(v.precalc_interpolation), precalc_gradient(v.precalc_gradient) { + + for (size_t encode_i = 0; encode_i < v.directions.size(); encode_i++) + directions.push_back(Direction(*this, *v.directions[encode_i].response)); + + } + + + + Voxel& Voxel::operator= (const Voxel& v) { + + Observed::Voxel::operator=(v); + precalc_interpolation = v.precalc_interpolation; + precalc_gradient = v.precalc_gradient; + + for (size_t encode_i = 0; encode_i < v.directions.size(); encode_i++) + directions.push_back(Direction(*this, *v.directions[encode_i].response)); + + return *this; + + } + + + const Diffusion::Encoding& Voxel::encoding(size_t encode_index) const { + + return directions[encode_index].encoding(); + + } + + + double Voxel::interpolate(const Fibre::Strand::BasicSection& section) { + + double pos_interp = interpolate(section.position()); + + double tan_norm = section.tangent().norm(); + + return pos_interp * tan_norm; + + } + + + double Voxel::interpolate(const Fibre::Strand::BasicSection& section, Fibre::Strand::BasicSection& gradient) { + + Coord pos_interp_gradient; + Coord tan_norm_gradient; + + double pos_interp = interpolate(section.position(), pos_interp_gradient); + double tan_norm = section.tangent().norm(tan_norm_gradient); + + gradient.zero(); + + gradient.position() = tan_norm * pos_interp_gradient; + gradient.tangent() = pos_interp * tan_norm_gradient; + + return pos_interp * tan_norm; + + } + + + double Voxel::interpolate(const Fibre::Strand::BasicSection& section, Fibre::Strand::BasicSection& gradient, Fibre::Strand::BasicSection::Tensor& hessian) { + + + Coord pos_interp_gradient; + Coord tan_norm_gradient; + Coord::Tensor interp_hessian; + Coord::Tensor norm_hessian; + + double pos_interp = interpolate(section.position(), pos_interp_gradient, interp_hessian); + double tan_norm = section.tangent().norm(tan_norm_gradient, norm_hessian); + + gradient.zero(); + + gradient.position() = tan_norm * pos_interp_gradient; + gradient.tangent() = pos_interp * tan_norm_gradient; + + + hessian.zero(); + + hessian.position(X).position() = tan_norm * interp_hessian[X]; + hessian.position(Y).position() = tan_norm * interp_hessian[Y]; + hessian.position(Z).position() = tan_norm * interp_hessian[Z]; + + hessian.position(X).tangent() = pos_interp_gradient[X] * tan_norm_gradient; + hessian.position(Y).tangent() = pos_interp_gradient[Y] * tan_norm_gradient; + hessian.position(Z).tangent() = pos_interp_gradient[Z] * tan_norm_gradient; + + hessian.tangent(X).tangent() = pos_interp * norm_hessian[X]; + hessian.tangent(Y).tangent() = pos_interp * norm_hessian[Y]; + hessian.tangent(Z).tangent() = pos_interp * norm_hessian[Z]; + + hessian.tangent(X).position() = pos_interp_gradient * tan_norm_gradient[X]; + hessian.tangent(Y).position() = pos_interp_gradient * tan_norm_gradient[Y]; + hessian.tangent(Z).position() = pos_interp_gradient * tan_norm_gradient[Z]; + + return pos_interp * tan_norm; + + } + + + double Voxel::interpolate(const Fibre::Tractlet::Section& section, Fibre::Strand::BasicSection& gradient, Fibre::Tractlet::Section::Tensor& hessian) { + + Fibre::Strand::BasicSection::Tensor strand_hessian; + + double interp = interpolate((const Fibre::Strand::BasicSection&)section, (Fibre::Strand::BasicSection&)gradient, strand_hessian); + + hessian = strand_hessian; + + return interp; + + } + + } + + } + +} diff --git a/src/bts/image/expected/voxel.h b/src/bts/image/expected/voxel.h new file mode 100644 index 0000000..e466e2f --- /dev/null +++ b/src/bts/image/expected/voxel.h @@ -0,0 +1,181 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + +#include "bts/image/expected/direction.h" + +#ifndef __bts_image_expected_voxel_h__ +#define __bts_image_expected_voxel_h__ + + +namespace BTS { + + namespace Image { + + namespace Expected { + + class Voxel; + + } + + } + +} + + +#include "bts/common.h" + +#include "bts/triple.h" +#include "bts/coord.h" + +#include "bts/image/expected/buffer.h" +#include "bts/image/observed/buffer.h" +#include "bts/image/observed/voxel.h" + +#include "bts/image/expected/direction.h" + +#include "bts/fibre/tractlet/section.h" +#include "bts/fibre/strand/basic_section/tensor.h" +#include "bts/fibre/strand/section.h" + +#include "bts/diffusion/model.h" +#include "bts/image/expected/buffer.h" + + +namespace BTS { + + namespace Image { + + namespace Expected { + + class Voxel : public Observed::Voxel { + + protected: + + std::vector directions; + + double precalc_interpolation; + Fibre::Tractlet::Section precalc_gradient; + Fibre::Tractlet::Section::Tensor precalc_hessian; + + public: + + Voxel() {} + + + Voxel(Expected::Buffer& exp_image, const Index& index, Diffusion::Model& diffusion_model); + + + Voxel(const Voxel& v); + + + Voxel& operator= (const Voxel& v); + + + virtual ~Voxel() {} + + + const Diffusion::Encoding& encoding(size_t encode_index) const; + + + Voxel& zero() + { Image::Voxel::zero(); precalc_interpolation = NAN; precalc_gradient.invalidate(), precalc_hessian.invalidate(); return *this; } + + + Voxel& negate() + { Image::Voxel::negate(); precalc_interpolation = NAN; precalc_gradient.invalidate(), precalc_hessian.invalidate(); return *this; } + + + double precalculated_interpolation() const + { return precalc_interpolation; } + + + const Fibre::Tractlet::Section& precalculated_gradient() const + { return precalc_gradient; } + + + const Fibre::Tractlet::Section::Tensor& precalculated_hessian() const + { return precalc_hessian; } + + + void precalculate_interpolation (Fibre::Strand::Section& section) + { section.precalc_interpolation = interpolate(section); } + + + void precalculate_interpolation_gradient (Fibre::Strand::Section& section) + { section.precalc_interpolation = interpolate(section, section.precalc_interp_gradient); } + + + void precalculate_interpolation_gradient_and_hessian (Fibre::Strand::Section& section) + { section.precalc_interpolation = interpolate(section, section.precalc_interp_gradient, section.precalc_interp_hessian); } + + + virtual double interpolate(const Fibre::Strand::BasicSection& section); + + + virtual double interpolate(const Fibre::Strand::BasicSection& section, Fibre::Strand::BasicSection& gradient); + + + virtual double interpolate(const Fibre::Strand::BasicSection& section, Fibre::Strand::BasicSection& gradient, Fibre::Strand::BasicSection::Tensor& hessian); + + //Default to the standard Strand::Section interpolation. + virtual double interpolate(const Fibre::Tractlet::Section& section, Fibre::Strand::BasicSection& gradient) + { return interpolate((const Fibre::Strand::BasicSection&)section, (Fibre::Strand::BasicSection&)gradient); } + + + //Default to the standard Strand::Section interpolation. + virtual double interpolate(const Fibre::Tractlet::Section& section, Fibre::Strand::BasicSection& gradient, Fibre::Tractlet::Section::Tensor& hessian); + + + Direction& direction(size_t index) + { return directions[index]; } + + + Voxel operator-() const + { Voxel answer(*this); for (size_t encode_i = 0; encode_i < num_encodings(); encode_i++) answer[encode_i] = -operator[](encode_i); return answer; } + + + // protected: + + virtual double interpolate(const Coord& triple) + { throw Exception ("If interpolate(const Fibre::Strand::BasicSection&,) is not overidden in derived class then interpolate(const Coord&) must be provided."); } + + virtual double interpolate(const Coord& triple, Coord& gradient) + { throw Exception ("If interpolate(const Fibre::Strand::BasicSection&, Fibre::Strand::BasicSection&) is not overidden in derived class then interpolate(const Coord&, Coord&) must be provided."); } + + + virtual double interpolate(const Coord& triple, Coord& gradient, Coord::Tensor& hessian) + { throw Exception ("If interpolate(const Fibre::Strand::BasicSection&, Fibre::Strand::BasicSection&, Fibre::Strand::BasicSection::Tensor&) is not overidden in derived class then interpolate(const Coord&, Coord&, Coord::Tensor&) must be provided."); } + + + + + + }; + + } + + } + +} + + +#endif diff --git a/src/bts/image/index.cpp b/src/bts/image/index.cpp new file mode 100644 index 0000000..79ca177 --- /dev/null +++ b/src/bts/image/index.cpp @@ -0,0 +1,83 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, 14/07/2010. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + +#include "bts/image/index.h" + +namespace BTS { + + namespace Image { + + std::ostream& operator<< (std::ostream& stream, const Index& coord) { + + stream << "[" << coord[X] << ", " << coord[Y] << ", " << coord[Z] << "]"; + + return stream; + + } + + + void Index::bound(int image_dims) { + + this->p[X] = min2(max2(this->p[X],0),image_dims); + this->p[Y] = min2(max2(this->p[Y],0),image_dims); + this->p[Z] = min2(max2(this->p[Z],0),image_dims); + + } + + + bool Index::operator< (const Index& A) const { + + bool is_less_than; + if (p[X] < A[X]) + is_less_than = true; + else if (p[X] == A[X]) { + if (p[Y] < A[Y]) + is_less_than = true; + else if (p[Y] == A[Y]) + is_less_than = (p[Z] < A[Z]); + else + is_less_than = false; + } else + is_less_than = false; + return is_less_than; + } + + bool Index::operator> (const Index& A) const { + + bool is_greater_than; + if (p[X] > A[X]) + is_greater_than = true; + else if (p[X] == A[X]) { + if (p[Y] > A[Y]) + is_greater_than = true; + else if (p[Y] == A[Y]) + is_greater_than = (p[Z] > A[Z]); + else + is_greater_than = false; + } else + is_greater_than = false; + return is_greater_than; + } + + + } +} diff --git a/src/bts/image/index.h b/src/bts/image/index.h new file mode 100644 index 0000000..a9163ab --- /dev/null +++ b/src/bts/image/index.h @@ -0,0 +1,139 @@ +/* + Copyright 2010 Brain Research Institute/National ICT Australia (NICTA), Melbourne, Australia + + Written by Thomas G Close, 5/05/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + +*/ + +#ifndef __bts_image_index_h__ +#define __bts_image_index_h__ + +namespace BTS { + + namespace Image { + + class Index; + + } + +} + +#include "bts/common.h" + +#include "bts/triple.h" + + + +namespace BTS { + + namespace Image { + + class Index : public Triple { + + public: + + Index () {} + + Index (int x_value, int y_value, int z_value) + : Triple(x_value, y_value, z_value) {} + + Index(const Index& c) + : Triple(c) {} + + Index(const Triple& t) + : Triple(t) {} + + Index(const Triple& t) + : Triple(t[X], t[Y], t[Z]) {} + + inline bool positive() + { return (this->p[X] > 0.0) && (this->p[Y] > 0.0) && (this->p[Z] > 0.0); } + + inline bool non_negative() + { return (this->p[X] >= 0.0) && (this->p[Y] >= 0.0) && (this->p[Z] >= 0.0); } + + inline bool bounded_by(const Triple& A) const + { return (this->p[X] < A[X]) && (this->p[Y] < A[Y]) && (this->p[Z] < A[Z]); } + + inline bool bounded_by(const Triple& A) const + { return (this->p[X] < (int)A[X]) && (this->p[Y] < (int)A[Y]) && (this->p[Z] < (int)A[Z]); } + + void bound(int image_dims); + template void bound(const Triple &image_dims); + + void bound(int low_bound, int up_bound); + template void bound(const Triple &low_bound, const Triple &up_bound); + + /*! Comparison between coordinates is implemented so that they can be sorted in std::maps and works by + * placing the most significance on X, then Y, and the Z channels. + */ + bool operator< (const Index& A) const; + + bool operator> (const Index& A) const; + + bool operator<= (const Index& A) const + { return this->operator<(A) ? true : this->operator == (A); } + + bool operator>= (const Index& A) const + { return this->operator>(A) ? true : this->operator == (A); } + + + Triple to_point() + { return Triple((double)this->p[X] , (double)this->p[Y], (double)this->p[Z]); } + + }; + + + std::ostream& operator<< (std::ostream& stream, const Index& coord); + + template void Index::bound(const Triple &image_dims) { + + this->p[X] = min2(max2(this->p[X],0),image_dims[X]); + this->p[Y] = min2(max2(this->p[Y],0),image_dims[Y]); + this->p[Z] = min2(max2(this->p[Z],0),image_dims[Z]); + + } + + inline void Index::bound(int low_bound, int up_bound) { + this->p[X] = min2(max2(this->p[X],low_bound),up_bound); + this->p[Y] = min2(max2(this->p[Y],low_bound),up_bound); + this->p[Z] = min2(max2(this->p[Z],low_bound),up_bound); + } + + template void Index::bound(const Triple &low_bound, const Triple &up_bound) { + this->p[X] = min2(max2(this->p[X],low_bound[X]),up_bound[X]); + this->p[Y] = min2(max2(this->p[Y],low_bound[Y]),up_bound[Y]); + this->p[Z] = min2(max2(this->p[Z],low_bound[Z]),up_bound[Z]); + } + + } + +} + + + + + + + + +//#undef COPY_VALUES + +#endif + + diff --git a/src/bts/image/inline_functions.h b/src/bts/image/inline_functions.h new file mode 100644 index 0000000..3eb9726 --- /dev/null +++ b/src/bts/image/inline_functions.h @@ -0,0 +1,53 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, 16/07/2010. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + +#ifndef __bts_image_inline_functions_h__ +#define __bts_image_inline_functions_h__ + + +#ifdef __bts_image_buffer_h__ + +#include "bts/image/buffer.cpp.h" + +#endif + +#ifdef __bts_image_observed_buffer_h__ + +#include "bts/image/observed/buffer.cpp.h" + +#endif + +#ifdef __bts_image_expected_buffertpl_h__ + +#include "bts/image/expected/buffer_tpl.cpp.h" + +#endif + + +#ifdef __bts_image_expected_direction_h__ + +#include "bts/image/expected/direction.cpp.h" + +#endif + + +#endif /* __bts_image_inline_functions_h__ */ diff --git a/src/bts/image/noise.cpp b/src/bts/image/noise.cpp new file mode 100644 index 0000000..9dd2ed0 --- /dev/null +++ b/src/bts/image/noise.cpp @@ -0,0 +1,63 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, 14/07/2010. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + + +#include "bts/image/noise.h" + +#include "bts/image/noise/gaussian.h" +#include "bts/image/noise/rician.h" +#include "bts/image/buffer.cpp.h" + +namespace BTS { + + namespace Image { + + const char* Noise::TYPE_DEFAULT = "gaussian"; + const double Noise::SNR_DEFAULT = 15; + + + Noise* Noise::factory(gsl_rng* rand_gen, + const std::string& type, + double snr, + double ref_signal) { + + + if (type == "gaussian") + + return new Noise::Gaussian(rand_gen, snr, ref_signal); + + else if (type == "rician") + + return new Noise::Rician(rand_gen, snr, ref_signal); + + else + + throw Exception ("Unrecognised noise type '" + type + "'."); + + } + + + } + + + +} diff --git a/src/bts/image/noise.h b/src/bts/image/noise.h new file mode 100644 index 0000000..c73cb45 --- /dev/null +++ b/src/bts/image/noise.h @@ -0,0 +1,141 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, 14/07/2010. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + +#ifndef __bts_image_noise_h__ +#define __bts_image_noise_h__ + +#define NOISE_PARAMETERS \ + Option ("noise_type", "Type of noise distribution") \ + + Argument ("noise_type", "").type_text (Image::Noise::TYPE_DEFAULT), \ +\ + Option ("noise_snr", "The signal-to-noise ratio of the noise.") \ + + Argument ("noise_snr", "").type_float (SMALL_FLOAT, Image::Noise::SNR_DEFAULT, LARGE_FLOAT), \ +\ + Option ("noise_ref_signal", "The reference intensity that the noise variance for a given SNR will be calculated from.") \ + + Argument ("noise_ref_signal", "").type_float (SMALL_FLOAT, NAN, LARGE_FLOAT) \ +\ + + +//Loads the parameters into variables +#define SET_NOISE_PARAMETERS \ +\ + std::string noise_type = Image::Noise::TYPE_DEFAULT; \ + double noise_snr = Image::Noise::SNR_DEFAULT; \ + double noise_ref_signal = NAN; \ +\ + opt = get_options("noise_type"); \ + if (opt.size()) \ + noise_type = opt[0][0].c_str(); \ +\ + opt = get_options("noise_snr"); \ + if (opt.size()) \ + noise_snr = opt[0][0]; \ +\ + opt = get_options("noise_ref_signal"); \ + if (opt.size()) \ + noise_ref_signal = opt[0][0]; \ + + +//Adds the parameters to the properties to be saved with the data. +#define ADD_NOISE_PROPERTIES(properties) \ + properties["noise_type"] = noise_type; \ + properties["noise_snr"] = str(noise_snr); \ + if (!isnan(noise_ref_signal)) \ + properties["noise_ref_signal"] = str(noise_ref_signal); + + + +extern "C" { +#include +#include +} + +#include "bts/image/observed/buffer.h" +#include "bts/image/expected/buffer.h" + +namespace BTS { + + namespace Image { + + class Noise { + + //Public nested classes and typedefs + public: + + class Gaussian; + class Rician; + + //Public static constants + public: + + const static char* TYPE_DEFAULT; + const static double SNR_DEFAULT; + + //Protected member variables + protected: + + gsl_rng* rand_gen; + double snr; + double ref_signal; + + //Public static member functions + public: + + static Noise* factory(gsl_rng* rand_gen, + const std::string& type, + double snr, + double ref_signal); + + + //Public member functions + public: + + Noise(gsl_rng* rand_gen, double snr, double ref_signal) + : rand_gen(rand_gen), snr(snr), ref_signal(ref_signal) {} + + + virtual Image::Observed::Buffer& noisify(Image::Observed::Buffer& image) = 0; + + virtual Image::Expected::Buffer& noisify(Image::Expected::Buffer& image) = 0; + + protected: + + template double noise_magnitude(T& image) const { + + double signal; + + if (!isnan(ref_signal)) + signal = ref_signal; + else + signal = image.max_b0(); + + return signal / snr; + + } + + }; + + } + +} + +#endif /* __bts_image_noise_h__ */ diff --git a/src/bts/image/noise/gaussian.cpp b/src/bts/image/noise/gaussian.cpp new file mode 100644 index 0000000..66a0d3c --- /dev/null +++ b/src/bts/image/noise/gaussian.cpp @@ -0,0 +1,57 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, 14/07/2010. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + +#include "math/math.h" + +#include "bts/image/noise/gaussian.h" +#include "bts/image/observed/voxel.h" + +#include "bts/image/inline_functions.h" + + +namespace BTS { + + namespace Image { + + + Noise::Gaussian::Gaussian (gsl_rng* rand_gen, double snr, double ref_signal) + : Noise(rand_gen, snr, ref_signal) {} + + + template void Noise::Gaussian::noisify_tpl(T& image) { + + double noise_mag = noise_magnitude(image); + + for (size_t x = 0; x < image.dim(X); x++) + for (size_t y = 0; y < image.dim(Y); y++) + for (size_t z = 0; z < image.dim(Z); z++) + for (size_t orient_i = 0; orient_i < image.num_encodings(); orient_i++) + + image(x,y,z)[orient_i] += gsl_ran_gaussian(rand_gen, noise_mag); + + + } + + + } + +} diff --git a/src/bts/image/noise/gaussian.h b/src/bts/image/noise/gaussian.h new file mode 100644 index 0000000..9dadc37 --- /dev/null +++ b/src/bts/image/noise/gaussian.h @@ -0,0 +1,65 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, 14/07/2010. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + +#ifndef __bts_image_noise_gaussian_h__ +#define __bts_image_noise_gaussian_h__ + +#include "bts/image/noise.h" +#include "bts/image/observed/buffer.h" +#include "bts/image/expected/buffer.h" + +namespace BTS { + + namespace Image { + + class Noise::Gaussian : public Noise { + + //Public static constants. + public: + + //Protected member variables + protected: + + //Public member functions + public: + + Gaussian(gsl_rng* rand_gen, double snr, double ref_signal); + + + Image::Observed::Buffer& noisify(Image::Observed::Buffer& image) + { noisify_tpl(image); return image; } + + Image::Expected::Buffer& noisify(Image::Expected::Buffer& image) + { noisify_tpl(image); return image; } + + protected: + + template void noisify_tpl(T& image); + + + }; + + } + +} + +#endif /* __bts_image_noise_gaussian_h__ */ diff --git a/src/bts/image/noise/rician.cpp b/src/bts/image/noise/rician.cpp new file mode 100644 index 0000000..535dbb8 --- /dev/null +++ b/src/bts/image/noise/rician.cpp @@ -0,0 +1,65 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, 14/07/2010. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + +#include "math/math.h" + +#include "bts/image/noise/rician.h" +#include "bts/image/observed/voxel.h" + +#include "bts/image/inline_functions.h" + + +namespace BTS { + + namespace Image { + + + Noise::Rician::Rician (gsl_rng* rand_gen, double snr, double ref_signal) + : Noise(rand_gen, snr, ref_signal) {} + + + template void Noise::Rician::noisify_tpl(T& image) { + + double noise_mag = noise_magnitude(image); + + for (size_t x = 0; x < image.dim(X); x++) + for (size_t y = 0; y < image.dim(Y); y++) + for (size_t z = 0; z < image.dim(Z); z++) { + + for (size_t orient_i = 0; orient_i < image.num_encodings(); orient_i++) { + + double noise1 = gsl_ran_gaussian(rand_gen, noise_mag); + double noise2 = gsl_ran_gaussian(rand_gen, noise_mag); + + image(x,y,z)[orient_i] = MR::Math::sqrt(MR::Math::pow2(image(x,y,z)[orient_i] + noise1) + MR::Math::pow2(noise2)); + + } + + } + + + } + + + } + +} diff --git a/src/bts/image/noise/rician.h b/src/bts/image/noise/rician.h new file mode 100644 index 0000000..3ec969b --- /dev/null +++ b/src/bts/image/noise/rician.h @@ -0,0 +1,65 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, 14/07/2010. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + +#ifndef __bts_image_noise_rician_h__ +#define __bts_image_noise_rician_h__ + +#include "bts/image/noise.h" +#include "bts/image/observed/buffer.h" +#include "bts/image/expected/buffer.h" + +namespace BTS { + + namespace Image { + + class Noise::Rician : public Noise { + + //Public static constants. + public: + + //Protected member variables + protected: + + //Public member functions + public: + + Rician(gsl_rng* rand_gen, double snr, double ref_signal); + + Image::Observed::Buffer& noisify(Image::Observed::Buffer& image) + { noisify_tpl(image); return image; } + + Image::Expected::Buffer& noisify(Image::Expected::Buffer& image) + { noisify_tpl(image); return image; } + + protected: + + template void noisify_tpl(T& image); + + + }; + + } + +} + + +#endif /* __bts_image_noise_rician_h__ */ diff --git a/src/bts/image/observed/buffer.cpp b/src/bts/image/observed/buffer.cpp new file mode 100644 index 0000000..a828f9f --- /dev/null +++ b/src/bts/image/observed/buffer.cpp @@ -0,0 +1,158 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + +#include "image/header.h" +#include "dataset/loop.h" + + +#include "bts/image/observed/buffer.h" + +#include "bts/image/inline_functions.h" + + +namespace BTS { + + namespace Image { + + namespace Observed { + + + std::ostream& operator<< (std::ostream& stream, const Buffer& buffer) + { return buffer.to_stream(stream); } + + + + void Buffer::load(const std::string& location, const Diffusion::Encoding::Set& default_encodings) { + + MR::Image::Header header(location); + + if (header.ndim() != 4) + throw Exception ("dwi image should contain 4 dimensions, found " + str(header.ndim()) + "."); + + Diffusion::Encoding::Set encodings; + if (header.get_DW_scheme().rows()) { + MR::Math::Matrix encodings_matrix; + encodings.set(header.get_DW_scheme()); + } else if (default_encodings.size()) + encodings = default_encodings; + else + throw Exception ("No encodings found in loaded image, and no defaults supplied."); + + if (header.dim(3) != (int) encodings.size()) + throw Exception ("Number of encoding directions in loaded image (" + str(header.dim(DW)) + ") do not match that in encoding file (" + str(encodings.size()) + ")."); + + //Get image dimensions and voxel lengths. + Triple dimensions (header.dim(X), header.dim(Y), header.dim(Z)); + Triple voxel_lengths (header.vox(X), header.vox(Y), header.vox(Z)); + + //Get offset from transform. + MR::Math::Matrix transform = header.transform(); + Triple mrtrix_offset (transform(0,3), transform(1,3), transform(2,3)); + Triple bts_offset = mrtrix_offset - voxel_lengths * 0.5; + + //Resize buffer to fit image. + reset(dimensions, voxel_lengths, bts_offset, encodings); + + //Copy data from image to buffer. + MR::Image::Voxel voxel (header); + MR::DataSet::Loop loop (0, 4); + + for (loop.start(voxel); loop.ok(); loop.next(voxel)) + operator()(voxel[X], voxel[Y], voxel[Z])[voxel[DW]] = voxel.value(); + + properties().insert(header.begin(), header.end()); + + + } + + Double::Buffer Buffer::isotropic(bool include_b0s) const { + + Double::Buffer mean_buffer (this->dims()); + + for (const_iterator vox_it = this->begin(); vox_it != this->end(); ++vox_it) { + mean_buffer(vox_it->first) = vox_it->second.isotropic(); + } + + return mean_buffer; + + } + + + void Buffer::remove_isotropic() { + + for (iterator vox_it = this->begin(); vox_it != this->end(); ++vox_it) { \ + vox_it->second.remove_isotropic(); + } + + } + + + + double Buffer::mean_square(bool include_b0s) const { + + double sum = 0.0; + + for (const_iterator vox_it = this->begin(); vox_it != this->end(); ++vox_it) { + sum += vox_it->second.mean_square_signal(include_b0s); + } + + return sum / this->num_voxels_in_bounds(); + + } + + + + + Double::Buffer Buffer::b0 () const { + + Double::Buffer b0_buffer (this->dims()); + + for (const_iterator vox_it = this->begin(); vox_it != this->end(); ++vox_it) { + b0_buffer(vox_it->first) = vox_it->second.b0(); + } + + return b0_buffer; + + } + + + double Buffer::average_b0() const { + + double b0_sum = 0; + + for (const_iterator vox_it = this->begin(); vox_it != this->end(); ++vox_it) { + b0_sum += vox_it->second.b0(); + } + + return b0_sum / this->num_voxels_in_bounds(); + + } + + + } + + } + +} + +#undef LOOP +#undef CONST_LOOP diff --git a/src/bts/image/observed/buffer.cpp.h b/src/bts/image/observed/buffer.cpp.h new file mode 100644 index 0000000..24825fe --- /dev/null +++ b/src/bts/image/observed/buffer.cpp.h @@ -0,0 +1,223 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, 16/07/2010. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + +#ifndef __bts_observed_buffer_cpp_h__ +#define __bts_observed_buffer_cpp_h__ + +#include "dataset/loop.h" + +namespace BTS { + + namespace Image { + + namespace Observed { + + template Buffer_tpl::Buffer_tpl(Triple dimensions, + Triple voxel_lengths, + Triple corner_offsets, + bool enforce_bounds) + + : Image::Buffer_tpl(dimensions, enforce_bounds), + voxel_lengths(voxel_lengths), + corner_offsets(corner_offsets) { + + if (!corner_offsets) + this->corner_offsets = default_corner_offset(dimensions, voxel_lengths); + + } + + + template void Buffer_tpl::reset(const Triple& dimensions, + const Triple& voxel_lengths, + const Triple& corner_offsets) { + + + + this->Image::Buffer_tpl::reset(dimensions); + this->voxel_lengths = voxel_lengths; + this->corner_offsets = corner_offsets; + + if (!this->corner_offsets) + this->corner_offsets = default_corner_offset(dimensions, voxel_lengths); + + + } + + + + + template std::ostream& Buffer_tpl::to_stream (std::ostream& stream) const { + + stream << "Dims: " << this->dims() << std::endl; + + stream << "Vox lengths: " << voxel_lengths << std::endl; + + stream << "Corner offsets: " << corner_offsets << std::endl; + + + for (size_t z = 0; z < this->dim(Z); z++) { + + stream << std::endl << std::endl << "----------" << std::endl + << " z=" << z << std::endl + << "----------" << std::endl; + + for (size_t y = 0; y < this->dim(Y); y++) { + + stream << std::endl << "y=" << y << std::endl << "----" << std::endl; + + for (size_t x = 0; x < this->dim(X); x++) { + + stream << "x=" << x << ": " << this->operator()(x,y,z) << std::endl; + } + } + } + + + return stream; + + } + + + template std::ostream& operator<< (std::ostream& stream, const Buffer_tpl& buffer) { + + return buffer.to_stream(stream); + + } + + + template void Buffer_tpl::save(const std::string& location) const { + + MR::Image::Header header; + + header.set_ndim(4); + + header.set_vox(X, this->vox_length(X)); + header.set_vox(Y, this->vox_length(Y)); + header.set_vox(Z, this->vox_length(Z)); + + header.set_dim(X, this->dim(X)); + header.set_dim(Y, this->dim(Y)); + header.set_dim(Z, this->dim(Z)); + header.set_dim(DW, num_encodings()); + + MR::Math::Matrix transform(4,4); + + transform.identity(); + + transform(0,3) = offset(X) + 0.5 * vox_length(X); + transform(1,3) = offset(Y) + 0.5 * vox_length(Y); + transform(2,3) = offset(Z) + 0.5 * vox_length(Z); + + header.set_transform(transform); + + MR::Math::Matrix encodings_matrix (num_encodings(), 4); + + for (size_t encode_i = 0; encode_i < num_encodings(); encode_i++) { + const Diffusion::Encoding& encode = this->encoding(encode_i); + encodings_matrix(encode_i,X) = encode[X]; + encodings_matrix(encode_i,Y) = encode[Y]; + encodings_matrix(encode_i,Z) = encode[Z]; + encodings_matrix(encode_i,DW) = encode.b_value(); + } + + header.set_DW_scheme(encodings_matrix); + + header.insert(properties().begin(), properties().end()); + + File::clear_path(location); + + header.create(location); + + //Copy data from buffer to image. + MR::Image::Voxel datapoint (header); + + std::vector loop_order(4); + + loop_order[0] = DW; + loop_order[1] = X; + loop_order[2] = Y; + loop_order[3] = Z; + + MR::DataSet::LoopInOrder loop (loop_order); + + loop.start(datapoint); + + for (size_t z = 0; z < this->dim(Z); z++) + for (size_t y = 0; y < this->dim(Y); y++) + for (size_t x = 0; x < this->dim(X); x++) { + + Image::Voxel vox; + + if (!this->is_empty(x,y,z)) + vox = this->operator()(x,y,z); + else + vox = Image::Voxel (num_encodings()); + + for (size_t encode_i = 0; encode_i < num_encodings(); encode_i++) { + datapoint.value() = vox[encode_i]; + loop.next(datapoint); + } + + } + + } + + + + + template double Buffer_tpl::rms(bool include_b0s) const { + + double sum = 0.0; + + for (typename Image::Buffer_tpl::const_iterator vox_it = this->begin(); vox_it != this->end(); ++vox_it) { + + if (!include_b0s || vox_it->second.b0()) + sum += vox_it->second.rms(); + + } + + return sum / this->num_voxels_in_bounds(); + + } + + + template double Buffer_tpl::max_b0() const { + + double max_b0 = 0; + + for (typename Image::Buffer_tpl::const_iterator vox_it = this->begin(); vox_it != this->end(); ++vox_it) + + if (vox_it->second.b0() > max_b0) + max_b0 = vox_it->second.b0(); + + return max_b0; + + } + + + } + + } + +} + +#endif /* __observed_buffer_tpl_cpp_h__ */ diff --git a/src/bts/image/observed/buffer.h b/src/bts/image/observed/buffer.h new file mode 100644 index 0000000..3f26af1 --- /dev/null +++ b/src/bts/image/observed/buffer.h @@ -0,0 +1,370 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + + + +#ifndef __bts_image_observed_buffer_h__ +#define __bts_image_observed_buffer_h__ + +namespace BTS { + + namespace Image { + + namespace Observed { + + class Buffer; + + } + + } + +} + +#include "image/header.h" +#include "image/voxel.h" + +#include "bts/triple.h" +#include "bts/image/buffer.h" +#include "bts/diffusion/encoding/set.h" +#include "bts/image/observed/buffer.h" + +#include "bts/image/properties.h" + +#include "bts/common.h" + +#define LOOP(op) \ +for (size_t z = 0; z < this->dim(Z); z++) { \ + for (size_t y = 0; y < this->dim(Y); y++) { \ + for (size_t x = 0; x < this->dim(X); x++) { \ + op \ + } \ + } \ +} + +namespace BTS { + + namespace Image { + + namespace Observed { + + template class Buffer_tpl : public Image::Buffer_tpl { + + + //Public static functions. + public: + + static Triple default_corner_offset(const Triple& dimensions, const Triple& voxel_lengths) + { return - voxel_lengths * dimensions * 0.5; } + + + // Returns the centre of the voxel in buffer space. + inline static Triple voxel_centre(Index coord) + { return coord.to_point() + Triple::Halves; } + + + // Returns the voxel coordinate that the point given in buffer space lies in. + static Index voxel_coord(Triple point) + { return Index((int)point[X], (int)point[Y], (int)point[Z]); } + + + protected: + + Triple voxel_lengths; + Triple corner_offsets; // Spatial offsets of bottom-left-back corner of the image. + + Properties props; + + + public: + + ~Buffer_tpl() {} + + + const Triple& vox_lengths() const + { return voxel_lengths; } + + + double vox_length(size_t dim_index) const + { return voxel_lengths[dim_index]; } + + + //! Offset of the lowest corner of the lowest voxel coordinate ([0,0,0]) of the image. + const Triple& offsets() const + { return corner_offsets; } + + + //! Offset of the lowest corner of the lowest voxel coordinate ([0,0,0]) of the image. + double offset(size_t dim_index) const + { return corner_offsets[dim_index]; } + + + std::ostream& to_stream (std::ostream& stream) const; + + + Properties& properties() + { return props; } + + const Properties& properties() const + { return props; } + + virtual void save(const std::string& location) const; + + + void reset(const Triple& dims, + const Triple& voxel_sizes, + const Triple& spatial_offset); + + + double rms(bool include_b0s) const; + + + virtual size_t num_encodings() const = 0; + + + virtual const Diffusion::Encoding& encoding(size_t index) const = 0; + + double max_b0() const; + + + protected: + + Buffer_tpl(bool enforce_bounds) : Image::Buffer_tpl(enforce_bounds){} + + Buffer_tpl( Triple dimensions, + Triple voxel_lengths, + Triple corner_offsets, + bool enforce_bounds); + + + Buffer_tpl(const Buffer_tpl& B) + : Image::Buffer_tpl(B), + voxel_lengths(B.voxel_lengths), + corner_offsets(B.corner_offsets), + props(B.props) {} + + + Buffer_tpl& operator= (const Buffer_tpl& B) + { this->Image::Buffer_tpl::operator= (B); voxel_lengths = B.voxel_lengths; corner_offsets = B.corner_offsets; props = B.props; return *this; } + + + + }; + + } + + } + +} + +#include "bts/image/observed/voxel.h" + +namespace BTS { + + namespace Image { + + namespace Observed { + + class Buffer : public Buffer_tpl { + + + protected: + + Diffusion::Encoding::Set encodings; + + + public: + + Buffer() : Buffer_tpl(true) {} + + //TODO: Make default constructor, and open functions. + Buffer(const Triple& dimensions, const Triple& voxel_sizes, const Triple& spatial_offset, const Diffusion::Encoding::Set& encodings) + : Buffer_tpl(dimensions, voxel_sizes, spatial_offset, true), + encodings(encodings) { } + + + Buffer(const std::string& image_location, const Diffusion::Encoding::Set& default_encodings = Diffusion::Encoding::Set()) + : Buffer_tpl(true) + { load(image_location, default_encodings); } + + + Buffer(const Buffer& B) + : Buffer_tpl(B), + encodings(B.encodings) {} + + + virtual ~Buffer() {} + + + Buffer& operator=(const Buffer& B) + { Buffer_tpl::operator=(B); encodings = B.encodings; return *this; } + + + void reset(const Triple& dims, + const Triple& voxel_sizes, + const Triple& spatial_offset, + const Diffusion::Encoding::Set& encodings) + + { Buffer_tpl::reset(dims, voxel_sizes, spatial_offset); this->encodings = encodings; } + + + void load(const std::string& location, const Diffusion::Encoding::Set& default_encodings = Diffusion::Encoding::Set()); + + + Buffer* clone() const + { return new Buffer(*this); } + + + Voxel& operator() (Index coord) + { return Image::Buffer_tpl::operator()(coord); } + + + Voxel& operator() (int x, int y, int z) + { return Image::Buffer_tpl::operator()(x,y,z); } + + + const Voxel& operator() (Index coord) const + { return Image::Buffer_tpl::operator()(coord); } + + + const Voxel& operator() (int x, int y, int z) const + { return Image::Buffer_tpl::operator()(x,y,z); } + + + size_t num_encodings() const + { return encodings.num_encodings(); } + + + const Diffusion::Encoding& encoding(size_t index) const + { return encodings[index]; } + + + const Diffusion::Encoding::Set& get_encodings() const + { return encodings; } + + size_t dim(size_t dim_index) const + { return Image::Buffer_tpl::dim(dim_index); } + + + double vox_length(size_t dim_index) const + { return Buffer_tpl::vox_length(dim_index); } + + //! Offset of the lowest corner of the lowest voxel coordinate ([0,0,0]) of the image. + double offset(size_t dim_index) const + { return Buffer_tpl::offset(dim_index); } + + + const Triple& dims() const + { return Image::Buffer_tpl::dims(); } + + + const Triple& vox_lengths() const + { return Buffer_tpl::vox_lengths(); } + + + //! Offset of the lowest corner of the lowest voxel coordinate ([0,0,0]) of the image. + const Triple& offsets() const + { return Buffer_tpl::offsets(); } + + + Buffer& zero () + { this->Image::Buffer_tpl::zero(); return *this; } + + + Double::Buffer b0 () const; + + + double average_b0() const; + + + double max_b0() const + { return Buffer_tpl::max_b0(); } + + + Double::Buffer isotropic(bool include_b0s) const; + + + double rms(bool include_b0s) const + { return Buffer_tpl::rms(include_b0s); } + + + double mean_square (bool include_b0s) const; + + + virtual void remove_isotropic(); + + + Buffer& operator+= (const Buffer& buff) + { this->Image::Buffer_tpl::operator+= (buff); return *this; } + + + Buffer& operator-= (const Buffer& buff) + { this->Image::Buffer_tpl::operator-= (buff); return *this; } + + + Buffer& operator*= (double M) + { this->Image::Buffer_tpl::operator*= (M); return *this; } + + + Buffer& operator/= (double M) + { this->Image::Buffer_tpl::operator/= (M); return *this; } + + + template Buffer& operator+= (const Image::Buffer_tpl& buff) + { this->Image::Buffer_tpl::operator+= (buff); return *this; } + + + template Buffer& operator-= (const Image::Buffer_tpl& buff) + { this->Image::Buffer_tpl::operator-= (buff); return *this; } + + + std::ostream& to_stream (std::ostream& stream) const + { return this->Buffer_tpl::to_stream(stream); } + + + Properties& properties() + { return this->Buffer_tpl::properties(); } + + const Properties& properties() const + { return this->Buffer_tpl::properties(); } + + + protected: + + + virtual Voxel new_voxel(const Index& c) + { return Voxel(*this,c); } + + + }; + + std::ostream& operator<< (std::ostream& stream, const Buffer& buffer); + + } + + } + +} + +#undef LOOP + + +#endif diff --git a/src/bts/image/observed/voxel.cpp b/src/bts/image/observed/voxel.cpp new file mode 100644 index 0000000..b6b6147 --- /dev/null +++ b/src/bts/image/observed/voxel.cpp @@ -0,0 +1,204 @@ +/* + Copyright 2010 Brain Research Institute/National ICT Australia (NICTA), Melbourne, Australia + + Written by Thomas G Close, 5/05/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + +*/ + + +#include "bts/image/voxel.h" +#include "bts/image/observed/buffer.h" +#include "bts/image/observed/voxel.h" + + +#include "bts/image/inline_functions.h" + +#define LOOP(op) \ +for (size_t encode_i = 0; encode_i < this->num_encodings(); encode_i++) {\ + op \ +} + +namespace BTS { + + namespace Image { + + namespace Observed { + + Voxel::Voxel(Observed::Buffer& obs_image, const Index& coord) + : Image::Voxel(obs_image.num_encodings()), + obs_image(&obs_image), + coordinate(coord), + centre_point(Observed::Buffer::voxel_centre(coordinate)) {} + + + Voxel::Voxel(size_t num_encodings, const Index& coord) + : Image::Voxel(num_encodings), + obs_image(0), + coordinate(coord), + centre_point(Observed::Buffer::voxel_centre(coordinate)) {} + + + + const Diffusion::Encoding& Voxel::encoding(size_t index) const + { return obs_image->encoding(index); } + + + + // NB: This will not work for signal with isotropic component removed. + double Voxel::sum_weak_difference(const Voxel& expected_image, Voxel& expected_image_gradient, bool include_b0s) const { + + double sum = 0.0; + + for (size_t encode_i = 0; encode_i < this->num_encodings(); encode_i++) { + + // If direction is not a b=0 direction. + if (this->encoding(encode_i).b_value() || include_b0s) { + + double diff = this->operator[](encode_i) - expected_image[encode_i]; + + if ( diff > 0.0) { + + sum += diff * diff; + expected_image_gradient[encode_i] = - 2.0 * diff; + + } else + expected_image_gradient[encode_i] = 0.0; + + } else + expected_image_gradient[encode_i] = 0.0; + + } + + return sum; + } + + + double Voxel::sum_strong_difference(const Voxel& expected_image, Voxel& expected_image_gradient, bool include_b0s) const { + + double sum = 0; + + for (size_t encode_i = 0; encode_i < this->num_encodings(); encode_i++) { + + // If direction is not a b=0 direction. + if (this->encoding(encode_i).b_value() || include_b0s) { + + double diff = this->operator[](encode_i) - expected_image[encode_i]; + sum += diff * diff; + expected_image_gradient[encode_i] = - 2.0 * diff; + + } else + expected_image_gradient[encode_i] = 0.0; + + } + + return sum; + } + + + double Voxel::sum_square_signal(bool include_b0s) const { + + double sum = 0; + + for (size_t encode_i = 0; encode_i < this->num_encodings(); encode_i++) { + + // If direction is not a b=0 direction. + if (this->encoding(encode_i).b_value() || include_b0s) + sum += MR::Math::pow2(this->operator[](encode_i)); + + } + + return sum; + + + } + + + + double Voxel::b0() const { + + double sum_b0 = 0.0; + size_t num_b0 = 0; + + for (size_t encode_i = 0; encode_i < this->num_encodings(); encode_i++) { + + if (this->encoding(encode_i).b_value() == 0.0) { + sum_b0 += this->operator[](encode_i); + ++num_b0; + } + } + + return sum_b0 / (double)num_b0; + } + + + double Voxel::isotropic() const { + + double sum = 0.0; + + size_t num_b0s = 0; + + for (size_t encode_i = 0; encode_i < this->num_encodings(); encode_i++) { + + if (this->encoding(encode_i).b_value()) + sum += this->operator[](encode_i); + else + ++num_b0s; + + } + + return sum /(double)(num_encodings() - num_b0s); + + } + + double Voxel::rms() const{ + + double sum = 0.0; + + for (size_t encode_i = 0; encode_i < this->num_encodings(); encode_i++) { + + sum += MR::Math::pow2(this->operator[](encode_i)); + + } + + return MR::Math::sqrt(sum /(double)num_encodings()); + + } + + + void Voxel::remove_isotropic() { + + double iso = this->isotropic(); + + for (size_t encode_i = 0; encode_i < this->num_encodings(); encode_i++) { + + if (this->encoding(encode_i).b_value()) + this->operator[](encode_i) -= iso; + + } + + } + + + + } + + } + +} + +#undef LOOP diff --git a/src/bts/image/observed/voxel.h b/src/bts/image/observed/voxel.h new file mode 100644 index 0000000..d2d9937 --- /dev/null +++ b/src/bts/image/observed/voxel.h @@ -0,0 +1,159 @@ +/* + Copyright 2010 Brain Research Institute/National ICT Australia (NICTA), Melbourne, Australia + + Written by Thomas G Close, 5/05/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + +*/ + +#ifndef __image_observed_voxel_h__ +#define __image_observed_voxel_h__ + +#include +#include + +#include "bts/common.h" + +#include "bts/image/observed/buffer.h" +#include "bts/diffusion/encoding.h" +#include "bts/image/voxel.h" +#include "bts/image/observed/buffer.h" +#include "bts/image/voxel.h" + +namespace BTS { + + namespace Image { + + namespace Observed { + + class Voxel : public Image::Voxel { + + //Public nested classes and typedefs + public: + + typedef Observed::Buffer Buffer; + + + protected: + + Buffer* obs_image; + + Index coordinate; + Coord centre_point; + + public: + + Voxel() {} + + Voxel(Buffer& buffer, const Index& coord); + + Voxel(const Voxel& v) + : Image::Voxel(v), obs_image(v.obs_image), coordinate(v.coordinate), centre_point(v.centre_point) {} + + + + Voxel& operator= (const Voxel& v) { + + Image::Voxel::operator=(v); + obs_image = v.obs_image; + coordinate = v.coordinate; + centre_point = v.centre_point; + + return *this; + } + + + //Doesn't copy across the parent image or coordinate. + Voxel& copy_value (const Voxel& v) + { Image::Voxel::operator=(v); return *this; } + + virtual ~Voxel() {} + + + virtual const Diffusion::Encoding& encoding(size_t index) const; + + + double b0() const; + + + const Coord& centre() const + { return centre_point; } + + + const Index& coord() const + { return coordinate; } + + + double sum_square_signal(bool include_b0s) const; + + + double mean_square_signal(bool include_b0s) const + { return sum_square_signal(include_b0s) / num_encodings(); } + + + double sum_strong_difference(const Voxel& expected_image, Voxel& expected_image_gradient, bool include_b0s) const; + + + double sum_weak_difference(const Voxel& expected_image, Voxel& expected_image_gradient, bool include_b0s) const; + + + double isotropic() const; + + + void remove_isotropic(); + + + double rms() const; + + + Voxel operator-() const + { Voxel answer(*this); for (size_t encode_i = 0; encode_i < num_encodings(); encode_i++) answer[encode_i] = -operator[](encode_i); return answer; } + + protected: + + Voxel(size_t num_encodings, const Index& coord); + + // friend class Observed::Buffer; + + friend std::ostream& operator<< (std::ostream& stream, const Observed::Voxel& voxel); + + + }; + + inline std::ostream& operator<< (std::ostream& stream, const Observed::Voxel& voxel) { + + stream << "coord: " << voxel.coordinate << std::endl; + stream << "centre point: " << voxel.centre_point << std::endl; + stream << "intensities: " << std::endl; + for (size_t encode_i = 0; encode_i < voxel.num_encodings(); encode_i++) { + stream << voxel[encode_i] << ", "; + } + stream << std::endl; + + return stream; + + } + + } + + } + +} + +#undef LOOP + +#endif diff --git a/src/bts/image/properties.h b/src/bts/image/properties.h new file mode 100644 index 0000000..14adf62 --- /dev/null +++ b/src/bts/image/properties.h @@ -0,0 +1,56 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, 21/07/2010. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + +#ifndef __bts_image_properties_h__ +#define __bts_image_properties_h__ + +#include + +namespace BTS { + + namespace Image { + + class Properties : public std::map{ + + //Public static variables, nested classes and typedefs + public: + + + //Protected member variables + protected: + + + //Public member functions + public: + + + //Protected member functions + protected: + + + }; + + } + +} + +#endif /* __bts_image_properties_h__ */ diff --git a/src/bts/image/reference/buffer.h b/src/bts/image/reference/buffer.h new file mode 100644 index 0000000..cab26a9 --- /dev/null +++ b/src/bts/image/reference/buffer.h @@ -0,0 +1,114 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + + +#ifndef __bts_image_reference_buffer_h__ +#define __bts_image_reference_buffer_h__ + + +namespace BTS { + + namespace Image { + + namespace Reference { + + template class Buffer; + + } + + } + +} + +#include "bts/fibre/strand/section.h" +#include "bts/fibre/tractlet/section.h" +#include "bts/fibre/tractlet/tensor.h" +#include "bts/fibre/strand/tensor.h" + + + +#define LOOP(op) \ +for (size_t z = 0; z < this->dim(Z); z++) { \ + for (size_t y = 0; y < this->dim(Y); y++) { \ + for (size_t x = 0; x < this->dim(X); x++) { \ + op \ + } \ + } \ +} + + +namespace BTS { + + namespace Image { + + namespace Reference { + + template class Buffer : public Image::Buffer_tpl< std::vector > { + + public: + + typedef std::map > Set; + +// class Set : public std::map > { +// +// Set() : std::map >() {} +// Set(const std::map >& m) : std::map >(m) {} +// ~Set() {}; +// +// }; + + public: + + Buffer () + : Image::Buffer_tpl< std::vector >(false) {} + + + Buffer (const Buffer& B) + : Image::Buffer_tpl< std::vector >(B) {} + + + ~Buffer () {} + + + Buffer* clone() + { return new Buffer(*this); } + + + Buffer& operator= (const Buffer& B) + { Image::Buffer_tpl< std::vector >::operator= (B); return *this; } + + + void clear_references() + { for (typename Image::Buffer_tpl< std::vector >::iterator vox_it = this->begin(); vox_it != this->end(); ++vox_it) vox_it->second.clear(); } + + }; + + } + + } + +} + + +#undef LOOP + +#endif //__bts_image_reference_buffer_h__ diff --git a/src/bts/image/voxel.h b/src/bts/image/voxel.h new file mode 100644 index 0000000..cf19439 --- /dev/null +++ b/src/bts/image/voxel.h @@ -0,0 +1,194 @@ +/* + Copyright 2010 Brain Research Institute/National ICT Australia (NICTA), Melbourne, Australia + + Written by Thomas G Close, 5/05/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + +*/ + +#ifndef __bts_image_voxel_h__ +#define __bts_image_voxel_h__ + +namespace BTS { + namespace Image { + + template class Voxel; + + } +} + + +#include +#include + +#include "bts/common.h" + +#define LOOP(op) \ +for (size_t encode_i = 0; encode_i < this->num_encodings(); encode_i++) {\ + op \ +} + + + +namespace BTS { + + namespace Image { + + template std::ostream& operator<< (std::ostream& stream, const Voxel& voxel); + + template class Voxel { + + protected: + + std::vector intensities; + + public: + + Voxel() {} + + Voxel(size_t num_encodings) + : intensities(num_encodings) {} + + + Voxel(size_t num_encodings, const T& default_value) + : intensities(num_encodings, default_value) { + } + + + Voxel(const Voxel& voxel) + : intensities(voxel.intensities) {} + + + Voxel& operator= (const Voxel& voxel) + { intensities = voxel.intensities;return *this; } + + + template Voxel& operator=(const U& vox) + { return operator=((const Voxel&)vox); } + + + + virtual ~Voxel() {} + + void resize(size_t new_size, const T& default_value = T()) + { intensities.resize(new_size, default_value); } + + T& operator[] (size_t encode_i) + { return intensities[encode_i]; } + + + const T& operator[] (size_t encode_i) const + { return intensities[encode_i]; } + + + Voxel operator-() const + { return Voxel(*this).negate(); } + + + Voxel& negate() + { LOOP(operator[](encode_i) = -operator[](encode_i);) return *this; } + + + Voxel& operator+= (const Voxel& v) + { LOOP(operator[](encode_i) += v[encode_i];) return *this; } + + + Voxel& operator+= (T f) + { LOOP(operator[](encode_i) += f;) return *this; } + + + Voxel& operator-= (const Voxel& v) + { LOOP(operator[](encode_i) -= v[encode_i];) return *this; } + + + Voxel& operator-= (T f) + { LOOP(operator[](encode_i) -= f;) return *this; } + + + Voxel& operator*= (T f) + { LOOP(operator[](encode_i) *= f;) return *this; } + + + Voxel& operator/= (T f) + { LOOP(operator[](encode_i) /= f;) return *this; } + + + Voxel operator+ (const Voxel& v) const + { Voxel answer(*this); answer += v; return answer; } + + + Voxel operator+ (T f) const + { Voxel answer(*this); answer += f; return answer; } + + + Voxel operator- (const Voxel& v) const + { Voxel answer(*this); answer -= v; return answer; } + + + Voxel operator- (T f) const + { Voxel answer(*this); answer -= f; return answer; } + + + Voxel operator* (T f) const + { Voxel answer(*this); answer *= f; return answer; } + + + Voxel operator/ (T f) const + { Voxel answer(*this); answer /= f; return answer; } + + + Voxel& zero() + { LOOP(BTS::zero(operator[](encode_i));) return *this; } + + + size_t num_encodings() const + { return intensities.size(); } + + + size_t size() const + { return intensities.size(); } + + friend std::ostream& operator<<<> (std::ostream& stream, const Voxel& voxel); + + }; + + template Voxel operator+ (T f, const Voxel& v) + { Voxel answer(v); answer += f; return answer; } + + + template Voxel operator* (T f, const Voxel& v) + { Voxel answer(v); answer *= f; return answer; } + + + template std::ostream& operator<< (std::ostream& stream, const Voxel& voxel) { + + for (size_t encode_i = 0; encode_i < voxel.num_encodings(); encode_i++) { + stream << voxel[encode_i] << ", "; + } + stream << std::endl; + return stream; + + } + + + } + +} + +#undef LOOP + +#endif diff --git a/src/bts/inline_functions.h b/src/bts/inline_functions.h new file mode 100644 index 0000000..e334ccb --- /dev/null +++ b/src/bts/inline_functions.h @@ -0,0 +1,56 @@ +/* + Copyright 2010 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close on Jun 3, 2010. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + +*/ + +#ifndef __bts_inline_functions_h__ +#define __bts_inline_functions_h__ + + + +#include "bts/image/inline_functions.h" + +#include "bts/prob/inline_functions.h" + + +#include "bts/diffusion/inline_functions.h" + +#include "bts/analysis/inline_functions.h" + +#include "bts/mcmc/inline_functions.h" + +#include "bts/utilities/inline_functions.h" + + +//#ifdef __bts_triple_tensor_h__ +// +//#include "bts/triple/tensor.cpp.h" +// +//#endif + +//#ifdef __bts_triple_tensor_writer_h__ +// +//#include "bts/triple/tensor/writer.cpp.h" +// +//#endif + +#endif /* __inlined_functions_h__ */ + + diff --git a/src/bts/math/blossom.cpp b/src/bts/math/blossom.cpp new file mode 100644 index 0000000..65af6ab --- /dev/null +++ b/src/bts/math/blossom.cpp @@ -0,0 +1,229 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, Mar 20, 2011. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + +#include +#include + +#include "bts/common.h" + +#include "bts/math/blossom.h" + +#include "blossom5/PerfectMatching.h" +#include "blossom5/CheckPerfectMatching.h" + +const double WEIGHTS_RANGE = 1e6; + +namespace BTS { + + namespace Math { + + namespace Blossom { + + + std::vector match_pairs(const std::vector& edges, + bool check_match, + bool fractional_jumpstart, + int dual_greedy_update_option, + double dual_LP_threshold, + bool update_duals_before, + bool update_duals_after, + double single_tree_threshold, + bool verbose) { + + + if (!edges.size()) + throw Exception ("Edges vector passed to 'Math::Blossom::match_pairs' is empty."); + + struct PerfectMatching::Options options; + + //---------------------------------------------------------------------------------// + // Convert weights from double to int with the smallest amount of information lost // + //---------------------------------------------------------------------------------// + + + std::set nodes; + + for (size_t edge_i = 0; edge_i < edges.size(); ++edge_i) { + nodes.insert(edges[edge_i].first); + nodes.insert(edges[edge_i].second); + } + + if (nodes.size() & 1) + throw Exception ("Odd number of nodes (" + str(edges.size()) + "), run BTS::Math::Blossom::if_odd_remove_worst() first to remove worst match (in a greedy sense)."); + + + size_t mapped_node = 0; + std::map mapped_nodes; + + for (std::set::iterator node_it = nodes.begin(); node_it != nodes.end(); ++node_it) { + mapped_nodes[*node_it] = mapped_node; + ++mapped_node; + } + + int* edges_array = new int[edges.size()*2]; + + for (size_t edge_i = 0; edge_i < edges.size(); ++edge_i) { + edges_array[edge_i*2] = mapped_nodes[edges[edge_i].first]; + edges_array[edge_i*2+1] = mapped_nodes[edges[edge_i].second]; + } + + + double max_weight = std::max_element(edges.begin(), edges.end())->weight; + double min_weight = std::min_element(edges.begin(), edges.end())->weight; + + double range = max_weight - min_weight; + + int* weights_array = new int[edges.size()]; + + for (size_t edge_i = 0; edge_i < edges.size(); edge_i++) { + weights_array[edge_i] = (edges[edge_i].weight - min_weight) * WEIGHTS_RANGE / range; + } + + + std::ofstream f ("/home/tclose/data/edge_graph.txt"); + f << nodes.size() << " " << edges.size() << std::endl; + for (size_t edge_i = 0; edge_i < edges.size(); ++edge_i) + f << edges_array[edge_i*2] << " " << edges_array[edge_i*2+1] << " " << weights_array[edge_i] << std::endl; + + + PerfectMatching *pm = new PerfectMatching(nodes.size(), edges.size()); + for (size_t edge_i = 0; edge_i < edges.size(); ++edge_i) + pm->AddEdge(edges_array[edge_i*2], edges_array[edge_i*2+1], weights_array[edge_i]); + + pm->options = options; + pm->Solve(); + + if (check_match) { + + int error = CheckPerfectMatchingOptimality(nodes.size(), edges.size(), edges_array, weights_array, pm); + + if (error) + throw Exception ("Blossom pair matching failed (error code " + str(error) + ")."); + + } + + std::vector output_pairs; + + for (size_t edge_i = 0; edge_i < edges.size(); ++edge_i) + if (pm->GetSolution(edge_i)) + output_pairs.push_back(edges[edge_i]); + + delete pm; + delete weights_array; + delete edges_array; + + return output_pairs; + + } + + + + //If there are an odd number of nodes then remove the node with the maximum minimum weight. + std::vector make_even(const std::vector& edges) { + + std::map node_min_weights; + + for (size_t edge_i = 0; edge_i < edges.size(); ++edge_i) { + + double weight = edges[edge_i].weight; + + for (size_t node_i = 0; node_i < 2; ++node_i) { + + size_t node = edges[edge_i].node(node_i); + + if (!node_min_weights.count(node)) + node_min_weights[node] = weight; + else { + if (weight < node_min_weights[node]) + node_min_weights[node] = weight; + } + + } + + } + + size_t num_nodes = node_min_weights.size(); + + std::vector even_edges (edges); + + //If odd number of nodes, remove the 'worst' one. + if (num_nodes & 1) { + + bool even_found = false; + + std::vector< std::pair > sorted_min_weights; + + for (std::map::iterator min_weight_it = node_min_weights.begin(); min_weight_it != node_min_weights.end(); ++min_weight_it) + sorted_min_weights.push_back(std::pair(min_weight_it->first, min_weight_it->second)); + + std::sort(sorted_min_weights.begin(), sorted_min_weights.end(), CompareSecond()); + + for (std::vector< std::pair >::reverse_iterator mw_it = sorted_min_weights.rbegin(); mw_it != sorted_min_weights.rend(); mw_it++) { + + size_t node = mw_it->first; + + for (std::vector::iterator edge_it = even_edges.begin(); edge_it != even_edges.end();) + if ((edge_it->first == node) || (edge_it->second == node)) + edge_it = even_edges.erase(edge_it); + else + ++edge_it; + + if (calc_num_nodes(even_edges) & 1) + even_edges = edges; + else { + even_found=true; + break; + } + + } + + if (!even_found) + throw Exception ("An even number of nodes could not be found using the 'make_even' algorithm. Suggest manual removal."); + + } + + return even_edges; + + } + + + + + size_t calc_num_nodes(const std::vector& edges) { + + std::set nodes; + + for (std::vector::const_iterator edge_it = edges.begin(); edge_it != edges.end(); ++edge_it) { + nodes.insert(edge_it->first); + nodes.insert(edge_it->second); + } + + return nodes.size(); + + } + + + } + + } + +} diff --git a/src/bts/math/blossom.h b/src/bts/math/blossom.h new file mode 100644 index 0000000..965647e --- /dev/null +++ b/src/bts/math/blossom.h @@ -0,0 +1,60 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, Mar 16, 2011. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + +#ifndef __bts_math_blossom_h__ +#define __bts_math_blossom_h__ + +#include +#include "bts/common.h" + +#include "bts/math/blossom/edge.h" + +namespace BTS { + + namespace Math { + + namespace Blossom { + + + std::vector match_pairs(const std::vector& edges, + bool check_match = false, + bool fractional_jumpstart = true, + int dual_greedy_update_option = 0, + double dual_LP_threshold = 0.0, + bool update_duals_before = false, + bool update_duals_after = false, + double single_tree_threshold = 1.0, + bool verbose = true); + + + + std::vector make_even(const std::vector& edges); + + + size_t calc_num_nodes(const std::vector& edges); + + } + } + +} + +#endif /* __bts_math_blossom_h__ */ diff --git a/src/bts/math/blossom/edge.h b/src/bts/math/blossom/edge.h new file mode 100644 index 0000000..24d5eab --- /dev/null +++ b/src/bts/math/blossom/edge.h @@ -0,0 +1,71 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, Mar 20, 2011. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + +#ifndef __bts_math_blossom_edge_h__ +#define __bts_math_blossom_edge_h__ + +namespace BTS { + + namespace Math { + + namespace Blossom { + + class Edge { + + public: + + Edge() {} + + Edge(size_t first, size_t second, double weight) + : first(first), second(second), weight(weight) {} + + public: + + size_t first; + size_t second; + double weight; + + bool has_node(size_t index) const + { return (first == index) || (second == index); } + + size_t& node(size_t index) { assert(index < 2); return !index ? first : second; } + const size_t& node(size_t index) const { assert(index < 2); return !index ? first : second; } + + bool operator< (const Edge& e) const { return weight < e.weight; } + + }; + + + inline std::ostream& operator<<(std::ostream& stream, const Edge& e) { + + stream << "{" << e.first << "," << e.second << "} = " << e.weight; + + return stream; + + } + } + + } + +} + +#endif /* */ diff --git a/src/bts/math/common.cpp b/src/bts/math/common.cpp new file mode 100644 index 0000000..8d54dd4 --- /dev/null +++ b/src/bts/math/common.cpp @@ -0,0 +1,139 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, Sep 13, 2010. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + +#include "bts/math/common.h" + +namespace BTS { + + namespace Math { + + + + MR::Math::Matrix random_rotation(gsl_rng* rand_gen, size_t ndims) { + + MR::Math::Matrix rotate_matrix(ndims,ndims); + + for (size_t col_i = 0; col_i < ndims; col_i++) { + + MR::Math::Vector ith_vector = rotate_matrix.column(col_i); + + for (size_t dim_i = 0; dim_i < ndims; dim_i++) + ith_vector[dim_i] = gsl_ran_gaussian(rand_gen, 1.0); + + MR::Math::normalise(ith_vector); + + for (size_t prev_col_i = 0; prev_col_i < col_i; prev_col_i++) { + + MR::Math::Vector proj = rotate_matrix.column(prev_col_i); + + double proj_scalar = MR::Math::dot(ith_vector, proj); + + proj *= proj_scalar; + + ith_vector -= proj; + + MR::Math::normalise(ith_vector); + + } + + } + + return rotate_matrix; + + } + + + std::vector binary_string(size_t size, size_t index) { + + + std::vector string(size); + + size_t mask = 1; + + for (size_t i = 0; i < size; ++i) { + string[i] = index & mask; + mask = mask << 1; + } + + return string; + + } + + std::string matlab_str(const MR::Math::Vector& v) { + + std::ostringstream stream; + + stream << "["; + + for (uint i = 0; i < v.size()-1; i++) + stream << v[i] << " "; + + stream << v[v.size()-1]; + + stream << "]"; + + return stream.str(); + + } + + + + std::string matlab_str(const MR::Math::Matrix& m) { + + std::ostringstream stream; + stream << "["; + + for (uint row_i = 0; row_i < m.rows(); row_i++) { + for (uint col_i = 0; col_i < m.columns(); col_i++) { + stream << m(row_i, col_i); + if (col_i != m.columns()-1) + stream << ", "; + + } + if (row_i != m.rows()-1) + stream << ";"; + } + + stream << "]"; + + return stream.str(); + + } + + + double trace(const MR::Math::Matrix& m) { + + assert(m.rows() == m.columns()); + + double sum = 0.0; + + for (uint i = 0; i < m.rows(); ++i) + sum += m(i,i); + + return sum; + + } + + + } + +} diff --git a/src/bts/math/common.h b/src/bts/math/common.h new file mode 100644 index 0000000..3eb2dd7 --- /dev/null +++ b/src/bts/math/common.h @@ -0,0 +1,91 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, 21/07/2010. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + +#ifndef __bts_math_common_h__ +#define __bts_math_common_h__ + +extern "C" { +#include +#include +} + +#include "math/vector.h" +#include "math/matrix.h" + +namespace BTS { + + namespace Math { + + + inline int sign(double x) + { return (x > 0) - (x < 0); } + + + template MR::Math::Matrix outer(const MR::Math::Vector& v1, const MR::Math::Vector& v2) { + + MR::Math::Matrix answer(v1.size(), v2.size()); + + for (size_t row_i = 0; row_i < v1.size(); row_i++) + for (size_t col_i = 0; col_i < v2.size(); col_i++) + answer(row_i,col_i) = v1[row_i] * v2[col_i]; + + return answer; + + } + + inline MR::Math::Matrix operator* (const MR::Math::Matrix& matrix, double scalar) { + + MR::Math::Matrix answer (matrix); + + return answer *= scalar; + + } + + inline MR::Math::Matrix operator* (double scalar, const MR::Math::Matrix& matrix) { + + return matrix * scalar; + + } + + MR::Math::Matrix random_rotation(gsl_rng* rand_gen, size_t ndims); + + + std::vector binary_string(size_t size, size_t i); + + + + //! Returns a single-line string representation of a MRtrix vector in a format readable by the MATLAB software package. + std::string matlab_str(const MR::Math::Vector& v); + + + //! Returns a single-line string representation of a MRtrix matrix in a format readable by the MATLAB software package. + std::string matlab_str(const MR::Math::Matrix& m); + + + //! returns the trace of the matrix. + double trace(const MR::Math::Matrix& m); + + } + +} + +#endif /* __bts_math_math_h__ */ diff --git a/src/bts/math/kmeans.cpp b/src/bts/math/kmeans.cpp new file mode 100644 index 0000000..6f53b75 --- /dev/null +++ b/src/bts/math/kmeans.cpp @@ -0,0 +1,72 @@ +/* + + Copyright 2010 Brain Research Institute/National ICT Australia (NICTA), Melbourne, Australia + + Modified by Thomas G Close, 10/4/11 from KMlocal.cpp + written by David Mount from the University of Maryland, 05/14/04 + as part of the Kmeans package available at + 'http://www.cs.umd.edu/~mount/Projects/KMeans/' + under the GNU General public licence. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + +*/ + +#include "bts/math/kmeans.h" // KMlocal includes + +namespace BTS { + + namespace Math { + + //---------------------------------------------------------------------- + // execute - execute the clustering algorithm + // This function executes the clustering algorithm. See the file + // KMlocal.h for a description of this algorithm. + //---------------------------------------------------------------------- + + ::KMfilterCenters KMeansBase::execute() // execute the algorithm + { + reset(); // resets everything + while (!isDone()) { // while not done + beginRun(); // start a new run + do { // do while run is not done + beginStage(); // start of stage processing + KMalg method = selectMethod(); // select a method + switch(method) { // apply one stage + case LLOYD: // Lloyd's algorithm + curr.lloyd1Stage(); + break; + case SWAP: // swap heuristic + curr.swap1Stage(); + break; + case RANDOM: // get random centers + curr.genRandom(); + break; + default: // shouldn't come here + assert(false); + break; + } + endStage(); // end of stage processing + } while (!isRunDone()); // while run is not done + endRun(); // end of run processing + tryAcceptance(); // accept if appropriate + } + return best; // return best solution + } + + + } +} diff --git a/src/bts/math/kmeans.h b/src/bts/math/kmeans.h new file mode 100644 index 0000000..777099d --- /dev/null +++ b/src/bts/math/kmeans.h @@ -0,0 +1,497 @@ +/* + + Copyright 2010 Brain Research Institute/National ICT Australia (NICTA), Melbourne, Australia + + Modified by Thomas G Close, 10/4/11 from KMlocal.h + written by David Mount from the University of Maryland, 05/14/04 + as part of the Kmeans package available at + 'http://www.cs.umd.edu/~mount/Projects/KMeans/' + under the GNU General public licence. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + +*/ + + + + +#ifndef __bts_math_kmeans_h__ +#define __bts_math_kmeans_h__ + +//---------------------------------------------------------------------- +// basic includes +//---------------------------------------------------------------------- +#include // math includes (exp, log) +#include "k_means/KMeans.h" // kmeans includes +#include "k_means/KMdata.h" // data points +#include "k_means/KMfilterCenters.h" // centers +#include "k_means/KMterm.h" // termination conditions +#include "k_means/KMrand.h" // random number generation +#include "k_means/KMlocal.h" + + +namespace BTS { + + namespace Math { + + //------------------------------------------------------------------------ + // Generic Local Search Overview + // KMlocal provides a generic algorithm for k-means clustering by + // local search. This generic algorithm is controlled by a class, + // KMlocal, whose methods provide the particular elements of each + // algorithm. + // + // Overview: + // --------- + // The generic algorithm begins by generating an initial solution + // "curr" and saving it in "best". These objects are local to the + // KMlocal structure. The value of "curr" reflects the current + // solution and "best" reflects the best solution seen so far. + // + // The algorithm consists of some number of basic iterations, + // called "stages". Each stage involves the execution of one step + // of either the swap heuristic or Lloyd's algorithm. + // + // Stages are grouped into "runs". Intuitively, a run involves a + // (small) number of stages in search of a better solution. A run + // might end, say, because a better solution was found or a fixed + // number of stages have been performed without any improvement. + // + // After a run is finished, we check to see whether we want to + // "accept" the solution. Presumably this happens if the cost is + // lower, but it may happen even if the cost is inferior in other + // circumstances (e.g., as part of a simulated annealing approach). + // Accepting a solution means copying the current solution to the + // saved solution. In some cases, the acceptance may involve + // reseting the current solution to a random solution. + // + // Generic Algorithm: + // ------------------ + // The generic local search algorithm is shown below. The various + // functions are overridden by the specific classes which provide + // the concrete details. + // + // reset() // resets curr and best + // while ( !isDone() ) { // while not done + // beginRun() // begin a new run + // do { // do while run is not done + // beginStage() // end of stage processing + // method = selectMethod() // select a method + // switch( method ) { // apply the method + // LLOYD: curr.Lloyd(); break + // SWAP: curr.Swap(); break + // RANDOM: curr.Random(); break + // } + // endStage() // end of stage processing + // } while ( !isRunDone() ) // while run is not done + // tryAcceptance() // accept if appropriate + // endRun() // end of run processing + // } + // return best // return best solution + // + // Termination Parameters + // ---------------------- + // Each algorithm relies on various parameter settings to determine + // termination conditions for runs and phases. These settings are + // stored in a class KMterm (see KMterm.h). + // + // Parameters (in term) + // -------------------- + // maxTotStage + // Maximum number of stages total. + //------------------------------------------------------------------------ + + class KMeansBase { // generic local search + protected: + // fixed quantities + int nPts; // number of points + int kCtrs; // number of centers + int dim; // dimension + ::KMterm term; // termination conditions + int maxTotStage; // max total stages (from term) + // varying quantities + int stageNo; // current stage number + int runInitStage; // stage at which run started + ::KMfilterCenters curr; // current solution + ::KMfilterCenters best; // saved solution + protected: // utility functions + virtual void printStageStats() { // print stage information + if (kmStatLev >= STAGE) { + *kmOut << "\t" << endl; + } + } + public: + // constructor + KMeansBase(const ::KMfilterCenters &sol, const ::KMterm &t) + : term(t), curr(sol), best(sol) { + nPts = sol.getNPts(); + kCtrs = sol.getK(); + dim = sol.getDim(); + stageNo = 0; + maxTotStage = term.getMaxTotStage(kCtrs, nPts); + } + + virtual ~KMeansBase() { } // virtual destructor + virtual ::KMfilterCenters execute(); // execute the algorithm + + int getTotalStages() const { // return total no. of stages + return stageNo; + } + + protected: // overridden by subclasses + virtual void reset() { // reset everything + stageNo = 0; + runInitStage = 0; + curr.genRandom(); // generate random centers + curr.getDist(); // compute initial distortion + best = curr; + } + virtual bool isDone() const { // are we done? + return stageNo >= maxTotStage; + } + virtual void beginRun() { // begin of run processing + runInitStage = stageNo; + } + virtual void beginStage() { } // start of stage processing + virtual ::KMalg selectMethod() = 0; // method: LLOYD or SWAP + virtual void endStage() { // end of stage processing + stageNo++; + } + virtual bool isRunDone() { // is run done? + return isDone(); + } + virtual void endRun() { } // end of run processing + virtual void tryAcceptance() { // test acceptance + if (curr.getDist() < best.getDist()) { // is current distortion lower? + best = curr; // then best the current + } + } + }; + + + + + //------------------------------------------------------------------------ + // KMlocalHybrid - a hybrid version combining Lloyd's and swaps. + // + // Overview + // -------- + // This implements a hybrid algorithm, which combines both of the + // previous methods along with something like simulated annealing. + // Because this uses a fast annealing schedule (T = T*timeFact) it + // should probably be called simulated quenching. + // + // The algorithm's execution is broken into the following different + // groups. + // + // Stage: One invocation of the Swap or Lloyd's algorithm. + // Run: A run consists of a consecutive sequence of swaps + // followed by a consecutive sequence of Lloyd's steps. A + // graphical representation of one run is presented below. + // + // +--+ +---+ +--------> save -----> + // | | | | Y| + // V | V | | N + // ----> Swap ------> Lloyd's ----> Accept? ----> restore --> + // old + // + // Decisions + // --------- + // There are three decisions which this algorithm needs to make. + // + // Continue swapping or move on to Lloyd's? + // This is based on the simulated annealing decision choice, + // based on the consecutive RDL. + // + // Make another pass through Lloyd's or go to acceptance? + // This is based on whether the relative improvement since the + // last stage (consecutive relative distortion loss) is above a + // certain fixed threshold (minConsecRDL). + // + // Accept the current solution: + // If the current solution is better than the saved solution, + // then yes. Otherwise, use the simulated annealing decision + // choice, based on the accumulated RDL. + // + // Simulated Annealing Choice + // -------------------------- + // Following the principal of simulated annealing, we somtimes + // chose to accept a solution, even if it is not an improvement. + // This choice occurs with probability: + // + // exp(RDL/T), + // + // where RDL is the relative distortion loss (relative to the + // saved solution), and T is the current temperature. Note that + // if RDL > 0 (improvement) then this quantity is > 1, and so we + // always accept. (Note that this is not formally correct, since + // in simulated annealing the probability should be based on the + // absolute distortion change not the relative distortion change.) + // + // Annealing Schedule + // ------------------ + // The temperature value T is a decreasing function of the number + // of the number of stages. It starts at some initial value T0 and + // decreases slowly over time. Rather than using the standard (slow) + // Boltzman annealing schedule, we use the following fast annealing + // schedule, every L stages we set + // + // T = TF * T, + // + // where: + // L (= tempRunLength) is an integer parameter set by the + // user. (Presumably it depends on the number of + // centers and the dimension of the space.) + // TF (= tempReducFactor) is a real number of the form 1-x, + // for some small x. + // + // These parameters are provided by the user and are stored in the + // termination condition class. + // + // Initial Temperature + // ------------------- + // The initial temperature T0 is a tricky thing to set. The user + // supplies a parameter p0 = initProbAccept, the initial + // probability of accepting a random swap. However, the + // probability of acceting a swap depends on the given RDL value. + // To estimate this, for the first L runs we use p0 as the + // probability. Over these runs we compute the average rdl value. + // Once the first L runs have completed, we set T0 so that: + // + // exp(-averageRDL/T0) = initProbAccept, + // + // or equivalently + // + // T0 = -averageRDL/(ln initProbAccept). + // + // Parameters (in term) + // -------------------- + // initProbAccept + // Initial probability of accepting an solution that does + // not alter the distortion. + // tempRunLength + // The number of stages before chaning the temperature. + // tempReducFactor + // The factor by which temperature is reduced at the end of + // a temperature run. + // minConsecRDL + // Minimum consecutive RDL needed to keep Lloyd's algorithm + // going. + // + // State variables + // --------------- + // temperature + // Temperature parameter for simulated annealing. + // initTempRunStage + // The stage number at the start of a temperature run. + // areSwapping + // True if we are still in swapping portion of a run, and + // false if we are in the Lloyd's portion of the run. + // prevDist + // In order to compute the consecutive RDL we need to save + // the distortion at the start of each trip through Lloyd's + // algorithm. + // save Simulated annealing may move to a worse solution at + // times. The "best" solution stores the global best. The + // "save" solution is the solution that simulated annealing + // falls back to if a solution is not accepted. + // sumTrials + // Sum of rdl values during the initial trials, where we + // are trying to estimate the mean RDL value. + // trialCt + // A counter which starts at the number of initial trials. + // When it reaches 0, we compute the average RDL value and + // set the initial temperature value. + // + // Utilities particular to Simulated Annealing + // ------------------------------------------- + // simAnnealAccept() + // Random acceptance test for simulated annealing. + // initTempRun() + // Initialize a temperature run process by computing the + // initial temperature value and saving the current + // stage number in initTempRunStage. + // isTempRunDone() + // Check whether the current temperature run is done. + // endTempRun() + // End a temperature run by updating the temperature value + // and saving the current stage number in initTempRunStage. + // + // Overridden methods + // ------------------ + // reset() + // Do base class resetting. Initialize areSwapping to + // true. Save the current solution in save. Initialize + // temperature runs. + // beginStage() + // Save current distortion in prevDist (for computing + // consecutive RDL). + // selectMethod() + // If we are swapping, use Swap, and otherwise use Lloyd's. + // endStage() + // Increment the stage number, get the distortion, and print + // the end-of-stage information. + // isRunDone() + // If we are swapping, then compute the simulated annealing + // random choice. If it rejects, then we have ended the + // swapping process and are transitioning to Lloyd's + // algorithm. In either case, return false. + // + // If we are doing Lloyd's, return true if the consecutive + // RDL is less than minConsecRDL, meaning that Lloyd's + // algorithm has converged. + // endRun() + // If temperature run is done then do processing for the + // end of a temperature run. Set areSwapping to true. + // tryAcceptance() + // At this point we have completed all the swaps and all + // the Lloyd's iterations. If the distortion has improved + // or if the simulated annealing random choice says to, + // save the current solution (and update the overall best + // if needed). Otherwise, restore the previously saved + // solution. + //------------------------------------------------------------------------ + + class KMeans : public ::KMlocal { + private: + double temperature; // temperature used in SA + int initTempRunStage; // stage when temp run started + bool areSwapping; // are we swapping? (or Lloyd's) + double prevDist; // distortion from prev stage + double sumTrials; // sum of RDL's over trials + int trialCt; // trial count + ::KMfilterCenters save; // saved solution + protected: // local utilities + double accumRDL() // accumulated RDL + { return (save.getDist() - curr.getDist()) / save.getDist(); } + + double consecRDL() // consecutive RDL + { return (prevDist - curr.getDist()) / prevDist; } + + virtual void printStageStats() { // print end of stage info + if (kmStatLev >= STAGE) { + *kmOut << " " << endl; + } + } + virtual void printRunStats() { // print end of run info + if (kmStatLev >= STAGE) { + *kmOut << " " << endl; + } + } + protected: // SA utilities + int nTrials() // number of trials + { return kmMax(20, term.getTempRunLength()); } + + bool simAnnealAccept(double rdl) { // random accept choice + double prob; + if (--trialCt >= 0) { // still in trial phase? + sumTrials += fabs(rdl); // increment sum of RDLs + if (trialCt == 0) { // last trial? get temp + temperature = -sumTrials/(nTrials()*log(term.getInitProbAccept())); + initTempRunStage = stageNo; // start counting stages + } + prob = term.getInitProbAccept(); // use initial probability + } + else { // use SA probability + prob = kmMin(term.getInitProbAccept(), exp(rdl/temperature)); + } + return prob > kmRanUnif(); + } + + void initTempRuns() { // initialize for temp runs + sumTrials = 0; + trialCt = nTrials(); + initTempRunStage = ::KM_HUGE_INT; // not counting stages + } + + bool isTempRunDone() // end of temperature run? + { return stageNo - initTempRunStage >= term.getTempRunLength(); } + + void endTempRun() { // process end of temp run + temperature *= term.getTempReducFact(); // reduce temperature + initTempRunStage = stageNo; + } + + public: + // constructor + KMeans(const ::KMfilterCenters &sol, const ::KMterm &t) + : ::KMlocal(sol, t), save(sol) { } + protected: // overridden methods + virtual void reset() { + ::KMlocal::reset(); // reset base class + save = curr; // save initial centers + areSwapping = true; // start with swapping + initTempRuns(); // initialize sim. annealing + printStageStats(); + } + virtual void beginStage() { // start of stage processing + prevDist = curr.getDist(); // save previous distortion + } + virtual ::KMalg selectMethod() { // select method + return (areSwapping ? SWAP : LLOYD ); + } + virtual void endStage() { // end of stage processing + stageNo++; // increment stage number + curr.getDist(); // get distortion + printStageStats(); + } + virtual bool isRunDone() { // run is done + if (areSwapping) { // swapping? + if (!simAnnealAccept(consecRDL())) { // check SA acceptance + areSwapping = false; // transition to Lloyd's + } + return false; + } + else { // doing Lloyd's algorithm + return consecRDL() <= term.getMinConsecRDL(); // test for convergence + } + } + virtual void endRun() { // end of run processing + if (isTempRunDone()) endTempRun(); // check/process end of temp run + areSwapping = true; // return to swapping + printRunStats(); + } + virtual void tryAcceptance() { // test acceptance + if (accumRDL() > 0) { // improvement over saved? + save = curr; // save this one + if (save.getDist() < best.getDist()) { // new best? + best = save; + } + } + else if (simAnnealAccept(accumRDL())) { // SA says save anyway + save = best; + } + else { // reject, restore old solution + curr = save; + } + } + }; + + + + + } +} + +#endif diff --git a/src/bts/math/munkres.h b/src/bts/math/munkres.h new file mode 100644 index 0000000..2e5e73a --- /dev/null +++ b/src/bts/math/munkres.h @@ -0,0 +1,568 @@ +/* + Copyright 2010 Brain Research Institute/National ICT Australia (NICTA), Melbourne, Australia + + Written by Thomas G Close, 5/05/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + +*/ + + +#ifndef __bts_math_munkres_h__ +#define __bts_math_munkres_h__ + +namespace BTS { + namespace Math { + + template class Munkres; + } +} + +#include + + +#include "math/matrix.h" +#include "math/vector.h" +#include "bts/common.h" + +namespace BTS { + + namespace Math { + + class Index { + + public: + + size_t row, column; + + Index () : row(99999999), column(99999999) {} + Index (size_t row, size_t column) : row(row), column(column) {} + + friend std::ostream& operator<< (std::ostream& stream, const Index& idx) + { + stream << "(" << idx.row << ", " << idx.column << ")"; + + return stream; + } + + }; + + template class Munkres { + + protected: + + const static int UNASSIGNED; + const static int NOT_PROPOSED; + + size_t nrows, ncolumns; + + MR::Math::Matrix Costs; + + + std::set all_rows; + std::set all_cols; + + std::set open_rows; + std::set open_cols; + + std::vector assigned_col; + std::vector assigned_row; + + std::vector proposed_col; + + public: + + + Munkres(size_t nrows, size_t ncolumns) : nrows(nrows), ncolumns(ncolumns), Costs(nrows,ncolumns), assigned_col(nrows), assigned_row(ncolumns), proposed_col(nrows) { + + if (ncolumns < nrows) + throw Exception ("Number of columns (" + str(ncolumns) + ") must exceed number of rows (" + str(nrows) + ")."); + + for (size_t row_i = 0; row_i < nrows; row_i++) all_rows.insert(row_i); + for (size_t col_i = 0; col_i < ncolumns; col_i++) all_cols.insert(col_i); + + } + + ~Munkres() {} + + + void match(MR::Math::Matrix& Costs, std::vector& matched_indices); + + protected: + + void subtract_row_min(); + + T min_open_value(); + + void initial_assignment(); + + bool found_solution(); + + Index new_match(); + + void increment_costs(); + + void add_to_closed_rows(T value); + + void subtract_from_open_columns(T value); + + void reassign_matches(Index new_match); + + void assign(size_t row, size_t col); + + void unassign(size_t row, size_t col); + + void propose(size_t row, size_t col); + + void clear_assignments(); + + void clear_proposals(); + + void open_all_rows(); + + void open_all_columns(); + + public: + + friend std::ostream& operator<< (std::ostream& stream, const Munkres& H) + { + + stream << std::endl << "----------------" << std::endl << "Cost: " << std::endl << H.Costs << std::endl; + + stream << "Assigned cols: "; + for (std::vector::const_iterator it = H.assigned_col.begin(); it != H.assigned_col.end(); it++) + stream << *it << ", "; + stream << std::endl; + + stream << "Assigned rows: "; + for (std::vector::const_iterator it = H.assigned_row.begin(); it != H.assigned_row.end(); it++) + stream << *it << ", "; + stream << std::endl; + + stream << "proposed cols: "; + for (std::vector::const_iterator it = H.proposed_col.begin(); it != H.proposed_col.end(); it++) + stream << *it << ", "; + stream << std::endl; + + stream << "Open rows: "; + for (std::set::const_iterator row_it = H.open_rows.begin(); row_it != H.open_rows.end(); row_it++) + stream << *row_it << ", "; + stream << std::endl; + + std::cout << "Open columns: "; + for (std::set::const_iterator col_it = H.open_cols.begin(); col_it != H.open_cols.end(); col_it++) + stream << *col_it << ", "; + stream << std::endl; + + stream << "-------end------" << std::endl << std::endl; + + return (stream); + } + + + }; + + + template const int Munkres::UNASSIGNED = -1; + template const int Munkres::NOT_PROPOSED = -1; + + + template void Munkres::match(MR::Math::Matrix& Costs, std::vector& matched_indices) { + + + if ((Costs.rows() != nrows) || (Costs.columns() != ncolumns) || (matched_indices.size() != nrows)) + throw Exception ("Size of cost matrix " + str(Costs.rows()) + "x" + str(Costs.columns()) + " or matched_indices vector " + str(matched_indices.size()) + " does not match Munkres object " + str(nrows) + "x" + str(ncolumns) + "."); + + this->Costs = Costs; + + open_rows = all_rows; + open_cols = all_cols; + + clear_assignments(); + + subtract_row_min(); + + initial_assignment(); + + while (!found_solution()) { + + clear_proposals(); + + Index proposed_match = new_match(); + + reassign_matches(proposed_match); + + } + + //Assign assigned cols to output vector reference (and cast to unsigned ints) + for (size_t i = 0; i < nrows; i++) + matched_indices[i] = (size_t)assigned_col[i]; + + } + + + template void Munkres::assign(size_t row, size_t col) { + + + assigned_row[col] = row; + assigned_col[row] = col; + +#ifdef _DEBUG_VERBOSE_ + std::cout << "assigned: " << row << ", " << col << *this << std::endl; +#endif + + } + + + template void Munkres::unassign(size_t row, size_t col) { + + + + assigned_row[col] = UNASSIGNED; + assigned_col[row] = UNASSIGNED; + +#ifdef _DEBUG_VERBOSE_ + std::cout << "unassigned: " << row << ", " << col << *this << std::endl; +#endif + + } + + + template void Munkres::propose(size_t row, size_t col) { + + + proposed_col[row] = col; + +#ifdef _DEBUG_VERBOSE_ + std::cout << "proposed: " << row << ", " << col << *this << std::endl; +#endif + + } + + + template void Munkres::open_all_rows() { + + open_rows = all_rows; + +#ifdef _DEBUG_VERBOSE_ + std::cout << "open all rows: " << *this << std::endl; +#endif + + } + + + template void Munkres::open_all_columns() { + + open_cols = all_cols; + +#ifdef _DEBUG_VERBOSE_ + std::cout << "open all cols: " << *this << std::endl; +#endif + + } + + + template void Munkres::clear_assignments() { + + + fill(assigned_col.begin(), assigned_col.end(), UNASSIGNED); + fill(assigned_row.begin(), assigned_row.end(), UNASSIGNED); + +#ifdef _DEBUG_VERBOSE_ + std::cout << "cleared assignments" << *this << std::endl; +#endif + + } + + + template void Munkres::clear_proposals() { + + fill(proposed_col.begin(), proposed_col.end(), NOT_PROPOSED); + +#ifdef _DEBUG_VERBOSE_ + std::cout << "cleared proposals" << *this << std::endl; +#endif + } + + + template void Munkres::subtract_row_min() { + + + for (size_t row_i = 0; row_i < nrows; row_i++) { + MR::Math::Vector row = Costs.row(row_i); + size_t index; + T min_val = min (row, index); + row -= min_val; + } + +#ifdef _DEBUG_VERBOSE_ + std::cout << "subtracted min cost in row" << *this << std::endl; +#endif + + + } + + + template void Munkres::initial_assignment() { + + std::set::iterator next_row = open_rows.begin(); + + for (std::set::iterator row_it = next_row; row_it != open_rows.end(); row_it = next_row) { + + ++next_row; + + for (std::set::iterator col_it = open_cols.begin(); col_it != open_cols.end(); col_it++) { + + if ( Costs (*row_it, *col_it) == 0 ) { + + assign(*row_it, *col_it); + open_rows.erase(row_it); + open_cols.erase(col_it); + break; + } + } + + } + + open_all_rows(); + open_all_columns(); + +#ifdef _DEBUG_VERBOSE_ + std::cout << "Initial assignment: " << *this << std::endl; +#endif + + + } + + + +// Close each column containing a starred zero. If 'n' columns are closed, the starred zeros describe a complete set of unique +// assignments. + + template bool Munkres::found_solution() { + + size_t num_assigned = 0; + + for (size_t col_i = 0; col_i < ncolumns; col_i++) { + + if (assigned_row[col_i] != UNASSIGNED) { + open_cols.erase(col_i); + num_assigned++; + } + + } + + bool found_sol = false; + if (num_assigned == nrows) + found_sol = true; + +#ifdef _DEBUG_VERBOSE_ + std::cout << "Covered columns: " << *this << std::endl; +#endif + + return found_sol; + + } + + + +// Find a open zero and propose it. If there is no assigned zero in the row containing this proposed zero, reassign the new chain +// of matches. Otherwise, close this row and open the column containing the assigned zero. Continue in this manner until there are +// no open zeros left. + + template Index Munkres::new_match() { + + while (true) { + + std::set::iterator next_row = open_rows.begin(); + + for (std::set::iterator row_it = next_row; row_it != open_rows.end(); row_it = next_row) { + + ++next_row; + + for (std::set::iterator col_it = open_cols.begin(); col_it != open_cols.end(); col_it++) { + + if ( Costs (*row_it, *col_it) == 0) { + + propose(*row_it, *col_it); + + if ( assigned_col[*row_it] == UNASSIGNED ) { + +#ifdef _DEBUG_VERBOSE_ + std::cout << "proposed new zero, (no assignment returning...) (" << *row_it << ", " << *col_it << ")" << *this << std::endl; +#endif + return Index(*row_it, *col_it); + } else { + open_cols.insert(assigned_col[*row_it]); + open_rows.erase(row_it); + +#ifdef _DEBUG_VERBOSE_ + std::cout << "proposed new zero, (found assignment continuing...)" << *this << std::endl; +#endif + + break; + } + + } + + } + + } + + increment_costs(); + + } + + } + + + +// Add the minimum open value to every element of each closed row, and subtract it from every element of each opened column. +// This step uses the smallest opened value in the cost matrix to modify the matrix. It may seem that since the values in the +// cost matrix are being altered, we would lose sight of the original problem. However, we are only changing certain values +/// that have already been tested and found not to be elements of the minimal assignment. Also we are only +// changing the values by an amount equal to the smallest value in the cost matrix, so we will not jump over the optimal +// (i.e. minimal assignment) with this change. + + + template void Munkres::increment_costs() { + + T min_value = min_open_value(); + + add_to_closed_rows(min_value); + + subtract_from_open_columns(min_value); + + + } + + + template T Munkres::min_open_value() { + + + T min_value = INFINITY; + + for (std::set::iterator row_it = open_rows.begin(); row_it != open_rows.end(); row_it++) { + + for (std::set::iterator col_it = open_cols.begin(); col_it != open_cols.end(); col_it++) { + + if ( Costs(*row_it, *col_it) < min_value ) + min_value = Costs(*row_it, *col_it); + + } + + } + +#ifdef _DEBUG_VERBOSE_ + std::cout << "min open value: " << min_value << *this << std::endl; +#endif + + return min_value; + + } + + + template void Munkres::add_to_closed_rows(T value) { + + + for (size_t row_i = 0; row_i < nrows; row_i++) { + + //If row is closed. + if (open_rows.find(row_i) == open_rows.end()) { + + for (size_t col_i = 0; col_i < ncolumns; col_i++) + Costs (row_i, col_i) += value; + + } + + } + + } + + + template void Munkres::subtract_from_open_columns(T value) { + + for (size_t row_i = 0; row_i < nrows; row_i++) { + + for (std::set::iterator col_it = open_cols.begin(); col_it != open_cols.end(); col_it++) { + + Costs( row_i, *col_it) -= value; + + } + } + } + + + +// Construct a chain of alternating proposed and assigned zeros as follows. Let Z0 represent the unclosed proposed zero +// found in Step 4. Let Z1 denote the assigned zero in the column of Z0 (if any). Let Z2 denote the proposed zero in the +// row of Z1 (there will always be one). Continue until the series terminates at a proposed zero that has no assigned zero +// in its column. Unassign each assigned zero of the series, assign each proposed zero of the series, remove all proposals +// and open all rows and columns. This step is very similar to the augmenting location algorithm (for solving the maximal +// matching problem) + + template void Munkres::reassign_matches(Index new_match) { + + std::vector unassign_indices; + std::vector assign_indices; + + assign_indices.push_back(new_match); + + size_t col_i = new_match.column; + + while (assigned_row[col_i] != UNASSIGNED) { + + + Index unassign_idx (assigned_row[col_i], col_i); + Index assign_idx (assigned_row[col_i], proposed_col[assigned_row[col_i]]); + + assign_indices.push_back(assign_idx); + unassign_indices.push_back(unassign_idx); + + col_i = proposed_col[assigned_row[col_i]]; + + } + +#ifdef _DEBUG_VERBOSE_ + std::cout << "reassigning matches" << *this << std::endl; +#endif + + + for (std::vector::iterator it = unassign_indices.begin(); it != unassign_indices.end(); it++) + unassign(it->row, it->column); + + for (std::vector::iterator it = assign_indices.begin(); it != assign_indices.end(); it++) + assign(it->row, it->column); + + assign_indices.clear(); + unassign_indices.clear(); + + open_all_rows(); + open_all_columns(); + + + } + + + + + } + +} + + +#endif + diff --git a/src/bts/math/odr.h b/src/bts/math/odr.h new file mode 100644 index 0000000..3092a4b --- /dev/null +++ b/src/bts/math/odr.h @@ -0,0 +1,110 @@ +/* + Copyright 2010 Brain Research Institute/National ICT Australia (NICTA), Melbourne, Australia + + Written by Thomas G Close, 5/05/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + +*/ + + +#ifndef __bts_math_odr_h__ +#define __bts_math_odr_h__ + +#include "math/matrix.h" +#include "math/vector.h" + +#include "bts/math/svd.h" +#include "bts/coord.h" + + +#include "bts/triple.h" + +//#define _DEBUG_VERBOSE_ + +namespace BTS { + namespace Math { + + class Line { + + public: + Coord centre; + Coord direction; + + friend std::ostream& operator<< (std::ostream& stream, const Line line) + { + std::cout << "centre = " << line.centre << std::endl; + std::cout << "direction = " << line.direction << std::endl; + return (stream); + } + + }; + + // Find the centroid of a set of points. + inline Coord centroid(const std::vector& points) { + + Coord sum(0.0,0.0,0.0); + + for (std::vector::const_iterator it = points.begin(); it != points.end(); it++) + sum += *it; + + sum /= points.size(); + + return sum; + + } + + + // Find the orthogonal-distance regressor line through a set of points. + inline Line odr(const std::vector& points) { + + Line line; + + line.centre = centroid(points); + + MR::Math::Matrix matrix(points.size(), 3); + + for (size_t point_i = 0; point_i < points.size(); point_i++) { + + matrix(point_i,X) = points[point_i][X] - line.centre[X]; + matrix(point_i,Y) = points[point_i][Y] - line.centre[Y]; + matrix(point_i,Z) = points[point_i][Z] - line.centre[Z]; + + } + + + USV usv = svd(matrix); +// +// std::cout << "V = ["; +// for (size_t row_i = 0; row_i < usv.v.rows(); row_i++) { +// for (size_t col_i = 0; col_i < usv.v.columns(); col_i++) +// std::cout << usv.v(row_i,col_i) << " "; +// std::cout << "; "; +// } +// std::cout << "]" << std::endl; + + line.direction.set(usv.v(X,0), usv.v(Y,0), usv.v(Z,0)); +// line.direction.set(usv.v(max_sigma_i,X), usv.v(max_sigma_i,Y), usv.v(max_sigma_i,Z)); + return line; + + } + + + + } +} + +#endif diff --git a/src/bts/math/polygon_intersect.h b/src/bts/math/polygon_intersect.h new file mode 100644 index 0000000..2d342ce --- /dev/null +++ b/src/bts/math/polygon_intersect.h @@ -0,0 +1,132 @@ +#include + +typedef double real; // could be double. +#define C const +#define bigReal 1.E38 // FLT_MAX, DBL_MAX if double above +#include + +typedef struct{real x; real y;} point; + +real inter(point * a, int na, point * b, int nb) { + + typedef struct{point min; point max;} box; + typedef long long hp; + typedef struct{long x; long y;} ipoint; + typedef struct{long mn; long mx;} rng; + typedef struct{ipoint ip; rng rx; rng ry; short in;} vertex; + + vertex ipa[na+1], ipb[nb+1]; + box B = { {bigReal, bigReal}, {-bigReal, -bigReal} }; + + double ascale; + + void range(point * x, int c) { + + while(c--) { + + void bd(real * X, real y){ + *X = *Xy ? *X:y; + } + + bd(&B.min.x, x[c].x); + bu(&B.max.x, x[c].x); + bd(&B.min.y, x[c].y); + bu(&B.max.y, x[c].y); + } + } + + if(na < 3 || nb < 3) + return 0; + + range(a, na); + range(b, nb); + + { const real gamut = 500000000., mid = gamut/2.; + real rngx = B.max.x - B.min.x, sclx = gamut/rngx, + rngy = B.max.y - B.min.y, scly = gamut/rngy; + { void fit(point * x, int cx, vertex * ix, int fudge){ + {int c=cx; while(c--){ + ix[c].ip.x = (long)((x[c].x - B.min.x)*sclx - mid)&~7|fudge|c&1; + ix[c].ip.y = (long)((x[c].y - B.min.y)*scly - mid)&~7|fudge; + }} + ix[0].ip.y += cx&1; + ix[cx] = ix[0]; + {int c=cx; while(c--) { + ix[c].rx = ix[c].ip.x < ix[c+1].ip.x ? + (rng){ix[c].ip.x,ix[c+1].ip.x}:(rng){ix[c+1].ip.x,ix[c].ip.x}; + ix[c].ry = ix[c].ip.y < ix[c+1].ip.y ? + (rng){ix[c].ip.y,ix[c+1].ip.y}:(rng){ix[c+1].ip.y,ix[c].ip.y}; + ix[c].in=0;}}} + fit(a, na, ipa, 0); fit(b, nb, ipb, 2);} + ascale = sclx*scly;} + { hp area(ipoint a, ipoint p, ipoint q) + {return (hp)p.x*q.y - (hp)p.y*q.x + + (hp)a.x*(p.y - q.y) + (hp)a.y*(q.x - p.x);} + hp s = 0; int j, k; + void cntrib(ipoint f, ipoint t, short w) + {s += (hp)w*(t.x-f.x)*(t.y+f.y)/2;} + int ovl(rng p, rng q){return p.mn < q.mx && q.mn < p.mx;} + for(j=0; jip.x + r1*(b->ip.x-a->ip.x), + a->ip.y + r1*(b->ip.y-a->ip.y)}, + b->ip, 1); + cntrib(d->ip, (ipoint){ + c->ip.x + r2*(d->ip.x - c->ip.x), + c->ip.y + r2*(d->ip.y - c->ip.y)}, 1); + ++a->in; --c->in;} + if(o) cross(&ipa[j], &ipa[j+1], &ipb[k], &ipb[k+1], a1, a2, a3, a4); + else cross(&ipb[k], &ipb[k+1], &ipa[j], &ipa[j+1], a3, a4, a1, a2); + }}}} + {void inness(vertex * P, int cP, vertex * Q, int cQ){ + int s=0, c=cQ; ipoint p = P[0].ip; + while(c--)if(Q[c].rx.mn < p.x && p.x < Q[c].rx.mx) + {int sgn = 0 < area(p, Q[c].ip, Q[c+1].ip); + s += sgn != Q[c].ip.x < Q[c+1].ip.x ? 0 : (sgn?-1:1); } + {int j; for(j=0; j. + +*/ + + +#ifndef __bts_math_svd_h__ +#define __bts_math_svd_h__ + + +extern "C" { +#include +} + +#include "math/matrix.h" +#include "math/vector.h" + +#include "bts/common.h" + + + + + + +namespace BTS { + + namespace Math { + + class USV { + + public: + + MR::Math::Matrix u; + MR::Math::Matrix v; + MR::Math::Vector sigma; + + USV(size_t rows, size_t columns) : u(rows, columns), v(columns, columns), sigma(columns) {} + ~USV() {} + + + + }; + + + // Protects M from being copied over by U in the gsl SVD computation. + inline USV svd(const MR::Math::Matrix& matrix) { + + USV usv(matrix.rows(), matrix.columns()); + + usv.u = matrix; + + MR::Math::Vector work(usv.sigma.size()); + + gsl_linalg_SV_decomp (usv.u.gsl(), usv.v.gsl(), usv.sigma.gsl(), work.gsl()); + + return usv; + + } + + + + + + // 'matrix' will be replaced by 'u' in the SVD computation. This saves copying although the input matrix is destroyed. + inline MR::Math::Vector& svd(MR::Math::Matrix& matrix, MR::Math::Matrix& v, MR::Math::Vector& sigma) { + + + + MR::Math::Vector work(sigma.size()); + + gsl_linalg_SV_decomp (matrix.gsl(), v.gsl(), sigma.gsl(), work.gsl()); + + + return sigma; + + + } + + + + } + + +} + +#endif diff --git a/src/bts/mcmc/annealer.cpp b/src/bts/mcmc/annealer.cpp new file mode 100644 index 0000000..1282324 --- /dev/null +++ b/src/bts/mcmc/annealer.cpp @@ -0,0 +1,55 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, 24/01/2011. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + +#include "bts/mcmc/annealer.h" + +namespace BTS { + + namespace MCMC { + + + const double Annealer::START_FRACTION_DEFAULT = 0.01; + + + Annealer::Annealer(size_t num_steps, double start_fraction) { + + t = MR::Math::log(start_fraction); + t_inc = - t / (double)num_steps; + + } + + double Annealer::factor() const { + + return MR::Math::exp(t); + + } + + void Annealer::increment() { + + t += t_inc; + + } + + + } + +} diff --git a/src/bts/mcmc/annealer.h b/src/bts/mcmc/annealer.h new file mode 100644 index 0000000..2a54dda --- /dev/null +++ b/src/bts/mcmc/annealer.h @@ -0,0 +1,61 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, 24/01/2011. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + +#ifndef __bts_mcmc_annealer_h__ +#define __bts_mcmc_annealer_h__ + +#include "bts/common.h" + +namespace BTS { + + namespace MCMC { + + class Annealer { + + //Public static variables, nested classes and typedefs + public: + + const static double START_FRACTION_DEFAULT; + + //Protected member variables + protected: + + double t; + double t_inc; + + //Public member functions + public: + + Annealer(size_t num_steps, double start_fraction); + + double factor() const; + + void increment(); + + + }; + + } + +} + +#endif /* __bts_mcmc_annealer_h__ */ diff --git a/src/bts/mcmc/common.h b/src/bts/mcmc/common.h new file mode 100644 index 0000000..f7ff333 --- /dev/null +++ b/src/bts/mcmc/common.h @@ -0,0 +1,47 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + + +#ifndef __bts_mcmc_common_h__ +#define __bts_mcmc_common_h__ + +namespace BTS { + + namespace MCMC { + + const std::string LOG_PROB_PROP = "log_px"; + const std::string ANNEAL_LOG_PROB_PROP = "anneal_log_px"; + const std::string ACCEPTANCE_RATIO_PROP = "acceptance_ratio"; + const std::string ELAPSED_TIME_PROP = "elapsed_time"; + const std::string H_PROP = "H"; + const std::string PROPOSED_H_PROP = "Proposed H"; + + typedef std::map SampleProperties; + typedef std::vector SamplePropertyHeader; + + } + +} + + +#endif + diff --git a/src/bts/mcmc/hamiltonian.h b/src/bts/mcmc/hamiltonian.h new file mode 100644 index 0000000..9663c0d --- /dev/null +++ b/src/bts/mcmc/hamiltonian.h @@ -0,0 +1,345 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + + +#ifndef __bts_mcmc_hamiltonian_h__ +#define __bts_mcmc_hamiltonian_h__ + +extern "C" { +#include +#include +} + +#include + +#include "progressbar.h" + +#include "bts/fibre/properties/extended.h" +#include "bts/mcmc/common.h" + +#include "bts/common.h" + + + +namespace BTS { + + namespace MCMC { + + namespace Hamiltonian { + + const size_t NUM_SAMPLES_DEFAULT = 20; + const size_t NUM_LEAPFROG_STEPS_DEFAULT = 30; + const size_t BURN_NUM_SAMPLES_DEFAULT = 0; + const size_t BURN_NUM_LEAPFROG_STEPS_DEFAULT = 30; + const size_t BURN_SNR_DEFAULT = 1; + + } + + + template State hamiltonian (State& initial_x, + Likelihood& likelihood, + Prior& prior, + MCMC::Proposal::Momentum& momentum, + const std::string& samples_location, + const std::map& run_properties, + size_t num_samples, + size_t num_leapfrog_steps, + gsl_rng* rand_gen, + bool prior_only = false, + bool save_iterations = false, + bool suppress_print = false ) { + + + std::vector sample_header; + + sample_header.push_back(LOG_PROB_PROP); +// sample_header.push_back(ELAPSED_TIME_PROP); + sample_header.push_back(H_PROP); + sample_header.push_back(PROPOSED_H_PROP); +// sample_header.push_back("total_signal"); +// sample_header.push_back("likelihood"); +// sample_header.push_back("prior"); + + std::vector components_list = prior.list_components(); + + sample_header.insert(sample_header.end(), components_list.begin(), components_list.end()); + + typename State::Writer samples (samples_location, initial_x, sample_header, run_properties); + + typename State::Writer iterations; +// typename State::Writer iteration_gradients; +// typename State::Momentum::Writer iteration_momentums; +// typename State::Writer iteration_prior_gradients; +// typename State::Writer iteration_curv_gradients; +// typename State::Writer iteration_end_gradients; +// typename State::Writer iteration_all_gradients; +// typename State::Writer iteration_likelihood_gradients; + + SamplePropertyHeader iteration_property_header; + + iteration_property_header.push_back("log_px"); + iteration_property_header.push_back("pred_d_log_px"); + iteration_property_header.push_back("act_d_log_px"); + iteration_property_header.push_back("grad_norm2"); + iteration_property_header.push_back("log_kinetic_energy"); + +// iteration_property_header.push_back("curv_pred_d_log_px"); +// iteration_property_header.push_back("curv_act_d_log_px"); +// +// iteration_property_header.push_back("end_pred_d_log_px"); +// iteration_property_header.push_back("end_act_d_log_px"); +// +// iteration_property_header.push_back("all_pred_d_log_px"); +// iteration_property_header.push_back("all_act_d_log_px"); + + + if (save_iterations) { + iterations.create(File::strip_extension(samples_location) + ".iter." + File::extension(samples_location), initial_x, iteration_property_header, run_properties); + +// iteration_gradients.create(File::strip_extension(samples_location) + ".gradient." + File::extension(samples_location), run_properties, std::vector()); +// iteration_momentums.create(File::strip_extension(samples_location) + ".momentum." + File::extension(samples_location), run_properties, std::vector()); +// iteration_likelihood_gradients.create(File::strip_extension(samples_location) + ".like_gradient." + File::extension(samples_location), run_properties, std::vector()); +// iteration_prior_gradients.create(File::strip_extension(samples_location) + ".prior_gradient." + File::extension(samples_location), run_properties, std::vector()); +// +// iteration_curv_gradients.create(File::strip_extension(samples_location) + ".curv_gradient." + File::extension(samples_location), run_properties, std::vector()); +// iteration_end_gradients.create(File::strip_extension(samples_location) + ".end_gradient." + File::extension(samples_location), run_properties, std::vector()); +// iteration_all_gradients.create(File::strip_extension(samples_location) + ".all_gradient." + File::extension(samples_location), run_properties, std::vector()); + } + + + + State x = initial_x; + + State zero = x; + zero.zero(); + + State gradient (zero); + State prior_gradient (zero); + State likelihood_gradient (zero); + +// double curv_log_prob = 0.0; +// double end_log_prob = 0.0; +// double all_log_prob = 0.0; + + State curv_gradient (zero); + State end_gradient (zero); + State all_gradient (zero); + + double start_log_kinetic_energy = NAN; + + double px = prior.log_prob(x, prior_gradient); + + if (!prior_only) + px += likelihood.log_prob(x, likelihood_gradient); + + gradient = prior_gradient + likelihood_gradient; + + //-------------------------// + // Take the MCMC samples // + //-------------------------// + + size_t iteration_count = 0; + + // Initialise the progress bar + MR::ProgressBar progress_bar ("Generating " + str(num_samples) + " Hamiltonian MCMC samples ...", num_samples); + + for (size_t sample_i = 0; sample_i < num_samples; sample_i++) { + + momentum.randomize(); + + double log_kinetic_energy = momentum.log_kinetic_energy(); // momentum.norm2() / 2.0; + + if (!suppress_print) + start_log_kinetic_energy = log_kinetic_energy; + + // NB: Since we want to find maxima not minima the probability of x is inverted when compared from the classical algorithm + // (as implemented in Mackay, D. 2003. Information Theory, Inference and Learning Algorithms, Cambridge University Press, pp388.) + + double H = log_kinetic_energy - px; + + clock_t sample_starttime = clock(); + + State prop_x = x; + State prop_gradient = gradient; + double prop_px = px; + + if (save_iterations) { +// curv_log_prob = prior.component_log_prob("curv_mag", prop_x, curv_gradient); +// end_log_prob = prior.component_log_prob("end_in_sphere", prop_x, end_gradient); +// all_log_prob = prior.component_log_prob("all_in_cube", prop_x, all_gradient); + } + + + // Make 'num_leapfrog_steps' leapfrog steps. + + + for (size_t leapfrog_i = 0; leapfrog_i < num_leapfrog_steps; leapfrog_i++) { + + // NB: Since we want to find maxima not minima the gradient of x is inverted when compared from the classical algorithm. + momentum.half_update_momentum(prop_gradient); // += prop_gradient * (leapfrog_step_size / 2.0); + + if (save_iterations) { + + prop_x.set_extend_prop("pred_d_log_px", str(momentum.predicted_change(prop_gradient))); +// prop_x.set_extend_prop("curv_pred_d_log_px"] = str(momentum.predicted_change(curv_gradient)); +// prop_x.set_extend_prop("end_pred_d_log_px"] = str(momentum.predicted_change(end_gradient)); +// prop_x.set_extend_prop("all_pred_d_log_px"] = str(momentum.predicted_change(all_gradient)); + + } + + // Debug purposes only. + double prev_prop_px = prop_px; + + momentum.update_state(prop_x); //prop_x += leapfrog_step_size * momentum; + + prop_px = prior.log_prob(prop_x, prior_gradient); + + if (!prior_only) + prop_px += likelihood.log_prob(prop_x, likelihood_gradient); + + prop_gradient = prior_gradient + likelihood_gradient; + + // NB: Since we want to find maxima not minima the gradient of x is inverted when compared from the classical algorithm. + momentum.half_update_momentum(prop_gradient); // momentum += prop_gradient * (leapfrog_step_size / 2.0); + + if (save_iterations) { + + prop_x.set_extend_prop("log_px", str(prop_px)); + prop_x.set_extend_prop("act_d_log_px", str(prop_px - prev_prop_px)); + prop_x.set_extend_prop("grad_norm2", str(prop_gradient.norm2())); + prop_x.set_extend_prop("log_kinetic_energy", str(momentum.log_kinetic_energy())); +// iteration_gradients.append(prop_gradient); +// iteration_likelihood_gradients.append(likelihood_gradient); +// iteration_prior_gradients.append(prior_gradient); +// iteration_momentums.append(momentum); + + +// double new_curv_log_prob = prior.component_log_prob("curv_mag", prop_x, curv_gradient); +// double new_all_log_prob = prior.component_log_prob("end_in_sphere", prop_x, all_gradient); +// double new_end_log_prob = prior.component_log_prob("all_in_cube", prop_x, end_gradient); +// +// prop_x.set_extend_prop("curv_act_d_log_px"] = str(new_curv_log_prob - curv_log_prob); +// prop_x.set_extend_prop("end_act_d_log_px"] = str(new_end_log_prob - end_log_prob); +// prop_x.set_extend_prop("all_act_d_log_px"] = str(new_all_log_prob - all_log_prob); +// +// iteration_curv_gradients.append(curv_gradient); +// iteration_end_gradients.append(end_gradient); +// iteration_all_gradients.append(all_gradient); +// +// curv_log_prob = new_curv_log_prob; +// end_log_prob = new_end_log_prob; +// all_log_prob = new_all_log_prob; + + std::map prop_component_values = prior.get_component_values(prop_x); + + for (std::map::iterator comp_it = prop_component_values.begin(); comp_it != prop_component_values.end(); ++comp_it) + prop_x.set_extend_prop(comp_it->first, comp_it->second); + + iterations.append(prop_x); + + } + ++iteration_count; + } + + breakpoint(); + + // Decide whether to accept 'step' (or rather chain of leapfrog steps). + + log_kinetic_energy = momentum.log_kinetic_energy(); //momentum.norm2() / 2.0; + + // NB: Since we want to find maxima not minima the gradient of x is inverted when compared from the classical algorithm. + double prop_H = log_kinetic_energy - prop_px; + + + // NB: Since we want to find maxima not minima the order of this subtraction is reversed. + double dH = prop_H - H; + + + + double elapsed_time = (double)(clock() - sample_starttime) / (double)CLOCKS_PER_SEC; + + + // Print out sample properties. + if (!suppress_print) { + std::cout << std::endl; + std::cout << "Sample: " << sample_i << ", "; +// std::cout << "state: " << x << ", "; + std::cout << "log[px]: " << px << ", "; + std::cout << "Start kinetic energy: " << start_log_kinetic_energy << ", "; + std::cout << "H: " << H << ", "; +// std::cout << "proposed state: " << prop_x << ", "; + std::cout << "Proposed log[px]: " << prop_px << ", "; + std::cout << "Final kinetic energy: " << log_kinetic_energy << ", "; + std::cout << "Proposed H: " << prop_H << ", "; + std::cout << "Elapsed time: " << elapsed_time; + + } + + + // If Hamiltonian decreases (i.e. there is less energy in the system) or the increase is below log[Y] (where Y is a uniformly distributed random variable between 0 and 1), accept the proposer. + + if ((dH < 0) || (log(gsl_ran_flat(rand_gen, 0,1)) < -dH)) { + x = prop_x; + gradient = prop_gradient; + px = prop_px; + if (!suppress_print) + std::cout << ", Accepted!." << std::endl; + } else if (!suppress_print) + std::cout << ", Not accepted." << std::endl; + + // Record sample stats. + + x.set_extend_prop(LOG_PROB_PROP, str(px)); +// x.set_extend_prop(ELAPSED_TIME_PROP] = str(elapsed_time); + x.set_extend_prop(H_PROP, str(H)); + x.set_extend_prop(PROPOSED_H_PROP, str(prop_H)); +// x.set_extend_prop("likelihood"] = str(likelihood_log_px); +// x.set_extend_prop("prior"] = str(prior_px); +// x.set_extend_prop("total_signal"] = str(total_signal); + + std::map component_values = prior.get_component_values(x); + + for (std::map::iterator comp_it =component_values.begin(); comp_it != component_values.end(); ++comp_it) + prop_x.set_extend_prop(comp_it->first, comp_it->second); + + // Save sample. + samples.append(x); + + + progress_bar++; + + } + + + State out_x = x; + + return out_x; + + } + + + + } + +} + +#endif diff --git a/src/bts/mcmc/inline_functions.h b/src/bts/mcmc/inline_functions.h new file mode 100644 index 0000000..28c86fc --- /dev/null +++ b/src/bts/mcmc/inline_functions.h @@ -0,0 +1,46 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, 16/07/2010. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + +#ifndef __bts_mcmc_inline_functions_h__ +#define __bts_mcmc_inline_functions_h__ + + +#ifdef __bts_mcmc_proposal_momentum_h__ + +#include "bts/mcmc/proposal/momentum.cpp.h" + +#endif + +#ifdef __bts_mcmc_proposal_momentum_weighted_h__ + +#include "bts/mcmc/proposal/momentum/weighted.cpp.h" + +#endif + + +#ifdef __bts_mcmc_proposal_momentum_weighted_nonseparable_h__ + +#include "bts/mcmc/proposal/momentum/weighted/non_separable.cpp.h" + +#endif + +#endif /* __bts_proposal_inline_functions_h__ */ diff --git a/src/bts/mcmc/metropolis.h b/src/bts/mcmc/metropolis.h new file mode 100644 index 0000000..dbf5936 --- /dev/null +++ b/src/bts/mcmc/metropolis.h @@ -0,0 +1,295 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + + +#ifndef __bts_mcmc_metropolis_h__ +#define __bts_mcmc_metropolis_h__ + +extern "C" { +#include +#include +} + +#include + +#include "progressbar.h" + +#include "bts/fibre/properties/extended.h" +#include "bts/mcmc/common.h" + +#include "bts/mcmc/annealer.h" + +#include "bts/image/expected/buffer.h" + +#include "bts/common.h" + + + +namespace BTS { + + namespace MCMC { + + + namespace Metropolis { + + const size_t NUM_ITERATIONS_DEFAULT = 1e5; + const size_t SAMPLE_PERIOD_DEFAULT = 1e3; + const size_t BURN_NUM_ITERATIONS_DEFAULT = 0; //1e4; + const size_t BURN_SAMPLE_PERIOD_DEFAULT = 1e2; + const double BURN_SNR_DEFAULT = 20; + const double ANNEAL_FRAC_START_DEFAULT = 1.0; //0.05; + + } + + template State metropolis ( State& initial_x, + Likelihood& likelihood, + Prior& prior, + typename State::Walker& walker, + const std::string& samples_location, + const std::map& run_properties, + size_t num_iterations, + size_t sample_period, + gsl_rng* rand_gen, + double anneal_frac_start = 1.0, + bool prior_only = false, + bool verbose = true, + bool save_images = false) { + + + if (save_images) + likelihood.get_observed_image().save(samples_location + ".obs.mif"); + + std::vector sample_header; + + sample_header.push_back(LOG_PROB_PROP); + sample_header.push_back(ANNEAL_LOG_PROB_PROP); + sample_header.push_back(ACCEPTANCE_RATIO_PROP); + sample_header.push_back(ELAPSED_TIME_PROP); + sample_header.push_back("densities"); + +#ifndef TEST_BED +// sample_header.push_back("total_signal"); +#endif + + sample_header.push_back("likelihood"); + sample_header.push_back("prior"); + + std::vector elem_header; + +// State::append_characteristic_property_keys(elem_header); + + std::vector components_list = prior.list_components(); + + sample_header.insert(sample_header.end(), components_list.begin(), components_list.end()); + + + typename State::Writer samples (samples_location, initial_x, sample_header, elem_header, run_properties); +// typename State::Writer iterations (File::strip_extension(samples_location) + ".iter." + File::extension(samples_location), run_properties, sample_header); + + State x = initial_x; + State prop_x = x; + + double prior_px = prior.log_prob(x); + + + double likelihood_px; + + MCMC::Annealer annealer(num_iterations, anneal_frac_start); + + if (prior_only) + likelihood_px = 0; + else + likelihood_px = likelihood.log_prob(x); + + + double px = likelihood_px * annealer.factor() + prior_px; + + + //-------------------------// + // Take the MCMC samples // + //-------------------------// + + size_t num_samples = num_iterations / sample_period; + + // Initialise the progress bar + MR::ProgressBar progress_bar ("Generating " + str(num_samples) + " Metropolis-Hastings MCMC samples ...", num_samples); + + + for (size_t sample_i = 0; sample_i < num_samples; sample_i++) { + + size_t accepted = 0; + + clock_t sample_starttime = clock(); + + for (size_t iteration_i = 0; iteration_i < sample_period; iteration_i++) { + + // Draw a new sample from the proposal distribution centred on the current state. + walker.step(x, prop_x, 1.0 / MR::Math::sqrt(annealer.factor())); + + //Calculate the unnormalised probability of the stepd state. + double prop_prior_px = prior.log_prob(prop_x); + + double prop_likelihood_px; + + if (prior_only) + prop_likelihood_px = 0; + else + prop_likelihood_px = likelihood.log_prob(prop_x); + + double prop_px = prop_likelihood_px * annealer.factor() + prop_prior_px; + + +// prop_x.set_extend_prop(LOG_PROB_PROP] = str(prop_px); +// prop_x.set_extend_prop("likelihood"] = str(likelihood_px); +// prop_x.set_extend_prop("prior"] = str(prior_px); +// +// std::map component_values = prior.get_component_values(prop_x); +// +// prop_x.properties.insert(component_values.begin(), component_values.end()); +// +// iterations.append(prop_x); + + // Divide the unnormalised probability of the stepd state by the unnormalised probability of the current state + // (remembering that we are dealing with log probability so it is implemented as a subtraction). + double a = prop_px - px; + +// std::cout << "prop_px: " << prop_px << " px: " << px << " a: " << a << std::endl; + +// prop_x.save("/home/tclose/data/tmp.tct"); + + //If the ratio is greater than a uniform value between 0 and 1 then accept the stepd step. + if ( (a > 0) || log(gsl_ran_flat(rand_gen, 0.0, 1.0)) <= a ) { + + // Accept the stepd tractlets + x = prop_x; + px = prop_px; + + //debugging only + likelihood_px = prop_likelihood_px; + prior_px = prop_prior_px; + + accepted++; + + } + + annealer.increment(); + + px = likelihood_px * annealer.factor() + prior_px; + + } + + + // Calculate stats about the current sample + double acceptance_ratio = ((double)accepted)/(double)sample_period; + double elapsed_time = (double)(clock() - sample_starttime) / (double)CLOCKS_PER_SEC; + + + std::vector areas = x[0].cross_sectional_areas(100); + std::vector densities(100); + for (size_t i = 0; i < 100; ++i) + densities[i] = areas[i] / x[0].acs(); + + // Record sample stats. + x.set_extend_prop(ANNEAL_LOG_PROB_PROP,str(likelihood_px + prior_px)); + x.set_extend_prop(LOG_PROB_PROP,str(px)); + x.set_extend_prop(ACCEPTANCE_RATIO_PROP,str(acceptance_ratio)); + x.set_extend_prop(ELAPSED_TIME_PROP,str(elapsed_time)); + x.set_extend_prop("densities", str(densities)); + +#ifndef TEST_BED + //-------- Debugging ---------// +// Image::Expected::Buffer& exp_image = *likelihood.get_expected_image().clone(); +// +// Image::Expected::Buffer& blank_image = *exp_image.clone(); +// Image::Expected::Buffer& dummy_image_gradient = *exp_image.clone(); +// blank_image.zero(); + +// double total_signal = exp_image.sum_strong_difference(blank_image, dummy_image_gradient,0); +#endif + + + State dummy_gradient = x; + + x.set_extend_prop("likelihood", str(likelihood_px)); + x.set_extend_prop("prior", str(prior_px)); + +#ifndef TEST_BED +// x.set_extend_prop("total_signal"] = str(total_signal); +#endif + + std::map component_values = prior.get_component_values(x); + + for (std::map::iterator comp_it = component_values.begin(); comp_it != component_values.end(); ++comp_it) + x.set_extend_prop(comp_it->first, comp_it->second); + +// x.properties.insert(component_values.begin(), component_values.end()); + +#ifndef TEST_BED +// exp_image.save("/home/tclose/data/metropolis/signal/iter_" + str(sample_i) + ".mif"); + +// delete &exp_image; +// delete &blank_image; +// delete &dummy_image_gradient; +#endif + + //-------- End Debugging ------// + + x.calc_characteristic_properties(); + + // Save sample. + samples.append(x); + + + if (save_images) { + likelihood.get_expected_image().save(samples_location + ".exp.mif"); + } + + + // Print out sample properties. + if (verbose) { + std::cout << std::endl; + std::cout << "Iteration: " << (sample_i+1) * sample_period << "/" << num_iterations << ", "; + std::cout << "log[px]: " << px << ", "; + std::cout << "acceptance ratio: " << acceptance_ratio << ", "; + std::cout << "elapsed time: " << elapsed_time; + std::cout << std::endl; + } + + progress_bar++; + + } + + //MR::ProgressBar::done(); + + State x_return(x); + + return x_return; + + } + + + + } + +} + +#endif diff --git a/src/bts/mcmc/naninf_exception.h b/src/bts/mcmc/naninf_exception.h new file mode 100644 index 0000000..f875c3d --- /dev/null +++ b/src/bts/mcmc/naninf_exception.h @@ -0,0 +1,53 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, 24/11/2010. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + +#ifndef __bts_mcmc_naninfexception_h__ +#define __bts_mcmc_naninfexception_h__ + + +namespace BTS { + + namespace MCMC { + + class NanInfException : public MR::Exception { + + public: + + NanInfException() + : MR::Exception ("Nan or Inf values found.") {} + + NanInfException(const NanInfException& e) + : MR::Exception(e) {} + + NanInfException& operator=(const NanInfException& e) + { MR::Exception::operator=(e); return *this; } + + ~NanInfException() {} + + }; + + } + +} + + +#endif /* __bts_mcmc_naninfexception_h__ */ diff --git a/src/bts/mcmc/proposal/distribution.cpp b/src/bts/mcmc/proposal/distribution.cpp new file mode 100644 index 0000000..d088046 --- /dev/null +++ b/src/bts/mcmc/proposal/distribution.cpp @@ -0,0 +1,65 @@ +/* + Copyright 2010 Brain Research Institute/National ICT Australia (NICTA), Melbourne, Australia + + Written by Thomas G Close, 5/05/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + +*/ + +#include "bts/mcmc/proposal/distribution.h" +#include "bts/mcmc/proposal/distribution/gaussian.h" +#include "bts/common.h" + +#include "bts/mcmc/inline_functions.h" + +namespace BTS { + + namespace MCMC { + + namespace Proposal { + + const char* Distribution::TYPE_DEFAULT = "gaussian"; + + + Distribution* Distribution::factory(const std::string& type, gsl_rng* rand_gen) { + + Proposal::Distribution* distribution; + + if (type == "gaussian") + + distribution = new Proposal::Distribution::Gaussian (rand_gen); + + else + throw Exception ("Unrecognised proposal type '" + type + "' passed to option '-prop_distr_type'."); + + return distribution; + + } + +// const double PROPOSAL_DEGREE_ARRAY_DEFAULT[] = {1.0, 1.5, 0.2, 0.01, 0.002, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0}; +// const std::vector Distribution::DEGREE_DEFAULTS (PROPOSAL_DEGREE_ARRAY_DEFAULT, &(PROPOSAL_DEGREE_ARRAY_DEFAULT[12])); +// +// +// const double PROPOSAL_SECONDARY_DEGREE_ARRAY_DEFAULT[] = {0.2, 0.1, 0.1, 0.01, 0.002, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0}; +// const std::vector Distribution::SECONDARY_DEGREE_DEFAULTS (PROPOSAL_SECONDARY_DEGREE_ARRAY_DEFAULT, &(PROPOSAL_SECONDARY_DEGREE_ARRAY_DEFAULT[12])); + + + } + + } + +} diff --git a/src/bts/mcmc/proposal/distribution.h b/src/bts/mcmc/proposal/distribution.h new file mode 100644 index 0000000..d8d02e8 --- /dev/null +++ b/src/bts/mcmc/proposal/distribution.h @@ -0,0 +1,146 @@ +/* + Copyright 2010 Brain Research Institute/National ICT Australia (NICTA), Melbourne, Australia + + Written by Thomas G Close, 5/05/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + +*/ + + +#ifndef __bts_mcmc_proposal_distribution_h__ +#define __bts_mcmc_proposal_distribution_h__ + + +#define PROPOSAL_DISTRIBUTION_PARAMETERS \ + Option ("prop_distr_type", "The 'Proposal::Distribution' object used to calculate the prior probability.") \ + + Argument ("prop_distr_type", "").type_text(MCMC::Proposal::Distribution::TYPE_DEFAULT) \ +\ + + +//Loads the 'proposal' parameters into variables +#define SET_PROPOSAL_DISTRIBUTION_PARAMETERS \ + std::string prop_distr_type = MCMC::Proposal::Distribution::TYPE_DEFAULT; \ +\ + Options prop_opt = get_options("prop_distr_type"); \ + if (prop_opt.size()) \ + prop_distr_type = prop_opt[0][0].c_str(); \ +\ + + +//Adds the 'proposal distribution' parameters to the properties to be saved with the data. +#define ADD_PROPOSAL_DISTRIBUTION_PROPERTIES(properties) \ + properties["prop_distr_type"] = prop_distr_type; \ + + + +#include +#include + +namespace BTS { + + namespace MCMC { + + namespace Proposal { + + class Distribution; + + } + + } + +} + + +extern "C" { +#include +#include +} + +namespace BTS { + + namespace MCMC { + + namespace Proposal { + + class Distribution { + + public: + + class Gaussian; + class HeavyTailed; + + public: + + const static double STEP_SIZE_DEFAULT; + const static double SHEER_SCALE_DEFAULT; + const static double SPREAD_SCALE_DEFAULT; + const static double BASEWIDTH_SCALE_DEFAULT; + const static double ENDPOINT_SCALE_DEFAULT; + const static double MIDPOINT_SCALE_DEFAULT; + const static double INTENSITY_STEP_SIZE_DEFAULT; + const static double BASE_INTENSITY_STEP_SIZE_DEFAULT; + +// const static std::vector DEGREE_DEFAULTS; +// const static std::vector SECONDARY_DEGREE_DEFAULTS; + + + //Public static constants + public: + + const static char* TYPE_DEFAULT; + + protected: + + gsl_rng* rand_gen; + + + //Public static methods + public: + + static Distribution* factory(const std::string& type, gsl_rng* rand_gen); + + public: + + virtual double sample(double current_state, double scale) = 0; + + virtual Distribution* clone() const = 0; + + virtual ~Distribution() {} + + protected: + + Distribution(gsl_rng* rand_gen) + : rand_gen(rand_gen) {} + + Distribution (const Distribution& g) + : rand_gen(g.rand_gen) {} + + Distribution& operator=(const Distribution& g) + { rand_gen = g.rand_gen; return *this; } + + + }; + + + } + + } + +} + + +#endif diff --git a/src/bts/mcmc/proposal/distribution/gaussian.cpp b/src/bts/mcmc/proposal/distribution/gaussian.cpp new file mode 100644 index 0000000..b44943a --- /dev/null +++ b/src/bts/mcmc/proposal/distribution/gaussian.cpp @@ -0,0 +1,50 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + +extern "C" { +#include +#include +} + + +#include "bts/mcmc/proposal/distribution/gaussian.h" + + +#include "bts/mcmc/inline_functions.h" + +namespace BTS { + + namespace MCMC { + + namespace Proposal { + + double Distribution::Gaussian::sample(double current_state, double scale) { + + return current_state + gsl_ran_gaussian(rand_gen, scale); + + } + + } + + } + +} diff --git a/src/bts/mcmc/proposal/distribution/gaussian.h b/src/bts/mcmc/proposal/distribution/gaussian.h new file mode 100644 index 0000000..fe7aca3 --- /dev/null +++ b/src/bts/mcmc/proposal/distribution/gaussian.h @@ -0,0 +1,72 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + + +#ifndef __bts_mcmc_proposal_distribution_gaussian_h__ +#define __bts_mcmc_proposal_distribution_gaussian_h__ + + +#include "bts/mcmc/proposal/distribution.h" + + +namespace BTS { + + namespace MCMC { + + namespace Proposal { + + class Distribution::Gaussian : public Distribution { + + public: + + Gaussian (gsl_rng* rand_gen) + : Distribution(rand_gen) {} + + Gaussian (const Gaussian& g) + : Distribution(g) {} + + Gaussian& operator=(const Gaussian& g) + { Distribution::operator=(g); return *this; } + + Gaussian* clone() const + { return new Gaussian(*this); } + + double sample(double current_state, double scale); + + + }; + + } + + } + +} + + + + + + + + + +#endif diff --git a/src/bts/mcmc/proposal/momentum.cpp b/src/bts/mcmc/proposal/momentum.cpp new file mode 100644 index 0000000..a873aca --- /dev/null +++ b/src/bts/mcmc/proposal/momentum.cpp @@ -0,0 +1,114 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, Jul 20, 2010. + + This file is part of MRtrix. + + MRtrix 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 size() of the License, or + (at your option) any later version. + + MRtrix 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 MRtrix. If not, see . + +*/ + +#ifndef __bts_proposal_momentum_cpp_h__ +#define __bts_proposal_momentum_cpp_h__ + +#include "bts/mcmc/proposal/momentum.h" +#include "math/vector.h" + + + +namespace BTS { + + namespace MCMC { + + namespace Proposal { + + const double Momentum::STEP_SCALE_DEFAULT = 0.05; + const std::string Momentum::STEP_LOCATION_DEFAULT = "/home/tclose/data/mcmc/hamiltonian/params/momentum/scaling.sta"; + + + void Momentum::set( Distribution* const proposal_distribution, + MR::Math::Vector relative_step) { + + momen = relative_step; + momen *= NAN; + step = relative_step; + + if (prop_distr) + delete prop_distr; + + this->prop_distr = proposal_distribution->clone(); + + } + + void Momentum::randomize() { + + for (size_t elem_i = 0; elem_i < size(); elem_i++) + momen[elem_i] = prop_distr->sample(0.0, 1.0); + + } + + + void Momentum::half_update_momentum(const MR::Math::Vector& gradient, double time_direction) { + + assert((time_direction == -1.0) || (time_direction == 1.0)); + + for (size_t elem_i = 0; elem_i < size(); elem_i++) + momen[elem_i] += time_direction * gradient[elem_i] * step[elem_i] / 2.0; + + } + + + + void Momentum::update_state(MR::Math::Vector& state, double time_direction) const { + + assert((time_direction == -1.0) || (time_direction == 1.0)); + + for (size_t elem_i = 0; elem_i < size(); elem_i++) + state[elem_i] += time_direction * momen[elem_i] * step[elem_i]; + + } + + + + double Momentum::predicted_change(const MR::Math::Vector& gradient, double time_direction) const { + + assert((time_direction == -1.0) || (time_direction == 1.0)); + + double pred_change = 0.0; + + for (size_t elem_i = 0; elem_i < size(); elem_i++) + pred_change += time_direction * momen[elem_i] * gradient[elem_i] * step[elem_i]; + + return pred_change; + + } + + std::ostream& operator<<(std::ostream& stream, const Momentum& momen) { + + stream << "Momentum: " << momen.momen << std::endl; + stream << "Step sizes: " << momen.step << std::endl; + + return stream; + + } + + + } + + } + +} + +#endif /* __bts_proposal_momentum_cpp_h__ */ diff --git a/src/bts/mcmc/proposal/momentum.cpp.h b/src/bts/mcmc/proposal/momentum.cpp.h new file mode 100644 index 0000000..c9ee284 --- /dev/null +++ b/src/bts/mcmc/proposal/momentum.cpp.h @@ -0,0 +1,106 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, 15/09/2010. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + +#ifndef __bts_mcmc_proposal_momentum_cpp_h__ +#define __bts_mcmc_proposal_momentum_cpp_h__ + +namespace BTS { + + namespace MCMC { + + namespace Proposal { + + template Momentum Momentum::factory(const T& state, + double step_scale, + const std::string& step_location, + const std::string& weight_location, + MCMC::Proposal::Distribution* const proposal_distribution) { + + + Momentum momentum; + + T step; + + if (step_location.size()) { + + T loaded_step; + + loaded_step.load(step_location); + + if (loaded_step.size() == 1) + step.resize(state.size(), loaded_step[0]); + else if (loaded_step.size() == state.size()) + step = loaded_step; + else + throw Exception ("Size of loaded step (" + str(loaded_step.size()) + ") from file '" + step_location + "' is not singular and does not match that of state (" + str(state.size()) + ")."); + + step *= step_scale; + + } else + step.resize(state.size(),step_scale); + + MR::Math::Vector& step_vector = step; + + //TODO: Reinstate this and create fixed weighted class. +// if (weight_location.size()) { +// +// size_t state_vector_size = state.vsize(); +// MR::Math::Matrix weights(state_vector_size, state_vector_size); +// weights = 0.0; +// +// MR::Math::Matrix loaded_weights (weight_location); +// +// size_t loaded_weights_size = loaded_weights.rows(); +// +// if (loaded_weights_size != loaded_weights.columns()) +// throw Exception ("Loaded matrix is not square (" + str(loaded_weights_size) + " x " + str(loaded_weights.columns()) + ")."); +// +// if (loaded_weights_size == state_vector_size) +// weights = loaded_weights; +// +// else if (!(state_vector_size % loaded_weights_size)) { +// +// for (size_t block_i = 0; block_i < state_vector_size; block_i += loaded_weights_size) +// weights.sub(block_i, block_i+loaded_weights_size, block_i, block_i+loaded_weights_size) = loaded_weights; +// +// } else +// throw Exception ("Loaded weights size (" + str(loaded_weights_size) + ") does not divide evenly into state vector size (" + str(state_vector_size) + ")."); +// +// +// momentum = Momentum::Weighted(proposal_distribution, step_vector, weights); +// } else + momentum = Momentum (proposal_distribution, step_vector); + + VAR(momentum); + + return momentum; + + } + + + } + + } + +} + +#endif /* __bts_mcmc_proposal_momentum_cpp_h__ */ diff --git a/src/bts/mcmc/proposal/momentum.h b/src/bts/mcmc/proposal/momentum.h new file mode 100644 index 0000000..9d43036 --- /dev/null +++ b/src/bts/mcmc/proposal/momentum.h @@ -0,0 +1,215 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, Jun 28, 2010. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + +#ifndef __bts_mcmc_proposal_momentum_h__ +#define __bts_mcmc_proposal_momentum_h__ + + +namespace BTS { + + namespace MCMC { + + namespace Proposal { + + class Momentum; + + } + + } + +} + + +#include "math/vector.h" +#include "bts/common.h" + + + +#define PROPOSAL_MOMENTUM_PARAMETERS \ + Option ("momen_step_scale", "The overall scale of the momen step sizes.") \ + + Argument ("momen_step_scale", "").type_float(SMALL_FLOAT, MCMC::Proposal::Momentum::STEP_SCALE_DEFAULT, LARGE_FLOAT), \ +\ + Option ("momen_step_location", "The relative scales of the momen step sizes.") \ + + Argument ("momen_step_location", "").type_text(), \ + \ + Option ("momen_weight_location", "The weight matrix used for the update of the momen.") \ + + Argument ("momen_weight_location", "").type_text() \ + +//Loads the 'proposal' parameters into variables +#define SET_PROPOSAL_MOMENTUM_PARAMETERS(state_location) \ + double momen_step_scale; \ + std::string momen_step_location; \ + std::string momen_weight_location; \ + if (File::has_extension(state_location)) { \ + momen_step_scale = Fibre::Strand::Set::Momentum::STEP_SCALE_DEFAULT; \ + momen_step_location = Fibre::Strand::Set::Momentum::STEP_LOCATION_DEFAULT; \ + } else if (File::has_extension(state_location)) { \ + momen_step_scale = Fibre::Tractlet::Set::Momentum::STEP_SCALE_DEFAULT; \ + momen_step_location = Fibre::Tractlet::Set::Momentum::STEP_LOCATION_DEFAULT; \ + } else { \ + momen_step_scale = MCMC::Proposal::Momentum::STEP_SCALE_DEFAULT; \ + momen_step_location = MCMC::Proposal::Momentum::STEP_LOCATION_DEFAULT; \ + } \ +\ + opt = get_options("momen_step_scale"); \ + if (opt.size()) \ + momen_step_scale = opt[0][0]; \ +\ + opt = get_options("momen_step_location"); \ + if (opt.size()) \ + momen_step_location = opt[0][0].c_str(); \ +\ + opt = get_options("momen_weight_location"); \ + if (opt.size()) \ + momen_weight_location = opt[0][0].c_str(); \ + +//Adds the 'prior' parameters to the momerties to be saved with the data. +#define ADD_PROPOSAL_MOMENTUM_PROPERTIES(properties) \ +\ + properties["momen_step_scale"] = str(momen_step_scale); \ + properties["momen_step_location"] = momen_step_location; \ + properties["momen_step"] = Fibre::Base::Object::load_matlab_str(momen_step_location, momen_step_scale); \ + if (momen_weight_location.size()) { \ + properties["momen_weight_location"] = momen_weight_location; \ + properties["momen_weight"] = Fibre::Base::Object::load_matlab_str(momen_weight_location,1.0); \ + } \ + +#include "bts/mcmc/proposal/distribution.h" +#include "bts/mcmc/state.h" + +namespace BTS { + + namespace MCMC { + + namespace Proposal { + + class Momentum { + + //Nested Classes and Typedefs + public: + + class Weighted; + + //Public static constants + public: + + static const double STEP_SCALE_DEFAULT; + static const std::string STEP_LOCATION_DEFAULT; + + //Public static functions. + public: + + template static Momentum factory( const T& state, + double step_scale, + const std::string& step_location, + const std::string& weight_location, + MCMC::Proposal::Distribution* const proposal_distribution); + + //Member variables + protected: + + MR::Math::Vector momen; + MR::Math::Vector step; + + Distribution* prop_distr; + + //Member functions + public: + + + Momentum(Distribution* const prop_distr = 0) : prop_distr(prop_distr) {} + + + Momentum(Distribution* const proposal_distribution, + const MR::Math::Vector& relative_step) + : prop_distr(0) + { set(proposal_distribution, relative_step); } + + ~Momentum() + { if (prop_distr) delete prop_distr; } + + Momentum(const Momentum& m) + : momen(m.momen), step(m.step) { if (m.prop_distr) delete prop_distr; prop_distr = m.prop_distr->clone(); } + + Momentum& operator=(const Momentum& m) + { momen = m.momen, step = m.step; if (m.prop_distr) delete prop_distr; prop_distr = m.prop_distr->clone(); return *this; } + + + void set(Distribution* const proposal_distribution, MR::Math::Vector relative_step); + + + size_t size() const + { return momen.size(); } + + double log_kinetic_energy() const + { return norm2(momen) / 2.0; } + + const MR::Math::Vector& momentum() const + { return momen; } + + const MR::Math::Vector& step_sizes() const + { return step; } + + void randomize(); + + + virtual void half_update_momentum(const MR::Math::Vector& gradient, double time_direction = 1.0); + + + virtual void update_state(MR::Math::Vector& state, double time_direction = 1.0) const; + + + template void half_update_momentum(const T& gradient, double time_direction = 1.0) + { half_update_momentum(gradient, time_direction); } + + + template void update_state(T& state, double time_direction = 1.0) const + { MR::Math::Vector& state_vector = state; update_state(state_vector, time_direction); } + + + void half_update_momentum(const MCMC::State& gradient, double time_direction = 1.0) + { half_update_momentum((const MR::Math::Vector&)gradient, time_direction); } + + + void update_state(MCMC::State& state, double time_direction = 1.0) const + { update_state((MR::Math::Vector&)state, time_direction);} + + //For debugging purposes. + double predicted_change(const MR::Math::Vector& gradient, double time_direction = 1.0) const; + + template double predicted_change(const T& gradient, double time_direction = 1.0) const + { return predicted_change(gradient, time_direction); } + + + friend std::ostream& operator<<(std::ostream& stream, const Momentum& momen); + + }; + + + std::ostream& operator<<(std::ostream& stream, const Momentum& momen); + + } + } +} + + +#endif /* __bts_proposal_momentum_h__ */ diff --git a/src/bts/mcmc/proposal/momentum/weighted.cpp b/src/bts/mcmc/proposal/momentum/weighted.cpp new file mode 100644 index 0000000..367d11e --- /dev/null +++ b/src/bts/mcmc/proposal/momentum/weighted.cpp @@ -0,0 +1,122 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, 15/09/2010. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + +#include "bts/mcmc/proposal/momentum/weighted.h" +#include "math/cholesky.h" + +namespace BTS { + + namespace MCMC { + + namespace Proposal { + + + Momentum::Weighted::Weighted(Distribution* const proposal_distribution, + const MR::Math::Vector& relative_step_sizes) + : Momentum(proposal_distribution, relative_step_sizes), + momen_step(relative_step_sizes.size()) {} + + + + + //!The kinetic energy is the weighted inner product of the momentum, normalized by 1/2 * log(2*pi)^D |weights|. + double Momentum::Weighted::log_kinetic_energy(const MR::Math::Matrix& weights_chol) const { + + MR::Math::Vector weights_momen(size()); + + MR::Math::Cholesky::solve(weights_momen, weights_chol, momen); + double energy = MR::Math::dot(weights_momen, momen) / 2.0; + + energy += log_normalization(MR::Math::Cholesky::det_from_decomp(weights_chol)); + + return energy; + + } + + + + //!The kinetic energy is the weighted inner product of the momentum, normalized by 1/2 * log(2*pi)^D |weights|. + double Momentum::Weighted::log_normalization(double inv_weights_determinant) const { + + return 0.5 * (LOG_2 + LOG_PI * size() + MR::Math::log(inv_weights_determinant)); + + } + + //!At the start of each leapfrog chain the momentum is randomized to have the a normal distribution with covariance matrix equal to the weighting matrix. + void Momentum::Weighted::randomize(const MR::Math::Matrix& cholesky) { + + MR::Math::Vector random_vec(size()); + + for (size_t elem_i = 0; elem_i < size(); ++elem_i) + random_vec[elem_i] = prop_distr->sample(0.0, 1.0); + + +// MR::Math::Vector random_vec("/home/tclose/data/mcmc/state/random_vec.txt"); + + MR::Math::Matrix lower_cholesky = cholesky; + + for (size_t elem_i = 0; elem_i < size(); ++elem_i) + for (size_t elem_i2 = elem_i+1; elem_i2 < size(); ++elem_i2) + lower_cholesky(elem_i, elem_i2) = 0.0; + + +// MR::Math::mult(momen, CblasNoTrans, CblasLower, cholesky, random_vec); + + MR::Math::mult(momen, lower_cholesky, random_vec); + + + + } + + + void Momentum::Weighted::update_state(MR::Math::Vector& state, const MR::Math::Matrix& weights_chol, double time_direction) const { + + + MR::Math::Vector working(state.size()); + MR::Math::Cholesky::solve(working, weights_chol, momen); + + for (size_t elem_i = 0; elem_i < size(); elem_i++) + state[elem_i] += time_direction * working[elem_i] * step[elem_i]; + + + } + + double Momentum::Weighted::predicted_change(const MR::Math::Vector& gradient, const MR::Math::Matrix& weights_chol, double time_direction) const { + + double pred_change = 0.0; + + MR::Math::Vector working(gradient.size()); + MR::Math::Cholesky::solve(working, weights_chol, momen); + + for (size_t elem_i = 0; elem_i < size(); elem_i++) + pred_change += time_direction * working[elem_i] * gradient[elem_i] * step[elem_i]; + + return pred_change; + + } + + + } + + } + +} diff --git a/src/bts/mcmc/proposal/momentum/weighted.cpp.h b/src/bts/mcmc/proposal/momentum/weighted.cpp.h new file mode 100644 index 0000000..5811d98 --- /dev/null +++ b/src/bts/mcmc/proposal/momentum/weighted.cpp.h @@ -0,0 +1,81 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, 22/11/2010. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + +#ifndef __bts_mcmc_proposal_momentum_weighted_cpp_h__ +#define __bts_mcmc_proposal_momentum_weighted_cpp_h__ + +namespace BTS { + + namespace MCMC { + + namespace Proposal { + + + template Momentum::Weighted Momentum::Weighted::factory(const T& state, + double step_scale, + const std::string& step_location, + MCMC::Proposal::Distribution* const proposal_distribution) { + + + Momentum::Weighted momentum; + + T step; + + if (step_location.size()) { + + T loaded_step; + + loaded_step.load(step_location); + + if (loaded_step.size() == 1) + step.resize(state.size(), loaded_step[0]); + else if (loaded_step.size() == state.size()) + step = loaded_step; + else + throw Exception ("Size of loaded step (" + str(loaded_step.size()) + ") from file '" + step_location + "' is not singular and does not match that of state (" + str(state.size()) + ")."); + + step *= step_scale; + + } else + step.resize(state.size(),step_scale); + +// step.base_intensity = 0.0; +// +// //TODO: Remove from production version +// for (size_t i = 0; i < step.size(); ++i) +// step[i].acs = 0.0; + + MR::Math::Vector& step_vector = step; + + return Momentum::Weighted (proposal_distribution, step_vector); + + } + + + + } + + } + +} + +#endif /* __bts_mcmc_proposal_momentum_weighted_cpp_h__ */ diff --git a/src/bts/mcmc/proposal/momentum/weighted.h b/src/bts/mcmc/proposal/momentum/weighted.h new file mode 100644 index 0000000..dc8b9c0 --- /dev/null +++ b/src/bts/mcmc/proposal/momentum/weighted.h @@ -0,0 +1,110 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, 15/09/2010. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + +#ifndef __bts_mcmc_proposal_momentum_weighted_h__ +#define __bts_mcmc_proposal_momentum_weighted_h__ + +#include "bts/mcmc/proposal/momentum.h" + +namespace BTS { + + namespace MCMC { + + namespace Proposal { + + class Momentum::Weighted : public Momentum { + + //Public nested classes + public: + + class NonSeparable; + + public: + + + template static Weighted factory(const T& state, + double step_scale, + const std::string& step_location, + MCMC::Proposal::Distribution* const proposal_distribution); + + protected: + + MR::Math::Vector momen_step; + + //Public static functions + public: + + //Public member functions + public: + + Weighted(Distribution* const prop_distr = 0) : Momentum(prop_distr) {} + + + Weighted(Distribution* const proposal_distribution, const MR::Math::Vector& relative_step_sizes); + + + ~Weighted() {} + + + Weighted(const Weighted& W) + : Momentum(W), momen_step(W.size()) {} + + + Weighted& operator=(const Weighted& W) + { Momentum::operator=(W); momen_step.resize(W.size()); return *this; } + + + virtual void update_state(MR::Math::Vector& state, const MR::Math::Matrix& weights_chol, double time_direction = 1.0) const; + + + template void update_state(T& state, const MR::Math::Matrix& weights_chol, double time_direction = 1.0) const + { MR::Math::Vector& state_vector = state; update_state(state_vector, weights_chol, time_direction); } + + + void randomize(const MR::Math::Matrix& cholesky); + + + double log_kinetic_energy(const MR::Math::Matrix& cholesky) const; + + //For debugging purposes. + double predicted_change(const MR::Math::Vector& gradient, const MR::Math::Matrix& weights_chol, double time_direction = 1.0) const; + + + template double predicted_change(const T& gradient, const MR::Math::Matrix& weights_chol, double time_direction = 1.0) const + { return predicted_change(gradient, weights_chol, time_direction); } + + protected: + + double log_normalization(double determinant) const; + + + + + }; + + } + + } + +} + +#endif /* __bts_mcmc_proposal_momentum_weighted_h__ */ diff --git a/src/bts/mcmc/proposal/momentum/weighted/non_separable.cpp b/src/bts/mcmc/proposal/momentum/weighted/non_separable.cpp new file mode 100644 index 0000000..8ce397e --- /dev/null +++ b/src/bts/mcmc/proposal/momentum/weighted/non_separable.cpp @@ -0,0 +1,71 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, Sep 27, 2010. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + +#include "math/matrix.h" +#include "math/cholesky.h" +#include "bts/mcmc/naninf_exception.h" + +#include "bts/math/common.h" + +#include "bts/mcmc/proposal/momentum/weighted/non_separable.h" + +namespace BTS { + + namespace MCMC { + + namespace Proposal { + + +// double Momentum::Weighted::NonSeparable::log_kinetic_energy(const MR::Math::Matrix& weights_chol) const { +// +// MR::Math::Vector weights_momen(size()); +// +// MR::Math::Cholesky::solve(weights_momen, weights_chol, momen); +// double energy = MR::Math::dot(weights_momen, momen) / 2.0; +// +// energy += log_normalization(MR::Math::Cholesky::det_from_decomp(weights_chol)); +// +// return energy; +// +// } + + + double Momentum::Weighted::NonSeparable::predicted_change(const MR::Math::Vector& gradient, const MR::Math::Matrix& fisher_chol, double time_direction) const { + + double pred_change = 0.0; + + MR::Math::Vector working(gradient.size()); + + MR::Math::Cholesky::solve(working, fisher_chol, momen); + + for (size_t elem_i = 0; elem_i < size(); elem_i++) + pred_change += working[elem_i] * gradient[elem_i] * step[elem_i]; + + return pred_change * time_direction; + + } + + } + + } + +} diff --git a/src/bts/mcmc/proposal/momentum/weighted/non_separable.cpp.h b/src/bts/mcmc/proposal/momentum/weighted/non_separable.cpp.h new file mode 100644 index 0000000..2d4cfc9 --- /dev/null +++ b/src/bts/mcmc/proposal/momentum/weighted/non_separable.cpp.h @@ -0,0 +1,82 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, Sep 28, 2010. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + +#ifndef __bts_mcmc_proposal_momentum_weighted_nonseparable_cpp_h__ +#define __bts_mcmc_proposal_momentum_weighted_nonseparable_cpp_h__ + + +namespace BTS { + + namespace MCMC { + + namespace Proposal { + + template Momentum::Weighted::NonSeparable Momentum::Weighted::NonSeparable::factory(const T& state, + double step_scale, + const std::string& step_location, + MCMC::Proposal::Distribution* const proposal_distribution, + size_t num_newton_steps) { + + + Momentum::Weighted::NonSeparable momentum; + + T step; + + if (step_location.size()) { + + T loaded_step; + + loaded_step.load(step_location); + + if (loaded_step.size() == 1) + step.resize(state.size(), loaded_step[0]); + else if (loaded_step.size() == state.size()) + step = loaded_step; + else + throw Exception ("Size of loaded step (" + str(loaded_step.size()) + ") from file '" + step_location + "' is not singular and does not match that of state (" + str(state.size()) + ")."); + + step *= step_scale; + + } else + step.resize(state.size(),step_scale); + +// step.base_intensity = 0.0; +// +// //TODO: Remove from production version +// for (size_t i = 0; i < step.size(); ++i) +// step[i].acs = 0.0; + + MR::Math::Vector& step_vector = step; + + return Momentum::Weighted::NonSeparable (proposal_distribution, step_vector, num_newton_steps); + + } + + + } + + } + +} + + +#endif /* __bts_mcmc_proposal_momentum_weighted_non_separable_cpp_h__ */ diff --git a/src/bts/mcmc/proposal/momentum/weighted/non_separable.h b/src/bts/mcmc/proposal/momentum/weighted/non_separable.h new file mode 100644 index 0000000..08f1c26 --- /dev/null +++ b/src/bts/mcmc/proposal/momentum/weighted/non_separable.h @@ -0,0 +1,174 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, Sep 27, 2010. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + +#ifndef __bts_mcmc_proposal_momentum_weighted_nonseparable_h__ +#define __bts_mcmc_proposal_momentum_weighted_nonseparable_h__ + +#include "bts/math/common.h" +#include "bts/mcmc/naninf_exception.h" +#include "bts/mcmc/proposal/momentum/weighted.h" + +namespace BTS { + + namespace MCMC { + + namespace Proposal { + + class Momentum::Weighted::NonSeparable : public Momentum::Weighted { + + //Public static variables, nested classes and typedefs + public: + + //Protected member variables + protected: + + //Working matrices and vectors. + MR::Math::Vector tmp_momen; + MR::Math::Vector working1; + MR::Math::Vector working2; + std::vector< MR::Math::Matrix > Winv_dWdx; + std::vector trace_Winv_dWdx; + + + //Public static functions + public: + + + template static NonSeparable factory(const T& state, + double step_scale, + const std::string& step_location, + MCMC::Proposal::Distribution* const proposal_distribution, + size_t num_newton_steps); + + //Public member functions + public: + + + NonSeparable(Distribution* const prop_distr = 0) : Weighted(prop_distr) {} + + NonSeparable(Distribution* const proposal_distribution, const MR::Math::Vector& step_sizes, size_t num_newton_steps) + : Weighted(proposal_distribution, step_sizes), + tmp_momen(step_sizes.size()), + working1(step_sizes.size()), + working2(step_sizes.size()), + Winv_dWdx(step_sizes.size(), MR::Math::Matrix(step_sizes.size(),step_sizes.size())), + trace_Winv_dWdx(step_sizes.size()) {} + + + virtual ~NonSeparable() {} + + + NonSeparable(const NonSeparable& NS) + : Weighted(NS), + tmp_momen(NS.tmp_momen), + working1(NS.working1), + working2(NS.working2), + Winv_dWdx(NS.Winv_dWdx), + trace_Winv_dWdx(NS.trace_Winv_dWdx) {} + + + NonSeparable& operator=(const NonSeparable& NS) { + + Weighted::operator=(NS); + tmp_momen = NS.tmp_momen; + working1 = NS.working1; + working2 = NS.working2; + Winv_dWdx = NS.Winv_dWdx; + trace_Winv_dWdx = NS.trace_Winv_dWdx; + + return *this; + } + + void randomize(const MR::Math::Matrix& weights_chol) + { Momentum::Weighted::randomize(weights_chol); } + +// double log_kinetic_energy(const MR::Math::Matrix& weights_chol) const; + + + template void half_update_momentum(const MR::Math::Vector& gradient, const MR::Math::Matrix& weights, std::vector& weights_gradient, double time_direction, size_t num_newton_steps = 1); + + + double predicted_change(const MR::Math::Vector& gradient, const MR::Math::Matrix& fisher_chol, double time_direction) const; + + + template double predicted_change(const T& gradient, const MR::Math::Matrix& fisher_chol, double time_direction) const + { return predicted_change(gradient, fisher_chol, time_direction); } + + }; + + + template void Momentum::Weighted::NonSeparable::half_update_momentum(const MR::Math::Vector& gradient, + const MR::Math::Matrix& weights_chol, + std::vector& weights_gradient, + double time_direction, + size_t num_newton_steps) { + + + assert((time_direction == -1.0) || (time_direction == 1.0)); + + for (size_t elem_i = 0; elem_i < size(); ++elem_i) { + + //More numerically sound than calculating the inverse and multiplying it with the gradient. + for (size_t col_i = 0; col_i < size(); ++col_i) { + MR::Math::Vector Winv_dWdx_col = Winv_dWdx[elem_i].column(col_i); + MR::Math::Cholesky::solve(Winv_dWdx_col, weights_chol, weights_gradient[elem_i].column(col_i)); + } + + trace_Winv_dWdx[elem_i] = Math::trace(Winv_dWdx[elem_i]) / 2.0; + } + + tmp_momen = momen; + + MR::Math::Vector weights_momen(size()); + + for (size_t newton_i = 0; newton_i < num_newton_steps; ++newton_i) { + + MR::Math::Cholesky::solve(weights_momen, weights_chol, tmp_momen); + + for (size_t elem_i = 0; elem_i < size(); ++elem_i) { + MR::Math::mult(working1, Winv_dWdx[elem_i], weights_momen); + working2[elem_i] = MR::Math::dot(working1 , tmp_momen) / 2.0; + + } + + for (size_t elem_i = 0; elem_i < size(); ++elem_i) { + + tmp_momen[elem_i] = momen[elem_i] + 0.5 * time_direction * step[elem_i] * (gradient[elem_i] - trace_Winv_dWdx[elem_i] + working2[elem_i]); + + if (isnan(tmp_momen[elem_i]) || isinf(tmp_momen[elem_i])) + throw NanInfException(); +// throw Exception ("Momentum has NaN or inf values in " + str(newton_i) + " newton step.\n\n" + str(tmp_momen) + "\n\n"); + } + + } + + momen = tmp_momen; + + } + + } + + } + +} + +#endif /* __bts_mcmc_proposal_momentum_weighted_non_separable_h__ */ diff --git a/src/bts/mcmc/proposal/walker.cpp b/src/bts/mcmc/proposal/walker.cpp new file mode 100644 index 0000000..5de1ae0 --- /dev/null +++ b/src/bts/mcmc/proposal/walker.cpp @@ -0,0 +1,62 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, Jul 28, 2010. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + +#include "bts/common.h" +#include "bts/mcmc/proposal/walker.h" + +namespace BTS { + + namespace MCMC { + + namespace Proposal { + + const std::string Walker::TYPE_DEFAULT = "standard"; + const double Walker::STEP_SCALE_DEFAULT = 1.0; + const std::string Walker::STEP_LOCATION_DEFAULT = "/home/tclose/data/mcmc/parameters/walker.sta"; + + void Walker::set(Distribution* const proposal_distribution, + MR::Math::Vector relative_step_sizes) { + + if (prop_distr) + delete prop_distr; + + this->prop_distr = proposal_distribution->clone(); + + step_sizes = relative_step_sizes; + + } + + + void Walker::step(const MR::Math::Vector& current, MR::Math::Vector& proposed, double scalar) const { + + assert(current.size() == proposed.size()); + + for (size_t elem_i = 0; elem_i < current.size(); elem_i++) + proposed[elem_i] = prop_distr->sample(current[elem_i], step_sizes[elem_i] * scalar); + + } + + } + + } + +} diff --git a/src/bts/mcmc/proposal/walker.h b/src/bts/mcmc/proposal/walker.h new file mode 100644 index 0000000..72a0191 --- /dev/null +++ b/src/bts/mcmc/proposal/walker.h @@ -0,0 +1,176 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, 26/07/2010. + + This file is part of MRtrix. + + MRtrix 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 walk_option) any later version. + + MRtrix 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 MRtrix. If not, see . + +*/ + +#ifndef __bts_mcmc_proposal_walker_h__ +#define __bts_mcmc_proposal_walker_h__ + +namespace BTS { + + namespace MCMC { + + namespace Proposal { + + class Walker; + + } + + } + +} + + + +#define PROPOSAL_WALKER_PARAMETERS \ + Option ("walk_type", "The 'Proposal Walker' object used to propose new fibres in MCMC sampling.") \ + + Argument ("walk_type", "").type_text(), \ +\ + Option ("walk_step_scale", "Overall scaling, every scaling is multiplied by this value.") \ + + Argument ("walk_step_scale", "").type_float (0.0, 1e5, NAN), \ +\ + Option ("walk_step_location", "The location of the relative scalings for each of the parameters.") \ + + Argument ("walk_step_location", "").type_text(), \ +\ + Option ("walk_intens_scale", "Intensity step size scaling.") \ + + Argument ("walk_intens_scale", "").type_float (0.0, 1e5, NAN) + + +//Loads the 'proposal' parameters into variables +#define SET_PROPOSAL_WALKER_PARAMETERS(state_location) \ + std::string walk_type; \ + double walk_step_scale; \ + std::string walk_step_location; \ + double walk_base_intens_scale; \ + \ + if (File::has_extension(state_location)) { \ + walk_type = Fibre::Strand::Set::Walker::TYPE_DEFAULT; \ + walk_step_scale = Fibre::Strand::Set::Walker::STEP_SCALE_DEFAULT; \ + walk_base_intens_scale = 0.01; \ + walk_step_location = Fibre::Strand::Set::Walker::STEP_LOCATION_DEFAULT; \ + \ + } else if (File::has_extension(state_location)) { \ + walk_type = Fibre::Tractlet::Set::Walker::TYPE_DEFAULT; \ + walk_step_scale = Fibre::Tractlet::Set::Walker::STEP_SCALE_DEFAULT; \ + walk_base_intens_scale = 0.01; \ + walk_step_location = Fibre::Tractlet::Set::Walker::STEP_LOCATION_DEFAULT; \ + \ + } else { \ + walk_type = MCMC::Proposal::Walker::TYPE_DEFAULT; \ + walk_step_scale = MCMC::Proposal::Walker::STEP_SCALE_DEFAULT; \ + walk_step_location = MCMC::Proposal::Walker::STEP_LOCATION_DEFAULT; \ + } \ + \ + Options walk_opt = get_options("walk_type"); \ + if (walk_opt.size()) \ + walk_type = walk_opt[0][0].c_str(); \ + \ + walk_opt = get_options("walk_step_scale"); \ + if (walk_opt.size()) \ + walk_step_scale = walk_opt[0][0]; \ + \ + walk_opt = get_options("walk_step_location"); \ + if (walk_opt.size()) \ + walk_step_location = walk_opt[0][0].c_str(); \ + \ + walk_opt = get_options("walk_base_intens_scale"); \ + if (walk_opt.size()) \ + walk_base_intens_scale = walk_opt[0][0]; + + + +//Adds the 'proposal' parameters to the properties to be saved with the data. +#define ADD_PROPOSAL_WALKER_PROPERTIES(properties) \ + properties["walk_type"] = walk_type; \ + properties["walk_step_scale"] = str(walk_step_scale); \ + properties["walk_base_intens_scale"] = str(walk_base_intens_scale); \ +\ + if (walk_type == "standard") { \ + properties["walk_step"] = Fibre::Base::Object::load_matlab_str(walk_step_location, walk_step_scale); \ + properties["walk_step_location"] = walk_step_location; \ +\ + } + + +#include "bts/mcmc/proposal/distribution.h" +#include "bts/mcmc/state.h" + +namespace BTS { + + namespace MCMC { + + namespace Proposal { + + class Walker { + + public: + + const static std::string TYPE_DEFAULT; + const static double STEP_SCALE_DEFAULT; + const static std::string STEP_LOCATION_DEFAULT; + + //Member variables + protected: + + MR::Math::Vector step_sizes; + + Distribution* prop_distr; + + //Member functions + public: + + + Walker(Distribution* const prop_distr = 0) : prop_distr(prop_distr) {} + + Walker(Distribution* const proposal_distribution, + const MR::Math::Vector& relative_step_sizes) + : prop_distr(0) + + { set(proposal_distribution, relative_step_sizes); } + + ~Walker() + { if (prop_distr) delete prop_distr; } + + + Walker(const Walker& m) + : step_sizes(m.step_sizes) { if (m.prop_distr) prop_distr = m.prop_distr->clone(); } + + + Walker& operator=(const Walker& m) + { step_sizes = m.step_sizes; if (m.prop_distr) prop_distr = m.prop_distr->clone(); return *this; } + + + void step(const MR::Math::Vector& current, MR::Math::Vector& proposed, double scalar = 1.0) const; + + + void set(Distribution* const proposal_distribution, + MR::Math::Vector relative_step_sizes); + + + + }; + + } + + } + +} + +#endif /* __bts_mcmc_proposal_walker_h__ */ diff --git a/src/bts/mcmc/riemannian.h b/src/bts/mcmc/riemannian.h new file mode 100644 index 0000000..b3f1522 --- /dev/null +++ b/src/bts/mcmc/riemannian.h @@ -0,0 +1,449 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + + +#ifndef __bts_mcmc_riemannian_h__ +#define __bts_mcmc_riemannian_h__ + +extern "C" { +#include +#include +} + +#include + +#include "progressbar.h" +#include "math/cholesky.h" + +#include "bts/fibre/strand/set/tensor.h" +#include "bts/fibre/tractlet/set/tensor.h" +#include "bts/mcmc/common.h" + +#include "bts/mcmc/proposal/momentum/weighted/non_separable.h" +#include "bts/mcmc/naninf_exception.h" + + +#include "bts/common.h" + + + + +namespace BTS { + + namespace MCMC { + + namespace Riemannian { + + const size_t NUM_SAMPLES_DEFAULT = 100; + const size_t NUM_LEAPFROG_STEPS_DEFAULT = 30; + const size_t NUM_NEWTON_STEPS_DEFAULT = 6; + const size_t BURN_NUM_SAMPLES_DEFAULT = 0; + const size_t BURN_NUM_LEAPFROG_STEPS_DEFAULT = 30; + const size_t BURN_NUM_NEWTON_STEPS_DEFAULT = 6; + const size_t BURN_SNR_DEFAULT = 1; + const float PRECONDITION_DEFAULT = 1000; + + } + + template class Posterior { + + //Public static variables, nested classes and typedefs + public: + + + //Protected member variables + protected: + + Prior_T& prior; + Likelihood_T& likelihood; + double precondition; + + size_t dimension; + + State_T prior_gradient, likelihood_gradient; + typename State_T::Tensor prior_fisher, likelihood_fisher; + std::vector prior_fisher_gradient, likelihood_fisher_gradient; + + typename State_T::Tensor::Writer fisher_writer; + + //Public member functions + public: + + Posterior(const State_T& state, Prior_T& prior, Likelihood_T& likelihood, double precondition = 0.0) + : prior(prior), + likelihood(likelihood), + precondition(precondition), + dimension(state.vsize()), + prior_gradient(state), + likelihood_gradient(state), + prior_fisher(state), + likelihood_fisher(state) { + + prior_gradient.zero(); + likelihood_gradient.zero(); + + prior_fisher.zero(); + likelihood_fisher.zero(); + + for (size_t elem_i = 0; elem_i < dimension; ++elem_i) { + prior_fisher_gradient.push_back(prior_fisher); + likelihood_fisher_gradient.push_back(likelihood_fisher); + } + + fisher_writer.create("/home/tclose/data/mcmc/riemannian/fishers.sta.tnr", state); + + } + + + double log_prob_and_fisher (const State_T& state, State_T& gradient, typename State_T::Tensor& fisher, std::vector& fisher_gradient) { + + double px = prior.log_prob_and_fisher(state, prior_gradient, prior_fisher, prior_fisher_gradient); + px += likelihood.log_prob_and_fisher(state, likelihood_gradient, likelihood_fisher, likelihood_fisher_gradient); + + gradient = prior_gradient + likelihood_gradient; + fisher = prior_fisher; + fisher += likelihood_fisher; + + if (precondition) { + + for (size_t elem_i = 0; elem_i < dimension; ++elem_i) + fisher(elem_i,elem_i) += precondition; + + } + + for (size_t elem_i = 0; elem_i < dimension; ++elem_i) { + fisher_gradient[elem_i] = prior_fisher_gradient[elem_i]; + fisher_gradient[elem_i] += likelihood_fisher_gradient[elem_i]; + } + + fisher_writer.append(fisher); + + return px; + + } + + + double log_prob_and_fisher (const State_T& state, State_T& gradient, typename State_T::Tensor& fisher) { + + double px = prior.log_prob_and_fisher(state, prior_gradient, prior_fisher); + px += likelihood.log_prob_and_fisher(state, likelihood_gradient, likelihood_fisher); + + gradient = prior_gradient; + gradient += likelihood_gradient; + + fisher = prior_fisher; + fisher += likelihood_fisher; + + if (precondition) { + + for (size_t elem_i = 0; elem_i < dimension; ++elem_i) + fisher(elem_i,elem_i) += precondition; + + } + + fisher_writer.append(fisher); + + return px; + + } + + //Protected member functions + protected: + + + }; + + + template State_T riemannian (State_T& initial_x, + Likelihood_T& likelihood, + Prior_T& prior, + MCMC::Proposal::Momentum::Weighted::NonSeparable& momentum, + const std::string& samples_location, + const std::map& run_properties, + size_t num_samples, + size_t num_leapfrog_steps, + size_t num_newton_steps, + gsl_rng* rand_gen, + double precondition = 0.0, + bool prior_only = false, + bool save_iterations = false, + bool suppress_print = false ) { + + + + Posterior posterior(initial_x, prior, likelihood, precondition); + + std::vector sample_header; + + sample_header.push_back(LOG_PROB_PROP); + sample_header.push_back(H_PROP); + sample_header.push_back(PROPOSED_H_PROP); + + + std::vector components_list = prior.list_components(); + + sample_header.insert(sample_header.end(), components_list.begin(), components_list.end()); + + typename State_T::Writer samples (samples_location, initial_x, sample_header, run_properties); + + typename State_T::Writer iterations, gradient_iterations; + + + SamplePropertyHeader iteration_property_header; + + iteration_property_header.push_back("log_px"); + iteration_property_header.push_back("pred_d_log_px"); + iteration_property_header.push_back("act_d_log_px"); + iteration_property_header.push_back("grad_norm2"); + iteration_property_header.push_back("log_kinetic_energy"); + + + + if (save_iterations) { + iterations.create(File::strip_extension(samples_location) + ".iter." + File::extension(samples_location), initial_x, iteration_property_header, run_properties); + gradient_iterations.create(File::strip_extension(samples_location) + ".grad_iter." + File::extension(samples_location), initial_x, SamplePropertyHeader(), run_properties); + } + + + + State_T x = initial_x; + + size_t dimension = x.vsize(); + + State_T gradient(x); + gradient.zero(); + + typename State_T::Tensor fisher(x); + fisher.zero(); + + std::vector fisher_gradient; + for (size_t elem_i = 0; elem_i < dimension; ++elem_i) + fisher_gradient.push_back(fisher); + + + typename State_T::Tensor fisher_chol (fisher); + + + double px = posterior.log_prob_and_fisher(x, gradient, fisher, fisher_gradient); + + fisher_chol = fisher; + + MR::Math::Cholesky::decomp(fisher_chol); + + + //-------------------------// + // Take the MCMC samples // + //-------------------------// + + size_t iteration_count = 0; + + // Initialise the progress bar + MR::ProgressBar progress_bar ("Generating " + str(num_samples) + " Riemannian Hamiltonian MCMC samples ...", num_samples); + + for (size_t sample_i = 0; sample_i < num_samples; sample_i++) { + + momentum.randomize(fisher_chol); + + double log_kinetic_energy = momentum.log_kinetic_energy(fisher_chol); //(LOG_2 + LOG_PI * dimension + fisher_det) / 2.0 + + // NB: Since we want to find maxima not minima the probability of x is inverted when compared from the classical algorithm + // (as implemented in Mackay, D. 2003. Information Theory, Inference and Learning Algorithms, Cambridge University Press, pp388.) + + double H = log_kinetic_energy - px; + + clock_t sample_starttime = clock(); + + State_T prop_x = x; + State_T prop_gradient = gradient; + typename State_T::Tensor prop_fisher = fisher; + typename State_T::Tensor prop_fisher_chol = fisher_chol; + double prop_px = px; + + + //Randomly select to evolve forwards or backwards in time. + double time_direction; + + if (gsl_rng_uniform(rand_gen) > 0.5) + time_direction = 1.0; + else + time_direction = -1.0; + +// MR::Math::Vector time_direction_matrix ("/home/tclose/data/mcmc/state/time_direction.txt"); +// +// time_direction = time_direction_matrix[0]; + + try { + + // Make 'num_leapfrog_steps' leapfrog steps. + for (size_t leapfrog_i = 0; leapfrog_i < num_leapfrog_steps; leapfrog_i++) { + + + if (save_iterations) { + + prop_x.set_extend_prop("pred_d_log_px",str(momentum.predicted_change(prop_gradient, prop_fisher_chol, time_direction))); + + } + + // NB: Since we want to find maxima not minima the gradient of x is inverted when compared from the classical algorithm. + momentum.half_update_momentum(prop_gradient, prop_fisher_chol, fisher_gradient, time_direction, num_newton_steps); + + // Debug purposes only. + double prev_prop_px = prop_px; + + MR::Math::Vector fishinv_momen(dimension), tmp_fishinv_momen(dimension); + MR::Math::Vector& prop_x_vector = prop_x; + State_T tmp_x (prop_x); + MR::Math::Vector& tmp_x_vector = tmp_x; + + MR::Math::Cholesky::solve(fishinv_momen, fisher_chol, momentum.momentum()); + + for (size_t newton_i = 0; newton_i < num_newton_steps; ++newton_i) { + + posterior.log_prob_and_fisher(tmp_x, prop_gradient, prop_fisher); + + MR::Math::Cholesky::decomp(prop_fisher_chol = prop_fisher); + MR::Math::Cholesky::solve(tmp_fishinv_momen, prop_fisher_chol, momentum.momentum()); + + for (size_t elem_i = 0; elem_i < dimension; ++elem_i) { + tmp_x_vector[elem_i] = prop_x_vector[elem_i] + (fishinv_momen[elem_i] + tmp_fishinv_momen[elem_i]) * momentum.step_sizes()[elem_i] * time_direction * 0.5; + if (isnan(tmp_x_vector[elem_i]) || isinf(tmp_x_vector[elem_i])) + throw NanInfException(); + // throw Exception ("State_T has NaN values in " + str(newton_i) + " newton step of " + str(leapfrog_i) + " leapfrog step.\n\n" + str(tmp_x_vector) + "\n\n"); + } + + + } + + prop_x = tmp_x; + + prop_px = posterior.log_prob_and_fisher(prop_x, prop_gradient, prop_fisher, fisher_gradient); + + MR::Math::Cholesky::decomp(prop_fisher_chol = prop_fisher); + + // NB: Since we want to find maxima not minima the gradient of x is inverted when compared from the classical algorithm. + momentum.half_update_momentum(prop_gradient, prop_fisher_chol, fisher_gradient, time_direction); + + if (save_iterations) { + + prop_x.set_extend_prop("log_px",str(prop_px)); + prop_x.set_extend_prop("act_d_log_px",str(prop_px - prev_prop_px)); + prop_x.set_extend_prop("grad_norm2",str(prop_gradient.norm2())); + prop_x.set_extend_prop("log_kinetic_energy",str(momentum.log_kinetic_energy(prop_fisher_chol))); + + std::map prop_component_values = prior.get_component_values(prop_x); + + for (std::map::iterator comp_it = prop_component_values.begin(); comp_it != prop_component_values.end(); ++comp_it) + prop_x.set_extend_prop(comp_it->first, comp_it->second); + + iterations.append(prop_x); + gradient_iterations.append(prop_gradient); + + } + + + ++iteration_count; + + } + + // Decide whether to accept 'step' (or rather chain of leapfrog steps). + double prop_log_kinetic_energy = momentum.log_kinetic_energy(prop_fisher_chol); + + // NB: Since we want to find maxima not minima the gradient of x is inverted when compared from the classical algorithm. + double prop_H = prop_log_kinetic_energy - prop_px; + + // NB: Since we want to find maxima not minima the order of this subtraction is reversed. + double dH = prop_H - H; + + double elapsed_time = (double)(clock() - sample_starttime) / (double)CLOCKS_PER_SEC; + + // Print out sample properties. + if (!suppress_print) { + std::cout << std::endl; + std::cout << "Sample: " << sample_i << ", "; + std::cout << "log[px]: " << px << ", "; + std::cout << "Start kinetic energy: " << log_kinetic_energy << ", "; + std::cout << "H: " << H << ", "; + std::cout << "Proposed log[px]: " << prop_px << ", "; + std::cout << "Final kinetic energy: " << prop_log_kinetic_energy << ", "; + std::cout << "Proposed H: " << prop_H << ", "; + std::cout << "Elapsed time: " << elapsed_time; + + } + + + // If Hamiltonian decreases (i.e. there is less energy in the system) or the increase is below log[Y] (where Y is a uniformly distributed random variable between 0 and 1), accept the proposer. + if ((dH < 0) || (log(gsl_ran_flat(rand_gen, 0,1)) < -dH)) { + x = prop_x; + gradient = prop_gradient; + fisher = prop_fisher; + fisher_chol = prop_fisher_chol; + px = prop_px; + + if (!suppress_print) + std::cout << ", Accepted!." << std::endl; + + } else if (!suppress_print) + std::cout << ", Not accepted." << std::endl; + + // Record sample stats. + + x.set_extend_prop(LOG_PROB_PROP, str(px)); + x.set_extend_prop(H_PROP, str(H)); + x.set_extend_prop(PROPOSED_H_PROP, str(prop_H)); + + + std::map component_values = prior.get_component_values(x); + + for (std::map::iterator comp_it = component_values.begin(); comp_it != component_values.end(); ++comp_it) + x.set_extend_prop(comp_it->first, comp_it->second); + + + } catch (const NanInfException& e) { + + std::cout << std::endl; + std::cout << "Sample: " << sample_i << " - "; + std::cout << "Not accepted due to NaN or Inf values found" << std::endl; + + } + + // Save sample. + samples.append(x); + + + progress_bar++; + + } + + + State_T out_x = x; + + return out_x; + + } + + + + } + +} + +#endif diff --git a/src/bts/mcmc/state.cpp b/src/bts/mcmc/state.cpp new file mode 100644 index 0000000..7263e31 --- /dev/null +++ b/src/bts/mcmc/state.cpp @@ -0,0 +1,35 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, Aug 2, 2010. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + +#include "bts/mcmc/state.h" + +namespace BTS { + + namespace MCMC { + + + const std::string State::FILE_EXTENSION = "sta"; + + + } + +} diff --git a/src/bts/mcmc/state.h b/src/bts/mcmc/state.h new file mode 100644 index 0000000..ab08c05 --- /dev/null +++ b/src/bts/mcmc/state.h @@ -0,0 +1,175 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, Aug 2, 2010. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + +#include "bts/mcmc/proposal/momentum.h" +#include "bts/mcmc/proposal/walker.h" + + +#ifndef __bts_mcmc_state_h__ +#define __bts_mcmc_state_h__ + +#include + +namespace BTS { + + namespace MCMC { + + class State; + + } +} + + +#include "math/vector.h" +#include "bts/utilities/reader.h" +#include "bts/utilities/writer.h" + + +namespace BTS { + + namespace MCMC { + + class State : public MR::Math::Vector { + + //Public static variables, nested classes and typedefs + public: + + typedef Proposal::Walker Walker; + typedef Proposal::Momentum Momentum; + typedef std::map Properties; + typedef Utilities::Reader Reader; + typedef Utilities::Writer Writer; + + template class Tensor_tpl; + class Tensor; + + public: + + Properties properties; + + + public: + + static const std::string FILE_EXTENSION; + + public: + + + //Do nothing, no characteristic properties in MCMC::State class. + static std::vector& append_characteristic_property_keys(std::vector& header) { return header; } + + //Public member functions + public: + + //! construct empty state + State () throw () {} + + //! copy constructor + State (const State& state) + : MR::Math::Vector (state), properties(state.properties) {} + + State(const MR::Math::Vector& vector) + : MR::Math::Vector(vector) {} + + //! construct state of size \a nelements + /** \note the elements of the state are left uninitialised. */ + State (size_t nelements) + : MR::Math::Vector(nelements) {} + + //! construct from existing data array + State (double* state_data, size_t nelements, size_t skip = 1) throw () + : MR::Math::Vector(state_data,nelements,skip) {} + + //! construct a state by reading from the text file \a filename + State (const std::string& file) + : MR::Math::Vector(file) {} + + + State& operator= (const State& state) + { MR::Math::Vector::operator=(state); properties = state.properties; return *this; } + + + //! destructor + ~State () {} + + + + double norm2() const + { return MR::Math::norm2(*this); } + + double norm() const + { return MR::Math::norm(*this); } + + double inner_product(const State& state) const + { return MR::Math::dot(*this, state); } + + State& zero() + { for (size_t i = 0; i < size(); i++) operator[](i) = 0.0; return *this;} + + State& invalidate() + { for (size_t i = 0; i < size(); i++) operator[](i) = NAN; return *this; } + + State operator- () { operator*=(-1.0); return *this; } + + + void set_extend_prop(const std::string& prop, const std::string& value) { + + properties[prop] = value; + + } + + + + + State operator+(const State& state) const { State answer = *this; answer += state; return answer; } + State operator-(const State& state) const { State answer = *this; answer -= state; return answer; } + + State operator* (const State& state) const { State answer = *this; answer *= state; return answer; } + State operator/ (const State& state) const { State answer = *this; answer /= state; return answer; } + + State operator* (double scalar) const { State answer = *this; answer *= scalar; return answer; } + State operator/ (double scalar) const { State answer = *this; answer /= scalar; return answer; } + + + MR::Math::Vector vector() const + { return *this; } + + void from_vector(const MR::Math::Vector& vec) + { MR::Math::Vector::operator=(vec); } + + size_t vsize() const + { return size(); } + + + void calc_characteristic_properties() {} + + }; + + + inline State operator*(double scalar, const State& state) + { return state * scalar; } + + } + +} + +#endif /* __bts_mcmc_state_h__ */ diff --git a/src/bts/mcmc/state/tensor.cpp b/src/bts/mcmc/state/tensor.cpp new file mode 100644 index 0000000..12e070f --- /dev/null +++ b/src/bts/mcmc/state/tensor.cpp @@ -0,0 +1,58 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, 11/08/2010. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + +#include "bts/mcmc/state/tensor.h" + +namespace BTS { + + namespace MCMC { + + + State::Tensor::Tensor(const State& template_value) + : MR::Math::Matrix(template_value.size(),template_value.size()) { + + for (size_t row_i = 0; row_i < template_value.size(); ++row_i) + this->row(row_i) = template_value; + + } + + State::Tensor& State::Tensor::invalidate() { + + MR::Math::Matrix::operator=(NAN); + + return *this; + + } + + State::Tensor& State::Tensor::zero() { + + MR::Math::Matrix::operator=(0.0); + + return *this; + + } + + + + } + +} diff --git a/src/bts/mcmc/state/tensor.h b/src/bts/mcmc/state/tensor.h new file mode 100644 index 0000000..0ae9359 --- /dev/null +++ b/src/bts/mcmc/state/tensor.h @@ -0,0 +1,77 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, 11/08/2010. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + +#ifndef __bts_mcmc_state_tensor_h__ +#define __bts_mcmc_state_tensor_h__ + +#include "bts/mcmc/state.h" +#include "math/matrix.h" + +namespace BTS { + + namespace MCMC { + + class State::Tensor : public MR::Math::Matrix { + + //Public static variables, nested classes and typedefs + public: + + class Writer; + + //Public member functions + public: + + Tensor () {} + + Tensor (size_t size) + : MR::Math::Matrix(size,size) {} + + Tensor (const State& value); + + Tensor (const MR::Math::Matrix& tensor) + : MR::Math::Matrix(tensor) {} + + ~Tensor() {} + + Tensor& operator=(const MR::Math::Matrix& tensor) + { MR::Math::Matrix::operator=(tensor); return *this; } + + size_t length() const + { return MR::Math::Matrix::rows(); } + + Tensor& invalidate(); + + Tensor& zero(); + + MR::Math::Matrix matrix() const + { return *this; } + + void from_matrix(const MR::Math::Matrix& matrix) + { MR::Math::Matrix::operator=(matrix); } + + }; + + } + +} + +#endif /* __bts_mcmc_state_tensor_h__ */ diff --git a/src/bts/mcmc/state/tensor/writer.cpp b/src/bts/mcmc/state/tensor/writer.cpp new file mode 100644 index 0000000..fcff0f4 --- /dev/null +++ b/src/bts/mcmc/state/tensor/writer.cpp @@ -0,0 +1,59 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, 11/08/2010. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + +#include "bts/mcmc/state/tensor/writer.h" + +namespace BTS { + + namespace MCMC { + + const std::string State::Tensor::Writer::HEADER_PREAMBLE = "%%% Keys %%%:"; + + + void State::Tensor::Writer::create (const std::string& location, size_t length) { + + this->length = length; + + out.open(location.c_str()); + + out << HEADER_PREAMBLE; + + for (size_t i = 0; i < length; i++) + out << "elem" << i << " "; + + out << std::endl; + + } + + + void State::Tensor::Writer::append(const MCMC::State::Tensor& tensor) { + + if (length != tensor.length()) + throw Exception ("Length of tensor matrix (" + str(tensor.length()) + ") did not match size of template value vector (" + str(length) + ")."); + + out << tensor; + + } + + } + +} diff --git a/src/bts/mcmc/state/tensor/writer.h b/src/bts/mcmc/state/tensor/writer.h new file mode 100644 index 0000000..60b0104 --- /dev/null +++ b/src/bts/mcmc/state/tensor/writer.h @@ -0,0 +1,78 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, 11/08/2010. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + +#ifndef __bts_mcmc_state_tensor_writer_h__ +#define __bts_mcmc_state_tensor_writer_h__ + +#include "bts/mcmc/state.h" +#include "bts/mcmc/state/tensor.h" + +namespace BTS { + + namespace MCMC { + + class State::Tensor::Writer { + + + //Public static variables, nested classes and typedefs + public: + + static const std::string HEADER_PREAMBLE; + + //Protected member variables + protected: + + std::vector header; + size_t length; + std::ofstream out; + + //Public member functions + public: + + Writer() {} + + Writer(const std::string& location, size_t size) + { create(location, size); } + + Writer(const std::string& location, const MCMC::State& template_value) + { create(location, template_value); } + + ~Writer() { close(); } + + void close() + { out.close(); } + + void create (const std::string& location, size_t size); + + void create (const std::string& location, const MCMC::State& template_value) + { create (location, template_value.size()); } + + void append(const MCMC::State::Tensor& tensor); + + + }; + + } + +} + +#endif /* __bts_mcmc_state_tensor_writer_h__ */ diff --git a/src/bts/prob/inline_functions.h b/src/bts/prob/inline_functions.h new file mode 100644 index 0000000..811f0be --- /dev/null +++ b/src/bts/prob/inline_functions.h @@ -0,0 +1,40 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, 16/07/2010. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + +#ifndef __bts_prob_inline_functions_h__ +#define __bts_prob_inline_functions_h__ + + +#ifdef __bts_prob_likelihood_imagediff_h__ + +#include "bts/prob/likelihood.cpp.h" + +#endif + + +#ifdef __bts_prob_likelihood_imagediff_gaussian_h__ + +//#include "bts/prob/likelihood/gaussian.cpp.h" + +#endif + +#endif /* __bts_prob_inline_functions_h__ */ diff --git a/src/bts/prob/likelihood.cpp b/src/bts/prob/likelihood.cpp new file mode 100644 index 0000000..c215731 --- /dev/null +++ b/src/bts/prob/likelihood.cpp @@ -0,0 +1,220 @@ +/* + Copyright 2010 Brain Research Institute/National ICT Australia (NICTA), Melbourne, Australia + + Written by Thomas G Close, 5/05/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + +*/ + +#include "bts/prob/likelihood.h" +#include "bts/image/observed/buffer.h" +#include "bts/image/expected/trilinear/buffer.h" + +#include "bts/prob/likelihood/gaussian.h" +#include "bts/prob/likelihood/one_sided_gaussian.h" +#include "bts/prob/likelihood/rician.h" + +#include "bts/prob/likelihood/gaussian.cpp.h" + +#include "bts/prob/inline_functions.h" +#include "bts/image/inline_functions.h" +#include "bts/prob/likelihood.cpp.h" +#include "bts/image/buffer.cpp.h" +#include "bts/diffusion/response.h" + +namespace BTS { + + namespace Prob { + + const char* Likelihood::TYPE_DEFAULT = "gaussian"; + const double Likelihood::SNR_DEFAULT = 20.0; + const char* Likelihood::B0_INCLUDE_DEFAULT = "none"; //Also "half" or "full" + const double Likelihood::OUTSIDE_SCALE_DEFAULT = 1.0; + const char* Likelihood::REF_B0_DEFAULT = "max"; // Also could be "average" + + + const Image::Observed::Buffer Likelihood::dummy_observed_buffer; + const Image::Expected::Trilinear::Buffer Likelihood::dummy_expected_buffer; + + + Likelihood* Likelihood::factory(const std::string& type, + const Image::Observed::Buffer& obs_image, + Image::Expected::Buffer* exp_image, + double assumed_snr, + const std::string& b0_include, + double outside_scale, + const std::string& ref_b0, + double ref_signal) { + + //FIXME: Not sure why this happens, but before exp_image is cloned it must be cleared to produce consistent results. + //Investigate and resolve. + exp_image->clear(); + + Likelihood* likelihood; + + if (type == "gaussian") + + likelihood = new Gaussian (obs_image, exp_image, assumed_snr, b0_include, outside_scale, ref_b0, ref_signal); + + else if (type == "one_sided_gaussian") + + likelihood = new OneSidedGaussian (obs_image, exp_image, assumed_snr, b0_include, outside_scale, ref_b0, ref_signal); + + else if (type == "rician") { + + const Diffusion::Model& diffusion_model = exp_image->get_diffusion_model(); + + if (!diffusion_model.includes_isotropic()) + throw Exception ("Only diffusion models that include isotropic components can be used with Rician noise model."); + + if (!exp_image->bounds_are_enforced()) + throw Exception ("Enforce bounds must be set with Rician noise model to avoid -inf values."); + + likelihood = new Rician (obs_image, exp_image, assumed_snr, b0_include, outside_scale, ref_b0, ref_signal); + + } else + throw Exception ("Unrecognised likelihood type '" + type + "' passed to option '-like_type'."); + + + return likelihood; + + + } + + + + + Likelihood::Likelihood ( + const Image::Observed::Buffer& observed_image, + Image::Expected::Buffer* const expected_image, + double assumed_snr, + const std::string& b0_include, + double outside_scale, + const std::string& ref_b0, + double ref_signal + ) : + obs_image(observed_image), + exp_image(expected_image->clone()), + b0_include(b0_include) + { + + if (!expected_image->dims_match(obs_image)) + throw Exception ("Expected image dimensions (" + str(expected_image->dims()) + ") do not match and observed image (" + str(obs_image.dims()) + ")."); + + set_assumed_snr(assumed_snr, ref_b0, ref_signal); + + this->exp_image->zero(); + + } + + Likelihood::Likelihood (const Likelihood& l) + : sigma2(l.sigma2), + obs_image(l.obs_image), + exp_image(l.exp_image->clone()), + b0_include(l.b0_include) {} + + + Likelihood& Likelihood::operator= (const Likelihood& l) { + + delete this->exp_image; + + sigma2 = l.sigma2; + obs_image = l.obs_image; + exp_image = l.exp_image->clone(); + b0_include = l.b0_include; + + return *this; + + } + + + + void Likelihood::set_assumed_snr(double assumed_snr, const std::string& ref_b0, double reference_signal) { + + double ref_signal; + + if (!isnan(reference_signal)) + ref_signal = reference_signal; + else if (obs_image.properties().count("noise_ref_signal")) + ref_signal = to(obs_image.properties()["noise_ref_signal"]); + else if (ref_b0 == "average") + ref_signal = obs_image.average_b0(); + else if (ref_b0 == "max") + ref_signal = obs_image.max_b0(); + else + throw Exception ("Unrecognised value for '-like_ref_b0' ('" + ref_b0 + "'), can be either 'average', or 'max'."); + + if (!ref_signal) + throw Exception ("The " + ref_b0 + " b0 of observed image is 0."); + + sigma2 = MR::Math::pow2(ref_signal / assumed_snr); + + } + + + void Likelihood::set_enforce_bounds(bool flag) { + + if (flag) + exp_image->clear_and_enforce_bounds(); + else + exp_image->relax_bounds(); + + } + + + //TODO: Collapse the workings of the different log_prob_tpl's into common subfunctions. + double Likelihood::log_prob(Image::Expected::Buffer& image) { + + double lprob = 0.0; + + std::set coords = image.non_empty(); + + for (size_t x = 0; x < image.dim(X); ++x) + for (size_t y = 0; y < image.dim(Y); ++y) + for (size_t z = 0; z < image.dim(Z); ++z) + coords.insert(Image::Index(x,y,z)); + + for (std::set::iterator coord_it = coords.begin(); coord_it != coords.end(); ++coord_it) { + + const Image::Expected::Voxel& exp_voxel = image.operator()(*coord_it); + + for (size_t encode_i = 0; encode_i < image.num_encodings(); encode_i++) { + + double observed; + + if (obs_image.in_bounds(*coord_it)) + observed = obs_image(*coord_it)[encode_i]; + else + observed = 0.0; + + if (image.encoding(encode_i).b_value()) + lprob += log_prob(exp_voxel[encode_i], observed); + else + lprob += b0_log_prob(exp_voxel[encode_i], observed); + + } + + } + + return lprob; + + + } + + } + +} diff --git a/src/bts/prob/likelihood.cpp.h b/src/bts/prob/likelihood.cpp.h new file mode 100644 index 0000000..dd04dd1 --- /dev/null +++ b/src/bts/prob/likelihood.cpp.h @@ -0,0 +1,268 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, 30/06/2010. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + +#ifndef __bts_prob_likelihood_imagediff_cpp_h__ +#define __bts_prob_likelihood_imagediff_cpp_h__ + +#include "bts/math/common.h" + +#include "bts/fibre/strand/set/tensor.h" +#include "bts/fibre/tractlet/set/tensor.h" +#include "bts/image/expected/quartic/buffer.h" + +namespace BTS { + + namespace Prob { + + + //TODO: Collapse the workings of the different log_prob_tpl's into common subfunctions. + template double Likelihood::log_prob_tpl(const typename T::Set& fibres) { + + exp_image->expected_image(fibres); + + return log_prob(*exp_image); + + } + + template double Likelihood::log_prob_tpl(const typename T::Set& fibres, typename T::Set& gradient) { + + typename Image::Reference::Buffer::Set& section_references = exp_image->expected_image_with_references(fibres); + + exp_image->precalculate_section_weighting_gradients(T()); + + double lprob = 0.0; + + gradient = fibres; + gradient.zero(); + + std::set coords = exp_image->non_empty_or_inbounds(); + + for (std::set::iterator coord_it = coords.begin(); coord_it != coords.end(); ++coord_it) { + + Image::Expected::Voxel& voxel = exp_image->operator()(*coord_it); + + std::vector d_lprob(exp_image->num_encodings()); + + for (size_t encode_i = 0; encode_i < exp_image->num_encodings(); encode_i++) { + + if (b0_include == "full" || exp_image->encoding(encode_i).b_value()) { + + double observed; + + if (obs_image.in_bounds(*coord_it)) + observed = obs_image(*coord_it)[encode_i]; + else + observed = 0; + + lprob += log_prob(exp_image->operator()(*coord_it)[encode_i], observed, d_lprob[encode_i]); + + } + + } + + for (size_t fibre_i = 0; fibre_i < fibres.size(); fibre_i++) { + + if (!section_references[fibre_i].is_empty(*coord_it)) { + + std::vector& voxel_section_references = section_references[fibre_i](*coord_it); + + for (typename std::vector::iterator section_it = voxel_section_references.begin(); + section_it != voxel_section_references.end(); ++section_it) { + + typename T::Section& section = **section_it; + typename T::Section section_gradient; + + voxel.precalculate_interpolation_gradient(section); + + for (size_t encode_i = 0; encode_i < exp_image->num_encodings(); encode_i++) { + + if (b0_include == "full" || exp_image->encoding(encode_i).b_value()) { + + voxel.direction(encode_i).signal(section, section_gradient); + + section_gradient.unnormalize_gradient(exp_image->vox_lengths()); + + + //Pre-multiply the section gradient with the lprob derivative, so it can be added directly to the + //fibre gradient. + section_gradient *= d_lprob[encode_i]; + + gradient[fibre_i].add_section_gradient(fibres[fibre_i], section, section_gradient); + + + } + + } + + } + + } + + } + + } + + return lprob; + + + } + + + template double Likelihood::log_prob_tpl(const typename T::Set& fibres, typename T::Set& gradient, typename T::Set::Tensor& hessian) { + + typename Image::Container::Buffer::Set& buffer_gradients = get_recycled_gradients(); + typename Image::Container::Buffer::Set& buffer_hessians = get_recycled_hessians(); + + exp_image->expected_image(fibres, buffer_gradients, buffer_hessians); + + double lprob = 0.0; + +// size_t fibres_vector_size = fibres.vsize(); +// size_t fibres_vector_size = fibres.vsize() - 1; + + //TODO: Add zero(T::Set& template_value) overload + gradient = fibres; + hessian = typename T::Set::Tensor(fibres); + + gradient.zero(); + hessian.zero(); + +// bool has_base_intensity = fibres.has_intrinsic_property("base_intensity"); + + std::vector fibre_block_start; + std::vector fibre_block_end; + +// size_t block_start = has_base_intensity; + size_t block_start = 0; + + for (size_t fibre_i = 0; fibre_i < fibres.size(); fibre_i++) { + fibre_block_start.push_back(block_start); + fibre_block_end.push_back(block_start += fibres[fibre_i].vsize()); + } + + + std::set coords = exp_image->non_empty(); + + for (size_t x = 0; x < exp_image->dim(X); ++x) + for (size_t y = 0; y < exp_image->dim(Y); ++y) + for (size_t z = 0; z < exp_image->dim(Z); ++z) + coords.insert(Image::Index(x,y,z)); + + + for (std::set::iterator coord_it = coords.begin(); coord_it != coords.end(); ++coord_it) { + + for (size_t encode_i = 0; encode_i < exp_image->num_encodings(); encode_i++) { + + if (b0_include == "full" || exp_image->encoding(encode_i).b_value()) { + + + double observed; + + if (obs_image.in_bounds(*coord_it)) + observed = obs_image(*coord_it)[encode_i]; + else + observed = 0; + + double d_lprob, d2_lprob2; + + lprob += log_prob(exp_image->operator()(*coord_it)[encode_i], observed, d_lprob, d2_lprob2); + + typename T::Set direction_gradient(fibres); + direction_gradient.zero(); + + typename T::Set::Tensor hessian_fibre_blocks(fibres); + hessian_fibre_blocks = 0.0; + + for (size_t fibre_i = 0; fibre_i < fibres.size(); fibre_i++) { + + if (!buffer_gradients[fibre_i].is_empty(*coord_it)) { + + direction_gradient[fibre_i] = buffer_gradients[fibre_i](*coord_it)[encode_i]; + + MR::Math::Matrix hessian_fibre_block_view = hessian_fibre_blocks.sub(fibre_block_start[fibre_i], fibre_block_end[fibre_i], fibre_block_start[fibre_i], fibre_block_end[fibre_i]); + + MR::Math::Matrix hessian_fibre_block = buffer_hessians[fibre_i](*coord_it)[encode_i]; + + hessian_fibre_block *= d_lprob; + + hessian_fibre_block_view = hessian_fibre_block; + + } else + direction_gradient[fibre_i] = T(fibres[fibre_i].size(), 0.0); + + } + + + MR::Math::Matrix hessian_outer_prod = Math::outer(direction_gradient, direction_gradient); + + hessian_outer_prod *= d2_lprob2; + + hessian += hessian_fibre_blocks; + hessian += hessian_outer_prod; + + gradient += direction_gradient * d_lprob; + + } + + } + + } + + return lprob; + + + } + + + //! Used to get the right used gradients for the templated type. + template <> inline Image::Container::Buffer::Set& Likelihood::get_recycled_gradients() { + + return recycled_strand_gradients; + + } + + //! Used to get the right used gradients for the templated type. + template <> inline Image::Container::Buffer::Set& Likelihood::get_recycled_gradients() { + + return recycled_tractlet_gradients; + + } + + //! Used to get the right used hessians for the templated type. + template <> inline Image::Container::Buffer::Set& Likelihood::get_recycled_hessians() { + + return recycled_strand_hessians; + + } + + //! Used to get the right used hessians for the templated type. + template <> inline Image::Container::Buffer::Set& Likelihood::get_recycled_hessians() { + + return recycled_tractlet_hessians; + + } + + } + +} + +#endif /* __bts_prob_likelihood_imagediff_cpp_h__ */ diff --git a/src/bts/prob/likelihood.h b/src/bts/prob/likelihood.h new file mode 100644 index 0000000..a866f54 --- /dev/null +++ b/src/bts/prob/likelihood.h @@ -0,0 +1,294 @@ +/* + Copyright 2010 Brain Research Institute/National ICT Australia (NICTA), Melbourne, Australia + + Written by Thomas G Close, 5/05/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + +*/ + + +#ifndef __bts_prob_likelihood_h__ +#define __bts_prob_likelihood_h__ + +namespace BTS { + + namespace Prob { + + class Likelihood; + + } + +} + +#define LIKELIHOOD_PARAMETERS \ + Option ("like_snr", "The assumed Signal-to-noise ratio (SNR) in the likelihood model.") \ + + Argument ("like_snr", "").type_float(0, Prob::Likelihood::SNR_DEFAULT,LARGE_FLOAT), \ +\ + Option ("like_type", "The 'Likelihood' object used to calculate the likelihood probability.") \ + + Argument ("like_type", "").type_text(Prob::Likelihood::TYPE_DEFAULT), \ +\ + Option ("like_b0_include", "Include b values in comparison between observed and expected images.") \ + + Argument ("like_b0_include", "").type_text(Prob::Likelihood::B0_INCLUDE_DEFAULT), \ +\ + Option ("like_outside_scale", "The scale of the outside signal contribution to the probability.") \ + + Argument ("like_outside_scale", "").type_float(0.0, Prob::Likelihood::OUTSIDE_SCALE_DEFAULT,LARGE_FLOAT), \ +\ + Option ("like_ref_b0", "Speicify whether to use the 'max' or 'average' b0 signal in the observed image for the calculation of the noise variance from the SNR.") \ + + Argument ("like_ref_b0", "").type_text(Prob::Likelihood::REF_B0_DEFAULT), \ +\ + Option ("like_ref_signal", "Manually speicify b0 signal for the calculation of the noise variance from the SNR.") \ + + Argument ("like_ref_signal", "").type_float(SMALL_FLOAT, NAN, LARGE_FLOAT) \ +\ +//Loads the 'prior' parameters into variables +#define SET_LIKELIHOOD_PARAMETERS \ + double like_snr = Prob::Likelihood::SNR_DEFAULT; \ + std::string like_type = Prob::Likelihood::TYPE_DEFAULT; \ + std::string like_b0_include = Prob::Likelihood::B0_INCLUDE_DEFAULT; \ + double like_outside_scale = Prob::Likelihood::OUTSIDE_SCALE_DEFAULT; \ + std::string like_ref_b0 = Prob::Likelihood::REF_B0_DEFAULT; \ + double like_ref_signal = NAN; \ +\ + Options like_opt = get_options("like_snr"); \ + if (like_opt.size()) \ + like_snr = like_opt[0][0]; \ +\ + like_opt = get_options("like_type"); \ + if (like_opt.size()) \ + like_type = like_opt[0][0].c_str(); \ +\ + like_opt = get_options("like_b0_include"); \ + if (like_opt.size()) \ + like_b0_include = like_opt[0][0].c_str(); \ +\ + like_opt = get_options("like_outside_scale"); \ + if (like_opt.size()) \ + like_outside_scale = like_opt[0][0]; \ +\ + like_opt = get_options("like_ref_b0"); \ + if (like_opt.size()) \ + like_ref_b0 = like_opt[0][0].c_str(); \ +\ + like_opt = get_options("like_ref_signal"); \ + if (like_opt.size()) \ + like_ref_signal = like_opt[0][0]; \ + + +//Adds the 'prior' parameters to the properties to be saved with the data. +#define ADD_LIKELIHOOD_PROPERTIES(properties) \ + properties["like_type"] = like_type; \ + if (like_type != "uniform") {\ + properties["like_snr"] = str(like_snr); \ + properties["like_b0_include"] = like_b0_include; \ + properties["like_outside_scale"] = str(like_outside_scale); \ + if (!isnan(like_ref_signal)) \ + properties["like_ref_signal"] = str(like_ref_signal); \ + else \ + properties["like_ref_b0"] = like_ref_b0; \ + } \ + +#include "bts/image/expected/buffer.h" +#include "bts/image/expected/trilinear/buffer.h" +#include "bts/image/observed/buffer.h" + +#include "bts/prob/prob.h" + +#include "bts/fibre/strand/set.h" +#include "bts/fibre/tractlet/set.h" +#include "bts/mcmc/state.h" + + + +namespace BTS { + + namespace Prob { + + class Likelihood { + + //Public nested classes. + public: + + class Gaussian; + class OneSidedGaussian; + class Rician; + + //Public static constants + public: + + const static char* TYPE_DEFAULT; + const static double SNR_DEFAULT; + const static char* B0_INCLUDE_DEFAULT; + const static double OUTSIDE_SCALE_DEFAULT; + const static char* REF_B0_DEFAULT; + + + const static Image::Observed::Buffer dummy_observed_buffer; + const static Image::Expected::Trilinear::Buffer dummy_expected_buffer; + + public: + + static Likelihood* factory(const std::string& type, + const Image::Observed::Buffer& obs_image, + Image::Expected::Buffer* exp_image, + double assumed_snr, + const std::string& b0_include, + double outside_scale, + const std::string& ref_b0, + double ref_signal); + + + protected: + + double sigma2; + + Image::Observed::Buffer obs_image; + Image::Expected::Buffer* exp_image; + + Image::Container::Buffer::Set recycled_strand_gradients; + Image::Container::Buffer::Set recycled_tractlet_gradients; + Image::Container::Buffer::Set recycled_strand_hessians; + Image::Container::Buffer::Set recycled_tractlet_hessians; + + size_t difference_mode; + + std::string b0_include; + + public: + + Likelihood(const Image::Observed::Buffer& observed_image, + Image::Expected::Buffer* const expected_image, + double assumed_snr, + const std::string& b0_include, + double outside_scale, + const std::string& ref_b0, + double ref_signal); + + + Likelihood(const Likelihood& l); + + + virtual ~Likelihood() + { delete this->exp_image; } + + + Likelihood& operator= (const Likelihood& l); + + virtual double log_prob(Image::Expected::Buffer& image); + + double log_prob(const Fibre::Strand& strand) + { Fibre::Strand::Set set; set.push_back(strand); return log_prob(set); } + + double log_prob(const Fibre::Tractlet& tractlet) + { Fibre::Tractlet::Set set; set.push_back(tractlet); return log_prob(set); } + + double log_prob(const Fibre::Strand& strand, Fibre::Strand& gradient) + { Fibre::Strand::Set set, set_gradient; set.push_back(strand); set_gradient = set; double lprob = log_prob(set, set_gradient); gradient = set_gradient[0]; return lprob; } + + double log_prob(const Fibre::Tractlet& tractlet, Fibre::Tractlet& gradient) + { Fibre::Tractlet::Set set, set_gradient; set.push_back(tractlet); set_gradient = set; double lprob = log_prob(set, set_gradient); gradient = set_gradient[0]; return lprob; } + + virtual double log_prob(const Fibre::Strand::Set& strands) + { return log_prob_tpl(strands); } + + virtual double log_prob(const Fibre::Tractlet::Set& tractlets) + { return log_prob_tpl(tractlets); } + + virtual double log_prob(const Fibre::Strand::Set& strands, Fibre::Strand::Set& gradient) + { return log_prob_tpl(strands, gradient); } + + + virtual double log_prob(const Fibre::Tractlet::Set& tractlets, Fibre::Tractlet::Set& gradient) + { return log_prob_tpl(tractlets, gradient); } + + + virtual double log_prob(const Fibre::Strand::Set& strands, Fibre::Strand::Set& gradient, Fibre::Strand::Set::Tensor& hessian) + { return log_prob_tpl(strands, gradient, hessian); } + + + virtual double log_prob(const Fibre::Tractlet::Set& tractlets, Fibre::Tractlet::Set& gradient, Fibre::Tractlet::Set::Tensor& hessian) + { return log_prob_tpl(tractlets, gradient, hessian); } + + + virtual double log_prob_and_fisher( const Fibre::Strand::Set& strands, + Fibre::Strand::Set& gradient, + Fibre::Strand::Set::Tensor& fisher_info) + { throw Exception ("should be implemented in derrived class."); } + + virtual double log_prob_and_fisher( const Fibre::Tractlet::Set& strands, + Fibre::Tractlet::Set& gradient, + Fibre::Tractlet::Set::Tensor& fisher_info) + { throw Exception ("should be implemented in derrived class."); } + + + template double log_prob_tpl(const typename T::Set& fibres); + + + template double log_prob_tpl(const typename T::Set& fibres, typename T::Set& gradient); + + + template double log_prob_tpl(const typename T::Set& fibres, typename T::Set& gradient, typename T::Set::Tensor& hessian); + + + virtual double log_prob(double expected, double observed) = 0; + + + virtual double b0_log_prob(double expected, double observed) = 0; + + + virtual double log_prob(double expected, double observed, double& d_lprob) = 0; + + + virtual double log_prob(double expected, double observed, double& d_lprob, double& d2_lprob2) = 0; + + + void save_expected_image(const std::string& location) //Used for debugging + { exp_image->save(location); } + + + const Image::Expected::Buffer& get_expected_image() //Used for debugging + { return *exp_image; } + + + const Image::Observed::Buffer& get_observed_image() //Used for debugging + { return obs_image; } + + + void set_enforce_bounds(bool flag); + + + void set_assumed_snr(double snr, const std::string& ref_b0, double ref_signal); + + protected: + + //! Used to get the right used gradients for the templated type. + template typename Image::Container::Buffer::Set& get_recycled_gradients(); + + //! Used to get the right used hessians for the templated type. + template typename Image::Container::Buffer::Set& get_recycled_hessians(); + + Likelihood() {} + + friend std::ostream& operator<< (std::ostream& stream, const Likelihood& likelihood); + + }; + + + } + +} + + +#endif diff --git a/src/bts/prob/likelihood/gaussian.cpp.h b/src/bts/prob/likelihood/gaussian.cpp.h new file mode 100644 index 0000000..11fd0f6 --- /dev/null +++ b/src/bts/prob/likelihood/gaussian.cpp.h @@ -0,0 +1,436 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, 23/09/2010. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + +#ifndef ___bts_prob_likelihood_imagediff_gaussian_cpp_h__ +#define ___bts_prob_likelihood_imagediff_gaussian_cpp_h__ + +namespace BTS { + + namespace Prob { + + + template double Likelihood::Gaussian::log_prob_and_fisher_tpl(const typename T::Set& fibres, typename T::Set& gradient, typename T::Set::Tensor& fisher_info, std::vector& fisher_info_gradients) { + + size_t fibres_vector_size = fibres.vsize(); + + typename Image::Reference::Buffer::Set& section_references = exp_image->expected_image_with_references(fibres); + + exp_image->precalculate_section_weighting_gradients_and_hessians(T()); + // + double lprob = 0.0; + + gradient = fibres; + fisher_info = typename T::Set::Tensor(fibres); + + gradient.zero(); + fisher_info.zero(); + + fisher_info_gradients.clear(); + + for (size_t elem_i = 0; elem_i < fibres_vector_size; elem_i++) + fisher_info_gradients.push_back(fisher_info); + + // bool has_base_intensity = fibres.has_intrinsic_property("base_intensity"); + // + // double base_intensity = 1.0; + // + // if (has_base_intensity) + // base_intensity = fibres.intrinsic_property("base_intensity"); + + + + std::vector fibre_block_start; + std::vector fibre_block_end; + + // size_t block_start = has_base_intensity; + size_t block_start = 0; + + for (size_t fibre_i = 0; fibre_i < fibres.size(); fibre_i++) { + fibre_block_start.push_back(block_start); + fibre_block_end.push_back(block_start += fibres[fibre_i].vsize()); + } + + // assert(block_start == fibre_vector_size); + + std::set coords = exp_image->non_empty_or_inbounds(); +// std::set coords; +// coords.insert(Image::Index(1,1,1)); + + //Testing + + for (std::set::iterator coord_it = coords.begin(); coord_it != coords.end(); ++coord_it) { + + Image::Expected::Voxel& voxel = exp_image->operator()(*coord_it); + + std::vector d_lprob(exp_image->num_encodings()); + std::vector d2_lprob2(exp_image->num_encodings()); + + + //--------------------------------------------------------------------------------// + // Calculate log probability and first and second derivatives for current voxel // + //--------------------------------------------------------------------------------// + for (size_t encode_i = 0; encode_i < exp_image->num_encodings(); encode_i++) { + + if (exp_image->encoding(encode_i).b_value()) { + + double observed; + + if (obs_image.in_bounds(*coord_it)) + observed = obs_image(*coord_it)[encode_i]; + else + observed = 0; + + lprob += log_prob(exp_image->operator()(*coord_it)[encode_i], observed, d_lprob[encode_i], d2_lprob2[encode_i]); + + } + + } + + + //--------------------------------------------------------------------------// + // Precalculate interpolation gradients between sections and current voxel // + //--------------------------------------------------------------------------// + + std::vector nonzero_fibres; + + for (size_t fibre_i = 0; fibre_i < fibres.size(); fibre_i++) + if (!section_references[fibre_i].is_empty(*coord_it)) { + + for (typename std::vector::iterator section_it = section_references[fibre_i](*coord_it).begin(); + section_it != section_references[fibre_i](*coord_it).end(); ++section_it) + voxel.precalculate_interpolation_gradient_and_hessian(**section_it); + + nonzero_fibres.push_back(fibre_i); + + } + + + + for (size_t encode_i = 0; encode_i < exp_image->num_encodings(); encode_i++) { + if (b0_include == "full" || exp_image->encoding(encode_i).b_value()) { + + +// if (has_base_intensity) { +// gradient.intrinsic_property("base_intensity") -= signal * diff / base_intensity; +// fisher_info(0,0) -= MR::Math::pow2(signal / base_intensity); +// } + + + std::vector< MR::Math::Vector > gradient_vectors; + std::vector< MR::Math::Matrix > hessian_matrices; + + + //-----------------------------------------------------------------------------------------------------------// + // Combine to calculate gradient and hessian for each fibre with nonzero contributions to the voxels signal // + //-----------------------------------------------------------------------------------------------------------// + + for (std::vector::iterator fibre_i_it = nonzero_fibres.begin(); fibre_i_it != nonzero_fibres.end(); ++fibre_i_it) { + + T direction_gradient (fibres[*fibre_i_it]); + typename T::Tensor direction_hessian (fibres[*fibre_i_it]); + + direction_gradient.zero(); + direction_hessian.zero(); + + std::vector& fibre_section_references = section_references[*fibre_i_it](*coord_it); + + for (typename std::vector::iterator section_it = fibre_section_references.begin(); + section_it != fibre_section_references.end(); ++section_it) { + + Fibre::Strand::BasicSection section_gradient; + Fibre::Strand::BasicSection::Tensor section_hessian; + + voxel.direction(encode_i).signal(**section_it, section_gradient, section_hessian); + + section_gradient.unnormalize_gradient(exp_image->vox_lengths()); + section_hessian.unnormalise_hessian(exp_image->vox_lengths()); + + direction_gradient.add_section_gradient(fibres[*fibre_i_it], **section_it, section_gradient); + direction_hessian.add_section_hessian(fibres[*fibre_i_it], **section_it, section_gradient, section_hessian); + + } + + direction_gradient *= fibres.base_intensity(); + direction_hessian *= fibres.base_intensity(); + + gradient_vectors.push_back(direction_gradient); + hessian_matrices.push_back(direction_hessian); + + gradient[*fibre_i_it] += direction_gradient * d_lprob[encode_i]; + + + } + + + + for (size_t nonzero_i1 = 0; nonzero_i1 < nonzero_fibres.size(); ++nonzero_i1) { + + size_t start1 = fibre_block_start[nonzero_fibres[nonzero_i1]]; + MR::Math::Vector& gradient1 = gradient_vectors[nonzero_i1]; + MR::Math::Matrix& hessian1 = hessian_matrices[nonzero_i1]; + + + for (size_t i1 = 0; i1 < gradient1.size(); i1++) + for (size_t i2 = 0; i2 < gradient1.size(); i2++) { + fisher_info(start1 + i1, start1 + i2) += d2_lprob2[encode_i] * gradient1[i1] * gradient1[i2]; +// std::cout << "fisher_info(" << start1 + i1 << ", " << start1 + i2 << ") = " << fisher_info(start1 + i1, start1 + i2) << " (" << d2_lprob2[encode_i] * gradient1[i1] * gradient1[i2] << ")" << std::endl; + } + + + + for (size_t i1 = 0; i1 < gradient1.size(); i1++) + for (size_t i2 = 0; i2 < gradient1.size(); i2++) + for (size_t i3 = 0; i3 < gradient1.size(); i3++) + fisher_info_gradients[start1 + i1](start1 + i2, start1 + i3) + += d2_lprob2[encode_i] * (hessian1(i2, i1) * gradient1[i3] + gradient1[i2] * hessian1(i3,i1)); + + + for (size_t nonzero_i2 = nonzero_i1+1; nonzero_i2 < nonzero_fibres.size(); ++nonzero_i2) { + + size_t start2 = fibre_block_start[nonzero_fibres[nonzero_i2]]; + MR::Math::Vector& gradient2 = gradient_vectors[nonzero_i2]; + + for (size_t i1 = 0; i1 < gradient1.size(); i1++) + for (size_t i2 = 0; i2 < gradient2.size(); i2++) { + + double incr = d2_lprob2[encode_i] * gradient1[i1] * gradient2[i2]; + + fisher_info(start1 + i1, start2 + i2) += incr; + fisher_info(start2 + i2, start1 + i1) += incr; + + } + + for (size_t i1 = 0; i1 < gradient1.size(); i1++) + for (size_t i2 = 0; i2 < gradient1.size(); i2++) + for (size_t i3 = 0; i3 < gradient2.size(); i3++) { + + double incr = d2_lprob2[encode_i] * hessian1(i2, i1) * gradient2[i3]; + + fisher_info_gradients[start1 + i1](start1 + i2, start2 + i3) += incr; + fisher_info_gradients[start1 + i1](start2 + i3, start1 + i2) += incr; + + } + + } + + + } + + + } + } + } + + return lprob; + + + } + + + template double Likelihood::Gaussian::log_prob_and_fisher_tpl(const typename T::Set& fibres, typename T::Set& gradient, typename T::Set::Tensor& fisher_info) { + + typename Image::Reference::Buffer::Set& section_references = exp_image->expected_image_with_references(fibres); + + exp_image->precalculate_section_weighting_gradients(T()); + + double lprob = 0.0; + + gradient = fibres; + fisher_info = typename T::Set::Tensor(fibres); + + gradient.zero(); + fisher_info.zero(); + + + + std::vector fibre_block_start; + std::vector fibre_block_end; + + // size_t block_start = has_base_intensity; + size_t block_start = 0; + + for (size_t fibre_i = 0; fibre_i < fibres.size(); fibre_i++) { + fibre_block_start.push_back(block_start); + fibre_block_end.push_back(block_start += fibres[fibre_i].vsize()); + } + + // assert(block_start == fibre_vector_size); + + std::set coords = exp_image->non_empty_or_inbounds(); + + + for (std::set::iterator coord_it = coords.begin(); coord_it != coords.end(); ++coord_it) { + + Image::Expected::Voxel& voxel = exp_image->operator()(*coord_it); + + std::vector d_lprob(exp_image->num_encodings()); + std::vector d2_lprob2(exp_image->num_encodings()); + + + //--------------------------------------------------------------------------------// + // Calculate log probability and first and second derivatives for current voxel // + //--------------------------------------------------------------------------------// + for (size_t encode_i = 0; encode_i < exp_image->num_encodings(); encode_i++) { + + if (b0_include == "full" || exp_image->encoding(encode_i).b_value()) { + + double observed; + + if (obs_image.in_bounds(*coord_it)) + observed = obs_image(*coord_it)[encode_i]; + else + observed = 0; + + lprob += log_prob(exp_image->operator()(*coord_it)[encode_i], observed, d_lprob[encode_i], d2_lprob2[encode_i]); + + } + + } + + + //--------------------------------------------------------------------------// + // Precalculate interpolation gradients between sections and current voxel // + //--------------------------------------------------------------------------// + for (size_t fibre_i = 0; fibre_i < fibres.size(); fibre_i++) + if (!section_references[fibre_i].is_empty(*coord_it)) + for (typename std::vector::iterator section_it = section_references[fibre_i](*coord_it).begin(); + section_it != section_references[fibre_i](*coord_it).end(); ++section_it) + voxel.precalculate_interpolation_gradient(**section_it); + + + + //-------------------------------------------// + // Combine to calculate gradient and fisher // + //-------------------------------------------// + + for (size_t encode_i = 0; encode_i < exp_image->num_encodings(); encode_i++) { + if (b0_include == "full" || exp_image->encoding(encode_i).b_value()) { + + + // if (has_base_intensity) { + // gradient.intrinsic_property("base_intensity") -= signal * diff / base_intensity; + // fisher_info(0,0) -= MR::Math::pow2(signal / base_intensity); + // } + + for (size_t fibre_i1 = 0; fibre_i1 < fibres.size(); fibre_i1++) { + if (!section_references[fibre_i1].is_empty(*coord_it)) { + + + //--------------------------------------------// + // Calculate the first fibre gradient vector // + //--------------------------------------------// + T gradient1 = fibres[fibre_i1]; + gradient1.zero(); + + for (typename std::vector::iterator section_it = section_references[fibre_i1](*coord_it).begin(); + section_it != section_references[fibre_i1](*coord_it).end(); ++section_it) { + + Fibre::Strand::BasicSection section_gradient; + + voxel.direction(encode_i).signal(**section_it, section_gradient); + section_gradient.unnormalize_gradient(exp_image->vox_lengths()); + gradient1.add_section_gradient(fibres[fibre_i1], **section_it, section_gradient); + + } + + gradient1 *= fibres.base_intensity(); + + MR::Math::Vector& gradient_vector1 = gradient1; + + gradient[fibre_i1] += gradient1 * d_lprob[encode_i]; + + + // if (has_base_intensity) + // for (size_t fibre_elem_i = 0; fibre_elem_i < gradient_vector1.size(); fibre_elem_i++) { + // + // size_t elem_i = fibre_block_start[fibre_i1] + fibre_elem_i; + // + // fisher_info(0, elem_i) -= gradient_vector1[fibre_elem_i] * signal; + // fisher_info(elem_i, 0) -= gradient_vector1[fibre_elem_i] * signal; + // + // } + + for (size_t fibre_i2 = 0; fibre_i2 < fibres.size(); fibre_i2++) { + if (!section_references[fibre_i2].is_empty(*coord_it)) { + + + //---------------------------------------------// + // Calculate the second fibre gradient vector // + //---------------------------------------------// + T gradient2 = fibres[fibre_i2]; + gradient2.zero(); + for (typename std::vector::iterator section_it = section_references[fibre_i2](*coord_it).begin(); + section_it != section_references[fibre_i2](*coord_it).end(); ++section_it) { + + Fibre::Strand::BasicSection section_gradient; + + voxel.direction(encode_i).signal(**section_it, section_gradient); + section_gradient.unnormalize_gradient(exp_image->vox_lengths()); + gradient2.add_section_gradient(fibres[fibre_i2], **section_it, section_gradient); + + } + + gradient2 *= fibres.base_intensity(); + + MR::Math::Vector& gradient_vector2 = gradient2; + + + //--------------------------------------------------------------------------------------------// + // Add the outer product of the two gradient vectors to the appropriate block of the Hessian // + //--------------------------------------------------------------------------------------------// + + for (size_t fibre_elem_i1 = 0; fibre_elem_i1 < gradient_vector1.size(); fibre_elem_i1++) { + + size_t elem_i1 = fibre_block_start[fibre_i1] + fibre_elem_i1; + + for (size_t fibre_elem_i2 = 0; fibre_elem_i2 < gradient_vector2.size(); fibre_elem_i2++) { + + size_t elem_i2 = fibre_block_start[fibre_i2] + fibre_elem_i2; + + fisher_info(elem_i1, elem_i2) += gradient_vector1[fibre_elem_i1] * gradient_vector2[fibre_elem_i2] * d2_lprob2[encode_i]; + + } + } + + size_t dummy = 0; + dummy++; + + } + } + + } + } + + } + } + } + + return lprob; + + } + + + } + +} + +#endif /* */ diff --git a/src/bts/prob/likelihood/gaussian.h b/src/bts/prob/likelihood/gaussian.h new file mode 100644 index 0000000..e4bebd5 --- /dev/null +++ b/src/bts/prob/likelihood/gaussian.h @@ -0,0 +1,163 @@ +/* + Copyright 2010 Brain Research Institute/National ICT Australia (NICTA), Melbourne, Australia + + Written by Thomas G Close, 5/05/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + +*/ + + +#ifndef __bts_prob_likelihood_imagediff_gaussian_h__ +#define __bts_prob_likelihood_imagediff_gaussian_h__ + + +#include "bts/prob/prob.h" +#include "bts/prob/likelihood.h" +#include "bts/prob/likelihood.h" + + +namespace BTS { + + namespace Prob { + + class Likelihood::Gaussian : public Likelihood { + + + public: + + Gaussian( const Image::Observed::Buffer& obs_image, + Image::Expected::Buffer* const exp_image, + double assumed_snr = Likelihood::SNR_DEFAULT, + const std::string& b0_include = Likelihood::B0_INCLUDE_DEFAULT, + double outside_scale = Likelihood::OUTSIDE_SCALE_DEFAULT, + const std::string& ref_b0 = Likelihood::REF_B0_DEFAULT, + double ref_signal = NAN) + + : Likelihood(obs_image, exp_image, assumed_snr, b0_include, outside_scale, ref_b0, ref_signal) {} + + + Gaussian(const Gaussian& s) + : Likelihood(s) {} + + + ~Gaussian() {} + + Gaussian& operator= (const Gaussian& s) + { this->Likelihood::operator=(s); return *this; } + + + using Likelihood::log_prob; + + double log_prob_and_fisher( const Fibre::Strand::Set& strands, + Fibre::Strand::Set& gradient, + Fibre::Strand::Set::Tensor& fisher_info, + std::vector& fisher_info_gradients) + { return log_prob_and_fisher_tpl(strands, gradient, fisher_info, fisher_info_gradients); } + + double log_prob_and_fisher( const Fibre::Tractlet::Set& tractlets, + Fibre::Tractlet::Set& gradient, + Fibre::Tractlet::Set::Tensor& fisher_info, + std::vector& fisher_info_gradients) + { return log_prob_and_fisher_tpl(tractlets, gradient, fisher_info, fisher_info_gradients); } + + + template double log_prob_and_fisher_tpl(const typename T::Set& fibres, + typename T::Set& gradient, + typename T::Set::Tensor& fisher_info, + std::vector& fisher_info_gradients); + + + double log_prob_and_fisher( const Fibre::Strand::Set& strands, + Fibre::Strand::Set& gradient, + Fibre::Strand::Set::Tensor& fisher_info) + { return log_prob_and_fisher_tpl(strands, gradient, fisher_info); } + + double log_prob_and_fisher( const Fibre::Tractlet::Set& strands, + Fibre::Tractlet::Set& gradient, + Fibre::Tractlet::Set::Tensor& fisher_info) + { return log_prob_and_fisher_tpl(strands, gradient, fisher_info); } + + + template double log_prob_and_fisher_tpl(const typename T::Set& fibres, + typename T::Set& gradient, + typename T::Set::Tensor& fisher_info); + + + double log_prob(double expected, double observed) { + + double diff = expected - observed; + + double lprob = - MR::Math::pow2(diff) / (2.0 * this->sigma2); + + //Add normalising constant. +// lprob += - MR::Math::log(MR::Math::sqrt(2.0 * M_PI * this->sigma2)); + + return lprob; + + } + + double b0_log_prob(double expected, double observed) { + + double diff = expected - observed; + + double lprob; + + if (b0_include == "full" || ((b0_include == "half") && diff > 0)) { + lprob = - MR::Math::pow2(diff) / (2.0 * this->sigma2); + //Add normalising constant. +// lprob += - MR::Math::log(MR::Math::sqrt(2.0 * M_PI * this->sigma2)); + } else + lprob = 0.0; + + + return lprob; + + } + + double log_prob(double expected, double observed, double& d_lprob) { + + double diff = expected - observed; + + d_lprob = - diff / this->sigma2; + + return log_prob(expected, observed); + + } + + double log_prob(double expected, double observed, double& d_lprob, double& d2_lprob2) { + + + d2_lprob2 = - 1.0 / this->sigma2; + + return log_prob(expected, observed, d_lprob); + + } + + + }; + + + + + + } + +} + +#include "bts/prob/likelihood/gaussian.cpp.h" + +#endif diff --git a/src/bts/prob/likelihood/one_sided_gaussian.h b/src/bts/prob/likelihood/one_sided_gaussian.h new file mode 100644 index 0000000..1834024 --- /dev/null +++ b/src/bts/prob/likelihood/one_sided_gaussian.h @@ -0,0 +1,141 @@ +/* + Copyright 2010 Brain Research Institute/National ICT Australia (NICTA), Melbourne, Australia + + Written by Thomas G Close, 5/05/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + +*/ + + +#ifndef __bts_prob_likelihood_imagediff_onesidedgaussian_h__ +#define __bts_prob_likelihood_imagediff_onesidedgaussian_h__ + + +#include "bts/prob/prob.h" +#include "bts/prob/likelihood.h" +#include "bts/prob/likelihood.h" + + +namespace BTS { + + namespace Prob { + + class Likelihood::OneSidedGaussian : public Likelihood { + + + public: + + OneSidedGaussian( const Image::Observed::Buffer& obs_image, + Image::Expected::Buffer* const exp_image, + double assumed_snr = Likelihood::SNR_DEFAULT, + const std::string& b0_include = Likelihood::B0_INCLUDE_DEFAULT, + double outside_scale = Likelihood::OUTSIDE_SCALE_DEFAULT, + const std::string& ref_b0 = Likelihood::REF_B0_DEFAULT, + double ref_signal = NAN) + + : Likelihood(obs_image, exp_image, assumed_snr, b0_include, outside_scale, ref_b0, ref_signal) {} + + + OneSidedGaussian(const OneSidedGaussian& s) + : Likelihood(s) {} + + + ~OneSidedGaussian() {} + + OneSidedGaussian& operator= (const OneSidedGaussian& s) + { this->Likelihood::operator=(s); return *this; } + + + using Likelihood::log_prob; + + + double log_prob(double expected, double observed) { + + double diff = expected - observed ; + + double lprob; + + if (diff > 0) + lprob = - MR::Math::pow2(diff) / (2.0 * this->sigma2);// - MR::Math::log(MR::Math::sqrt(2.0 * M_PI * this->sigma2)); + else + lprob = 0.0; + + return lprob; + + } + + double b0_log_prob(double expected, double observed) { + + double diff = expected - observed ; + + double lprob; + + if (this->b0_include == "full" || this->b0_include == "half") { + + if (diff > 0) + lprob = - MR::Math::pow2(diff) / (2.0 * this->sigma2);// - MR::Math::log(MR::Math::sqrt(2.0 * M_PI * this->sigma2)); + else + lprob = 0.0; + + } else + lprob = 0.0; + + + return lprob; + + } + + double log_prob(double expected, double observed, double& d_lprob) { + + double diff = expected - observed ; + + if (diff < 0) + d_lprob = - diff / this->sigma2; + else + d_lprob = 0.0; + + return log_prob(expected, observed); + + } + + double log_prob(double expected, double observed, double& d_lprob, double& d2_lprob2) { + + double diff = expected - observed ; + + if (diff < 0) + d2_lprob2 = - 1.0 / this->sigma2; + else + d2_lprob2 = 0.0; + + return log_prob(expected, observed, d_lprob); + + } + + + + }; + + + + + + } + +} + + +#endif diff --git a/src/bts/prob/likelihood/rician.h b/src/bts/prob/likelihood/rician.h new file mode 100644 index 0000000..c620b9b --- /dev/null +++ b/src/bts/prob/likelihood/rician.h @@ -0,0 +1,157 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, 26/01/2011. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + +#ifndef __bts_prob_likelihood_imagediff_rician_h__ +#define __bts_prob_likelihood_imagediff_rician_h__ + +#include "math/math.h" +#include "math/bessel.h" + +#include "bts/prob/likelihood.h" + +namespace BTS { + + namespace Prob { + + + class Likelihood::Rician : public Likelihood { + + + public: + + Rician( const Image::Observed::Buffer& obs_image, + Image::Expected::Buffer* const exp_image, + double assumed_snr = Likelihood::SNR_DEFAULT, + const std::string& b0_include = Likelihood::B0_INCLUDE_DEFAULT, + double outside_scale = Likelihood::OUTSIDE_SCALE_DEFAULT, + const std::string& ref_b0 = Likelihood::REF_B0_DEFAULT, + double ref_signal = NAN) + + : Likelihood(obs_image, exp_image, assumed_snr, b0_include, outside_scale, ref_b0, ref_signal) {} + + + Rician(const Rician& s) + : Likelihood(s) {} + + + ~Rician() {} + + Rician& operator= (const Rician& s) + { this->Likelihood::operator=(s); return *this; } + + + using Likelihood::log_prob; + + double log_prob_and_fisher( const Fibre::Strand::Set& strands, + Fibre::Strand::Set& gradient, + Fibre::Strand::Set::Tensor& fisher_info, + std::vector< MR::Math::Matrix >& fisher_info_gradients) + { return log_prob_and_fisher_tpl(strands, gradient, fisher_info, fisher_info_gradients); } + + double log_prob_and_fisher( const Fibre::Tractlet::Set& strands, + Fibre::Tractlet::Set& gradient, + Fibre::Tractlet::Set::Tensor& fisher_info, + std::vector< MR::Math::Matrix >& fisher_info_gradients) + { return log_prob_and_fisher_tpl(strands, gradient, fisher_info, fisher_info_gradients); } + + + template double log_prob_and_fisher_tpl(const typename T::Set& fibres, + typename T::Set& gradient, + typename T::Set::Tensor& fisher_info, + std::vector< MR::Math::Matrix >& fisher_info_gradients) + { throw Exception ("Not implemented yet."); } + + + double log_prob_and_fisher( const Fibre::Strand::Set& strands, + Fibre::Strand::Set& gradient, + Fibre::Strand::Set::Tensor& fisher_info) + { return log_prob_and_fisher_tpl(strands, gradient, fisher_info); } + + double log_prob_and_fisher( const Fibre::Tractlet::Set& strands, + Fibre::Tractlet::Set& gradient, + Fibre::Tractlet::Set::Tensor& fisher_info) + { return log_prob_and_fisher_tpl(strands, gradient, fisher_info); } + + + template double log_prob_and_fisher_tpl(const typename T::Set& fibres, + typename T::Set& gradient, + typename T::Set::Tensor& fisher_info) + { throw Exception ("Not implemented yet."); } + + + double log_prob(double expected, double observed) { + + assert(expected > 0.0 && observed > 0.0); + + double bessel_x = expected * observed / this->sigma2; + + double lprob = MR::Math::log(observed / this->sigma2 * + MR::Math::exp (- (MR::Math::pow2(observed) + MR::Math::pow2(expected))/ (2.0 * this->sigma2)) * + MR::Math::Bessel::I0_scaled(bessel_x)) + bessel_x; + + return lprob; + + } + + + double b0_log_prob(double expected, double observed) { + + assert(expected > 0.0 && observed > 0.0); + + double lprob; + + if (b0_include == "full") { + + double bessel_x = expected * observed / this->sigma2; + + lprob = MR::Math::log(observed / this->sigma2 * + MR::Math::exp (- (MR::Math::pow2(observed) + MR::Math::pow2(expected))/ (2.0 * this->sigma2)) * + MR::Math::Bessel::I0_scaled(bessel_x)) + bessel_x; + + } else + lprob = 0.0; + + return lprob; + + } + + + double log_prob(double expected, double observed, double& d_lprob) { + + throw Exception ("Not implemented yet."); + + } + + double log_prob(double expected, double observed, double& d_lprob, double& d2_lprob2) { + + throw Exception ("Not implemented yet."); + } + + + + }; + + } + +} + +#endif /* __bts_prob_likelihood_imagediff_rician_h__ */ diff --git a/src/bts/prob/posterior.h b/src/bts/prob/posterior.h new file mode 100644 index 0000000..72b279b --- /dev/null +++ b/src/bts/prob/posterior.h @@ -0,0 +1,59 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, Sep 28, 2010. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + +#ifndef __bts_prob_posterior_h__ +#define __bts_prob_posterior_h__ + +namespace BTS { + + namespace Prob { + + template class Posterior { + + //Public static variables, nested classes and typedefs + public: + + + //Protected member variables + protected: + + Prior* prior; + Likelihood* likelihood; + + //Public member functions + public: + + Posterior(const State& state, Prior* prior, Likelihood* likelihood) + : prior(prior->clone()), likelihood(likelihood->clone()) {} + + + //Protected member functions + protected: + + + }; + + } + +} + +#endif /* __bts_prob_posterior_h__ */ diff --git a/src/bts/prob/prior.cpp b/src/bts/prob/prior.cpp new file mode 100644 index 0000000..a39dc5f --- /dev/null +++ b/src/bts/prob/prior.cpp @@ -0,0 +1,111 @@ +/* + Copyright 2010 Brain Research Institute/National ICT Australia (NICTA), Melbourne, Australia + + Written by Thomas G Close, 5/05/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + +*/ + +#include "bts/prob/prior.h" +#include "bts/prob/prior_component/magnitude.h" +#include "bts/prob/prior_component/hook.h" +#include "bts/prob/prior_component/density.h" + +#include "bts/prob/inline_functions.h" + + +namespace BTS { + + namespace Prob { + + const char* Prior::TYPE_DEFAULT = "default"; + const double Prior::SCALE_DEFAULT = 1; + + Prior::Prior(double scale, + double mag_scale, + double mag_aux_scale, + double hook_scale, + double hook_num_points, + double density_high_scale, + double density_low_scale, + double density_num_points, + double acs_scale, + double acs_mean, + double length_scale, + double length_mean) + : scale(scale), + magnitude(mag_scale, mag_aux_scale), + hook(hook_scale, hook_num_points), + density(density_high_scale, density_low_scale, density_num_points), + acs(acs_scale, acs_mean), + length(length_scale,length_mean){} + + std::map Prior::get_component_values(const Fibre::Strand fibres) { + Fibre::Strand gradient; + gradient = fibres; + std::map component_map; + component_map[PriorComponent::Magnitude::NAME] = str(magnitude.log_prob(fibres, gradient)); + component_map[PriorComponent::Hook::NAME] = str(hook.log_prob(fibres, gradient)); + component_map[PriorComponent::Length::NAME] = str(length.log_prob(fibres, gradient)); + component_map[PriorComponent::Density::NAME] = 0.0; + component_map[PriorComponent::ACS::NAME] = 0.0; + return component_map; + } + + + std::map Prior::get_component_values(const Fibre::Tractlet fibres) { + Fibre::Tractlet gradient; + gradient = fibres; + std::map component_map; + component_map[PriorComponent::Magnitude::NAME] = str(magnitude.log_prob(fibres, gradient)); + component_map[PriorComponent::Hook::NAME] = str(hook.log_prob(fibres[0], gradient[0])); + component_map[PriorComponent::Length::NAME] = str(length.log_prob(fibres[0], gradient[0])); + component_map[PriorComponent::Density::NAME] = str(density.log_prob(fibres, gradient)); + component_map[PriorComponent::ACS::NAME] = str(acs.log_prob(fibres));; + return component_map; + } + + + + double Prior::log_prob(const Fibre::Strand strand, Fibre::Strand gradient) { + + double lprob = 0.0; + + lprob += magnitude.log_prob(strand, gradient); + lprob += hook.log_prob(strand, gradient); + lprob += length.log_prob(strand, gradient); + + return lprob; + + } + + double Prior::log_prob(const Fibre::Tractlet tractlet, Fibre::Tractlet gradient) { + + double lprob = 0.0; + + lprob += magnitude.log_prob(tractlet, gradient); + lprob += hook.log_prob(tractlet[0], gradient[0]); + lprob += length.log_prob(tractlet[0], gradient[0]); + lprob += density.log_prob(tractlet, gradient); + lprob += acs.log_prob(tractlet, gradient); + + return lprob; + + } + + } +} diff --git a/src/bts/prob/prior.cpp.h b/src/bts/prob/prior.cpp.h new file mode 100644 index 0000000..8f057b6 --- /dev/null +++ b/src/bts/prob/prior.cpp.h @@ -0,0 +1,50 @@ +/* + Copyright 2010 Brain Research Institute/National ICT Australia (NICTA), Melbourne, Australia + + Written by Thomas G Close, 5/05/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + +*/ + +#include "bts/prob/prior.h" + +#include "bts/prob/inline_functions.h" + + +namespace BTS { + + namespace Prob { + + const char* Prior::TYPE_DEFAULT = "default"; + const double Prior::SCALE_DEFAULT = 1; + + + template std::map get_component_values(const T& fibre) { + + std::map component_values; + + component_values["magnitude"] = magnitude.log_prob(fibre); + component_values["hook"] = hook.log_prob(fibre); + component_values["density"] = density.log_prob(fibre); + + return component_values; + + } + + + } +} diff --git a/src/bts/prob/prior.h b/src/bts/prob/prior.h new file mode 100644 index 0000000..3c01740 --- /dev/null +++ b/src/bts/prob/prior.h @@ -0,0 +1,289 @@ +/* + Copyright 2010 Brain Research Institute/National ICT Australia (NICTA), Melbourne, Australia + + Written by Thomas G Close, 5/05/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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 prior_option) any later version. + + BTS 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 BTS. If not, see . + +*/ + + +#ifndef __bts_prob_prior_h__ +#define __bts_prob_prior_h__ + + +//Defines the parameters that are required to initialise the prior objects. +#define PRIOR_PARAMETERS \ + Option ("prior_scale", "Scales the weight of the whole prior distribution") \ + + Argument ("prior_scale", "").type_float(0, Prob::Prior::SCALE_DEFAULT,LARGE_FLOAT), \ +\ + Option ("prior_hook", "The type of prior placed on the sheer of the secondary axes") \ + + Argument ("prior_hook_scale", "").optional().type_float(0, Prob::PriorComponent::Hook::SCALE_DEFAULT,LARGE_FLOAT) \ + + Argument ("prior_hook_num_points", "").optional().type_integer(1, Prob::PriorComponent::Hook::NUM_POINTS_DEFAULT,LARGE_INT), \ +\ + Option ("prior_mag", "The prior placed on the tractlet magnitude") \ + + Argument ("prior_mag_scale", "").optional().type_float(0, Prob::PriorComponent::Magnitude::SCALE_DEFAULT,LARGE_FLOAT) \ + + Argument ("prior_mag_aux_scale", "").optional().type_float(0, Prob::PriorComponent::Magnitude::AUX_SCALE_DEFAULT,LARGE_FLOAT), \ +\ + Option ("prior_density", "The type of prior placed on the sheer of the secondary axes") \ + + Argument ("prior_density_high_scale", "").optional().type_float(0, Prob::PriorComponent::Density::HIGH_SCALE_DEFAULT,LARGE_FLOAT) \ + + Argument ("prior_density_low_scale", "").optional().type_float(0, Prob::PriorComponent::Density::LOW_SCALE_DEFAULT,LARGE_FLOAT) \ + + Argument ("prior_density_num_points", "").optional().type_integer(1, Prob::PriorComponent::Density::NUM_POINTS_DEFAULT,LARGE_INT), \ +\ + Option ("prior_acs", "The prior placed on the tractlet acs") \ + + Argument ("prior_acs_scale", "").optional().type_float(0, Prob::PriorComponent::ACS::SCALE_DEFAULT,LARGE_FLOAT) \ + + Argument ("prior_acs_mean", "").optional().type_float(0, Prob::PriorComponent::ACS::MEAN_DEFAULT,LARGE_FLOAT), \ +\ + Option ("prior_length", "The prior placed on the tractlet length") \ + + Argument ("prior_length_scale", "").optional().type_float(0, Prob::PriorComponent::Length::SCALE_DEFAULT,LARGE_FLOAT) \ + + Argument ("prior_length_mean", "").optional().type_float(0, Prob::PriorComponent::Length::MEAN_DEFAULT,LARGE_FLOAT) \ +\ + +//Loads the 'prior' parameters into variables +#define SET_PRIOR_PARAMETERS \ + double prior_scale = Prob::Prior::SCALE_DEFAULT; \ + \ + Options prior_opt = get_options("prior_scale"); \ + if (prior_opt.size()) \ + prior_scale = prior_opt[0][0]; \ +\ + double prior_hook_scale = Prob::PriorComponent::Hook::SCALE_DEFAULT; \ + size_t prior_hook_num_points = Prob::PriorComponent::Hook::NUM_POINTS_DEFAULT; \ + \ + prior_opt = get_options("prior_hook"); \ + if (prior_opt.size()) { \ + if (prior_opt[0].size() >= 1) \ + prior_hook_scale = prior_opt[0][0]; \ + if (prior_opt[0].size() >= 2) \ + prior_hook_num_points = prior_opt[0][1]; \ + } \ + \ + double prior_mag_scale = Prob::PriorComponent::Magnitude::SCALE_DEFAULT; \ + double prior_mag_aux_scale = Prob::PriorComponent::Magnitude::AUX_SCALE_DEFAULT; \ + \ + prior_opt = get_options("prior_mag"); \ + if (prior_opt.size()) { \ + if (prior_opt[0].size() >= 1) \ + prior_mag_scale = prior_opt[0][0]; \ + if (prior_opt[0].size() >= 2) \ + prior_mag_aux_scale = prior_opt[0][1]; \ + } \ + \ + double prior_density_high_scale = Prob::PriorComponent::Density::HIGH_SCALE_DEFAULT; \ + double prior_density_low_scale = Prob::PriorComponent::Density::LOW_SCALE_DEFAULT; \ + size_t prior_density_num_points = Prob::PriorComponent::Density::NUM_POINTS_DEFAULT; \ +\ + prior_opt = get_options("prior_density"); \ + if (prior_opt.size()) { \ + if (prior_opt[0].size() >= 1) \ + prior_density_high_scale = prior_opt[0][0]; \ + if (prior_opt[0].size() >= 1) \ + prior_density_low_scale = prior_opt[0][1]; \ + if (prior_opt[0].size() >= 2) \ + prior_density_num_points = prior_opt[0][2]; \ + } \ + \ + double prior_acs_scale = Prob::PriorComponent::ACS::SCALE_DEFAULT; \ + double prior_acs_mean = Prob::PriorComponent::ACS::MEAN_DEFAULT; \ + \ + prior_opt = get_options("prior_acs"); \ + if (prior_opt.size()) { \ + if (prior_opt[0].size() >= 1) \ + prior_acs_scale = prior_opt[0][0]; \ + if (prior_opt[0].size() >= 2) \ + prior_acs_mean = prior_opt[0][1]; \ + } \ + \ + double prior_length_scale = Prob::PriorComponent::Length::SCALE_DEFAULT; \ + double prior_length_mean = Prob::PriorComponent::Length::MEAN_DEFAULT; \ + \ + prior_opt = get_options("prior_length"); \ + if (prior_opt.size()) { \ + if (prior_opt[0].size() >= 1) \ + prior_length_scale = prior_opt[0][0]; \ + if (prior_opt[0].size() >= 2) \ + prior_length_mean = prior_opt[0][1]; \ + } \ + \ + + + +//Adds the 'prior' parameters to the properties to be saved with the data. +#define ADD_PRIOR_PROPERTIES(properties) \ + if (prior_scale) { \ + properties["prior_scale"] = str(prior_scale); \ +\ + if (prior_mag_scale) { \ + properties["prior_mag_scale"] = str(prior_mag_scale); \ + properties["prior_mag_aux_scale"] = str(prior_mag_aux_scale); \ + } \ +\ + if (prior_hook_scale) { \ + properties["prior_hook_scale"] = str(prior_hook_scale); \ + properties["prior_hook_num_points"] = str(prior_hook_num_points); \ + } \ +\ + if (prior_density_high_scale) { \ + properties["prior_density_high_scale"] = str(prior_density_high_scale); \ + properties["prior_density_low_scale"] = str(prior_density_low_scale); \ + properties["prior_density_num_points"] = str(prior_density_num_points); \ + } \ +\ + if (prior_acs_scale) { \ + properties["prior_acs_scale"] = str(prior_acs_scale); \ + properties["prior_acs_mean"] = str(prior_acs_mean); \ + } \ + \ + if (prior_length_scale) { \ + properties["prior_length_scale"] = str(prior_length_scale); \ + properties["prior_length_mean"] = str(prior_length_mean); \ + } \ + } \ + +#include "bts/prob/prior_component/magnitude.h" +#include "bts/prob/prior_component/hook.h" +#include "bts/prob/prior_component/density.h" +#include "bts/prob/prior_component/acs.h" +#include "bts/prob/prior_component/length.h" + +#include "bts/common.h" + +#include "bts/prob/prob.h" + +#include "bts/fibre/strand/set.h" +#include "bts/fibre/tractlet/set.h" +#include "bts/mcmc/state.h" + + +namespace BTS { + + namespace Prob { + + class Prior { + + public: + + const static char* TYPE_DEFAULT; + const static double SCALE_DEFAULT; + + protected: + + double scale; + PriorComponent::Magnitude magnitude; + PriorComponent::Hook hook; + PriorComponent::Density density; + PriorComponent::ACS acs; + PriorComponent::Length length; + + public: + + Prior(double scale, + double mag_scale, + double mag_aux_scale, + double hook_scale, + double hook_num_points, + double density_high_scale, + double density_low_scale, + double density_num_points, + double acs_scale, + double acs_mean, + double length_scale, + double length_mean); + + Prior(const Prior& p) + : scale(p.scale), magnitude(p.magnitude), hook(p.hook), density(p.density), acs(p.acs), length(p.length) {} + + Prior& operator=(const Prior& p) + { scale =p.scale; magnitude = p.magnitude; hook = p.hook; density = p.density; acs = p.acs; length = p.length; return *this; } + + virtual ~Prior() {} + + std::vector list_components() const { + std::vector components; + components.push_back(PriorComponent::Magnitude::NAME); + components.push_back(PriorComponent::Hook::NAME); + components.push_back(PriorComponent::Density::NAME); + components.push_back(PriorComponent::ACS::NAME); + components.push_back(PriorComponent::Length::NAME); + return components; + } + + std::map get_component_values(const Fibre::Strand strand); + + std::map get_component_values(const Fibre::Tractlet tractlet); + + template std::map get_component_values(const T fibres) { + std::map overall_map, elem_map; + std::vector components = list_components(); + for (std::vector::iterator comp_it = components.begin(); comp_it != components.end(); ++comp_it) + overall_map[*comp_it] = 0.0; + for (size_t fibre_i = 0; fibre_i < fibres.size(); ++fibre_i) { + elem_map = get_component_values(fibres[fibre_i]); + for (std::map::iterator comp_it = elem_map.begin(); comp_it != elem_map.end(); ++comp_it) + overall_map[comp_it->first] += comp_it->second; + + } + return overall_map; + } + + double log_prob(const Fibre::Strand strand, Fibre::Strand gradient); + + double log_prob(const Fibre::Tractlet tractlet, Fibre::Tractlet gradient); + + template double log_prob(const T fibres, T gradient) { + + double lprob = 0.0; + + if (scale) + for (size_t fibre_i = 0; fibre_i < fibres.size(); ++fibre_i) + lprob += log_prob(fibres[fibre_i], gradient[fibre_i]); + + return lprob; + } + + template double log_prob(const T& fibre) { + + T dummy_gradient; + dummy_gradient = fibre; + + return log_prob(fibre, dummy_gradient); + + } + + template double log_prob(const T strand, T gradient, typename T::Tensor hessian) + { throw Exception ("Not implemented yet."); } + + + template double log_prob_and_fisher(const T strand, T gradient, typename T::Tensor fisher) + { throw Exception ("Not implemented yet."); } + + + template double log_prob_and_fisher(const T strand, + T gradient, typename T::Tensor fisher, + std::vector fisher_gradient) + { throw Exception ("Not implemented yet."); } + + }; + + + } + +} + + + + +#endif diff --git a/src/bts/prob/prior_component/acs.cpp b/src/bts/prob/prior_component/acs.cpp new file mode 100644 index 0000000..da0589b --- /dev/null +++ b/src/bts/prob/prior_component/acs.cpp @@ -0,0 +1,67 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + +#include "math/math.h" +#include "bts/prob/prior_component/acs.h" + + +namespace BTS { + + namespace Prob { + + namespace PriorComponent { + + const double ACS::SCALE_DEFAULT = 0.0; //1000 + const double ACS::MEAN_DEFAULT = 0.05; + const std::string ACS::NAME = "acs"; + + double ACS::log_prob(const Fibre::Tractlet tractlet) { + + return -scale * MR::Math::pow2(tractlet.acs() - mean); + + } + + + double ACS::log_prob(const Fibre::Tractlet tractlet, Fibre::Tractlet gradient) { + + assert(!gradient.is_owner()); + + // If gradient hasn't been initialised, initialise it to the size of the tractlet, otherwise check its degree. + if (!gradient.degree()) { + gradient = tractlet; + gradient.zero(); + } else if (gradient.degree() != tractlet.degree()) + throw Exception ("Tractlet degree (" + str(tractlet.degree()) + ") does not match that of the supplied gradient (" + str(gradient.degree()) + ")."); + + double lprob = -scale * MR::Math::pow2(tractlet.acs() - mean); + + if (tractlet.has_var_acs()) + gradient.acs_sqrt() -= 4.0 * scale * tractlet.acs_sqrt() * (tractlet.acs() - mean) ; + + return lprob; + } + + } + + } + +} diff --git a/src/bts/prob/prior_component/acs.h b/src/bts/prob/prior_component/acs.h new file mode 100644 index 0000000..faa49a7 --- /dev/null +++ b/src/bts/prob/prior_component/acs.h @@ -0,0 +1,83 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + + +#ifndef __bts_prob_priorcomponent_acs_h__ +#define __bts_prob_priorcomponent_acs_h__ + +#include "math/math.h" + +#include "bts/fibre/strand/set.h" + +namespace BTS { + + namespace Prob { + + namespace PriorComponent { + + class ACS { + + public: + + const static double SCALE_DEFAULT; + const static double MEAN_DEFAULT; + const static std::string NAME; + + //Protected member variables. + protected: + + double scale; + double mean; + + public: + + ACS (double scale, double mean) + : scale(scale), mean(mean) {} + + ACS(const ACS& m) + : scale(m.scale), mean(m.mean) {} + + ACS& operator=(const ACS& m) + { scale = m.scale; mean = m.mean; return *this; } + + ~ACS() {} + + ACS* clone() const + { return new ACS(*this); } + + double log_prob(const Fibre::Tractlet tractlet); + + double log_prob(const Fibre::Tractlet tractlet, Fibre::Tractlet gradient); + + const std::string& get_name() + { return NAME; } + }; + + } + + } + +} + + + +#endif diff --git a/src/bts/prob/prior_component/density.cpp b/src/bts/prob/prior_component/density.cpp new file mode 100644 index 0000000..2657c60 --- /dev/null +++ b/src/bts/prob/prior_component/density.cpp @@ -0,0 +1,66 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + + +#include "bts/fibre/track/set.h" +#include "bts/prob/prior_component/density.h" +#include "bts/prob/inline_functions.h" + +namespace BTS { + + namespace Prob { + + namespace PriorComponent { + + const double Density::HIGH_SCALE_DEFAULT = 1; + const double Density::LOW_SCALE_DEFAULT = 1; + const std::string Density::NAME = "density"; + const size_t Density::NUM_POINTS_DEFAULT = 100; + + double Density::log_prob(const Fibre::Tractlet tractlet, Fibre::Tractlet gradient) { + + double log_prob = 0.0; + gradient.invalidate(); + + std::vector areas = tractlet.cross_sectional_areas(num_points); + + for (size_t point_i = 0; point_i < num_points; ++point_i) { + + // Divide the Apparrent Connection Strength (ACS) of the tractlet by the perpendicular component of the area. + double density = tractlet.acs() / areas[point_i]; + + // Arbitrary function that makes the probability of the density being either very large or very low improbable. + log_prob -= high_scale* MR::Math::pow2(1.0 - density); + log_prob -= low_scale * MR::Math::pow2(1.0 - 1.0 / density); + + } + + return log_prob; + + + } + + } + + } + +} diff --git a/src/bts/prob/prior_component/density.h b/src/bts/prob/prior_component/density.h new file mode 100644 index 0000000..a9b9c92 --- /dev/null +++ b/src/bts/prob/prior_component/density.h @@ -0,0 +1,95 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + + +#ifndef __bts_prob_prior_tractlet_density__ +#define __bts_prob_prior_tractlet_density__ + +#include "bts/fibre/tractlet.h" +#include "bts/fibre/tractlet/tensor.h" + + + +namespace BTS { + + namespace Prob { + + namespace PriorComponent { + + class Density { + + public: + + const static double HIGH_SCALE_DEFAULT; + const static double LOW_SCALE_DEFAULT; + const static std::string NAME; + const static size_t NUM_POINTS_DEFAULT; + + protected: + + double high_scale; + double low_scale; + size_t num_points; + + public: + + Density() {} + + Density(double high_scale, + double low_scale, + size_t num_points=NUM_POINTS_DEFAULT) + : high_scale(high_scale), low_scale(low_scale), num_points(num_points) {} + + Density(const Density& d) + : high_scale(d.high_scale), low_scale(d.low_scale), num_points(num_points) {} + + Density& operator= (const Density& d) + { high_scale = d.high_scale; low_scale = d.low_scale; num_points = d.num_points; return *this; } + + Density* clone() const + { return new Density(*this); } + + double log_prob(const Fibre::Tractlet, Fibre::Tractlet gradient); + + double log_prob(const Fibre::Tractlet tractlet, Fibre::Tractlet gradient, Fibre::Tractlet::Tensor hessian) + { throw Exception ("Not implemented"); } + + double log_prob_and_fisher(const Fibre::Tractlet tractlet, Fibre::Tractlet gradient, Fibre::Tractlet::Tensor hessian) + { throw Exception ("Not implemented"); } + + double log_prob_and_fisher(const Fibre::Tractlet tractlet, Fibre::Tractlet gradient, Fibre::Tractlet::Tensor fisher, std::vector& fisher_gradient) + { throw Exception ("Not implemented"); } + + const std::string& get_name() + { return NAME; } + + }; + + } + + } + +} + + + +#endif diff --git a/src/bts/prob/prior_component/hook.cpp b/src/bts/prob/prior_component/hook.cpp new file mode 100644 index 0000000..10d091d --- /dev/null +++ b/src/bts/prob/prior_component/hook.cpp @@ -0,0 +1,88 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + +#include "bts/prob/prior_component/hook.h" + +#include "bts/prob/inline_functions.h" + +namespace BTS { + + namespace Prob { + + namespace PriorComponent { + + const double Hook::SCALE_DEFAULT = 50.0; + const std::string Hook::NAME = "hook"; + const size_t Hook::NUM_POINTS_DEFAULT = 100; + + double Hook::log_prob(const Fibre::Strand strand, Fibre::Strand gradient) { + + double lprob = 0.0; + gradient.invalidate(); + + std::pair endpoints = strand.endpoints(); + Coord end_to_end = endpoints.second - endpoints.second; + Coord normed_end_to_end = end_to_end.normalise(); + double end_to_end_length = end_to_end.norm2(); + + Fibre::Track track(strand, num_points); + + for (size_t point_i = 0; point_i < num_points; ++point_i) { + + Coord start_diff = track[point_i] - endpoints.first; + double start_dot = normed_end_to_end.dot(start_diff); + + //If the point on the track is before the start point of the strand w.r.t. the ultimate endpoint of the strand + if (start_dot < 0.0) { + double start_dist2 = start_diff.norm2(); + lprob -= 0.5 * MR::Math::pow2(start_dot) / (start_dist2 * end_to_end_length); + } else { + + Coord end_diff = track[point_i] - endpoints.second; + double end_dot = normed_end_to_end.dot(end_diff); + + if (end_dot > 0.0) { + double end_dist2 = end_diff.norm2(); + lprob -= 0.5 * MR::Math::pow2(end_dot) / (end_dist2 * end_to_end_length); + + } + + } + + } + + lprob *= scale; + return lprob; + } + + + double Hook::log_prob(const Fibre::Strand& strand, Fibre::Strand& gradient, Fibre::Strand::Tensor& hessian) { + + throw Exception("Not implemented yet"); + + } + + } + + } + +} diff --git a/src/bts/prob/prior_component/hook.h b/src/bts/prob/prior_component/hook.h new file mode 100644 index 0000000..e0b9100 --- /dev/null +++ b/src/bts/prob/prior_component/hook.h @@ -0,0 +1,85 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + + +#ifndef __bts_prob_prior_strand_hook_h__ +#define __bts_prob_prior_strand_hook_h__ + +#include "math/math.h" + +#include "bts/fibre/strand/set.h" + +namespace BTS { + + namespace Prob { + + namespace PriorComponent { + + class Hook { + + public: + + const static double SCALE_DEFAULT; + const static std::string NAME; + const static bool ACTIVE_DEFAULT; + const static size_t NUM_POINTS_DEFAULT; + + + //Protected member variables. + protected: + + double scale; + size_t num_points; + + public: + + Hook (double scale, size_t num_points) + : scale(scale), num_points(num_points) {} + + Hook(const Hook& m) + : scale(m.scale), num_points(m.num_points) {} + + Hook& operator=(const Hook& m) + { scale = m.scale; num_points = m.num_points; return *this; } + + ~Hook() {} + + Hook* clone() const + { return new Hook(*this); } + + double log_prob(const Fibre::Strand strand, Fibre::Strand gradient); + + double log_prob(const Fibre::Strand& strand, Fibre::Strand& gradient, Fibre::Strand::Tensor& hessian); + + const std::string& get_name() + { return NAME; } + }; + + } + + } + +} + + + +#endif diff --git a/src/bts/prob/prior_component/length.cpp b/src/bts/prob/prior_component/length.cpp new file mode 100644 index 0000000..ec2a46c --- /dev/null +++ b/src/bts/prob/prior_component/length.cpp @@ -0,0 +1,68 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + +#include "math/math.h" +#include "bts/prob/prior_component/length.h" + + +namespace BTS { + + namespace Prob { + + namespace PriorComponent { + + const double Length::SCALE_DEFAULT = 0.0; //10 + const double Length::MEAN_DEFAULT = 0.05; + const std::string Length::NAME = "length"; + + double Length::log_prob(const Fibre::Strand strand) { + + return - scale * MR::Math::pow2(strand[1].norm() - mean); + + } + + + double Length::log_prob(const Fibre::Strand strand, Fibre::Strand gradient) { + + assert(!gradient.is_owner()); + + // If gradient hasn't been initialised, initialise it to the size of the tractlet, otherwise check its degree. + if (!gradient.degree()) { + gradient = strand; + gradient.zero(); + } else if (gradient.degree() != strand.degree()) + throw Exception ("Tractlet degree (" + str(strand.degree()) + ") does not match that of the supplied gradient (" + str(gradient.degree()) + ")."); + + double lprob = -scale * MR::Math::pow2(strand[1].norm() - mean); + + gradient[1][X] = -2.0 * scale * strand[1][X] * (strand[1].norm() - mean) / strand[1].norm(); + gradient[1][Y] = -2.0 * scale * strand[1][Y] * (strand[1].norm() - mean) / strand[1].norm(); + gradient[1][Z] = -2.0 * scale * strand[1][Z] * (strand[1].norm() - mean) / strand[1].norm(); + + return lprob; + } + + } + + } + +} diff --git a/src/bts/prob/prior_component/length.h b/src/bts/prob/prior_component/length.h new file mode 100644 index 0000000..b7efac4 --- /dev/null +++ b/src/bts/prob/prior_component/length.h @@ -0,0 +1,83 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + + +#ifndef __bts_prob_priorcomponent_length_h__ +#define __bts_prob_priorcomponent_length_h__ + +#include "math/math.h" + +#include "bts/fibre/strand/set.h" + +namespace BTS { + + namespace Prob { + + namespace PriorComponent { + + class Length { + + public: + + const static double SCALE_DEFAULT; + const static double MEAN_DEFAULT; + const static std::string NAME; + + //Protected member variables. + protected: + + double scale; + double mean; + + public: + + Length (double scale, double mean) + : scale(scale), mean(mean) {} + + Length(const Length& m) + : scale(m.scale), mean(m.mean) {} + + Length& operator=(const Length& m) + { scale = m.scale; mean = m.mean; return *this; } + + ~Length() {} + + Length* clone() const + { return new Length(*this); } + + double log_prob(const Fibre::Strand strand); + + double log_prob(const Fibre::Strand strand, Fibre::Strand gradient); + + const std::string& get_name() + { return NAME; } + }; + + } + + } + +} + + + +#endif diff --git a/src/bts/prob/prior_component/magnitude.cpp b/src/bts/prob/prior_component/magnitude.cpp new file mode 100644 index 0000000..137beda --- /dev/null +++ b/src/bts/prob/prior_component/magnitude.cpp @@ -0,0 +1,260 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + +#include "bts/prob/prior_component/magnitude.h" + +#include "bts/prob/inline_functions.h" + +namespace BTS { + + namespace Prob { + + namespace PriorComponent { + + const double Magnitude::SCALE_DEFAULT = 25.0; + const double Magnitude::AUX_SCALE_DEFAULT = 75.0; + const std::string Magnitude::NAME = "magnitude"; + + double Magnitude::log_prob(const Fibre::Strand strand, Fibre::Strand gradient) { + + double lprob = 0.0; + gradient.zero(); + + const Triple& v1 = strand[1]; + + double v1_norm2 = v1.norm2(); + + for (size_t degree_i = 2; degree_i < strand.degree(); degree_i++) { + + const Triple& vm = strand[degree_i]; + double vm_norm2 = vm.norm2(); + + if (v1_norm2) { + + lprob -= scale * MR::Math::pow2(degree_i) * vm_norm2 / v1_norm2; + +#ifndef GRADIENT_NOT_REQUIRED + //The gradient of the curve magnitude w.r.t. Vm. + gradient[degree_i] -= vm * 2.0 * MR::Math::pow2(degree_i) * scale / v1_norm2; + + //The gradient of the curve magnitude w.r.t. V1. + gradient[1] += v1 * 2.0 * MR::Math::pow2(degree_i) * scale * vm_norm2/(v1_norm2 * v1_norm2); +#endif + + } else if (vm_norm2) // If v1 is zero and vm is non zero set the probability to be very low + lprob = -LARGE_FLOAT; + } + + return lprob; + + } + +// double Magnitude::log_prob(const Fibre::Strand& strand, Fibre::Strand& gradient, Fibre::Strand::Tensor& hessian) { +// +// double lprob = 0.0; +// gradient.zero(); +// +// hessian.reset(strand); +// +// const Triple& v1 = strand[1]; +// +// double v1_norm2 = v1.norm2(); +// +// for (size_t degree_i = 2; degree_i < strand.degree(); degree_i++) { +// +// const Triple& vm = strand[degree_i]; +// double vm_norm2 = vm.norm2(); +// +// lprob -= scale * degree_i * vm_norm2 / v1_norm2; +// +// #ifndef GRADIENT_NOT_REQUIRED +// //The gradient of the curve magnitude w.r.t. Vm. +// gradient[degree_i] -= vm * 2.0 * degree_i * scale / v1_norm2; +// +// //The gradient of the curve magnitude w.r.t. V1. +// gradient[1] += v1 * 2.0 * scale * degree_i * vm_norm2/(v1_norm2 * v1_norm2); +// +// #ifndef HESSIAN_NOT_REQUIRED +// +// for (size_t dim_i1 = 0; dim_i1 < 3; dim_i1++) { +// +// hessian(degree_i,dim_i1,degree_i,dim_i1) -= 2.0 * degree_i * scale / v1_norm2; +// hessian(1, dim_i1, 1, dim_i1) += 2.0 * scale * degree_i * vm_norm2 / MR::Math::pow2(v1_norm2); +// +// for (size_t dim_i2 = 0; dim_i2 < 3; dim_i2++) { +// +// hessian(degree_i, dim_i1, 1, dim_i2) += 4.0 * scale * degree_i * vm[dim_i1] * v1[dim_i2] / MR::Math::pow2(v1_norm2); +// hessian(1, dim_i1, degree_i, dim_i2) += 4.0 * scale * degree_i * v1[dim_i1] * vm[dim_i2] / MR::Math::pow2(v1_norm2); +// +// hessian(1, dim_i1, 1, dim_i2) -= 8.0 * scale * degree_i * v1[dim_i1] * v1[dim_i2] * vm_norm2 / MR::Math::pow3(v1_norm2); +// } +// +// +// } +// +// +// #endif +// +// #endif +// +// } +// +// +// return lprob; +// +// } + + + double Magnitude::log_prob(const Fibre::Tractlet tractlet, Fibre::Tractlet gradient) { + + gradient.zero(); + + double lprob = log_prob(tractlet[0], gradient[0]); + + const Coord v1 = tractlet(0,1); + + double v1_norm2 = v1.norm2(); + + for (size_t ax_i = 1; ax_i < 3; ++ax_i) { + for (size_t degree_i = 1; degree_i < tractlet.degree(); degree_i++) { + + const Coord vm = tractlet(ax_i,degree_i); + double vm_norm2 = vm.norm2(); + + if (v1_norm2) { + + lprob -= scale * MR::Math::pow2(degree_i) * vm_norm2 / v1_norm2; + + #ifndef GRADIENT_NOT_REQUIRED + //The gradient of the curve magnitude w.r.t. Vm. + gradient(ax_i, degree_i) -= vm * 2.0 * MR::Math::pow2(degree_i) * scale / v1_norm2; + + //The gradient of the curve magnitude w.r.t. V1. + gradient(0,1) += v1 * 2.0 * MR::Math::pow2(degree_i) * scale * vm_norm2/(v1_norm2 * v1_norm2); + #endif + + } else if (vm_norm2) // If v1 is zero and vm is non zero set the probability to be very low + lprob = -LARGE_FLOAT; + } + } + + return lprob; + + } + + +// +// double Magnitude::log_prob_and_fisher(const Fibre::Strand& strand, Fibre::Strand& gradient, Fibre::Strand::Tensor& fisher) { +// +// double log_prob = 0.0; +// gradient.zero(); +// +// fisher.reset(strand); +// +// const Coord v1 = strand[1]; +// +// double v1_norm2 = v1.norm2(); +// +// for (size_t degree_i = 2; degree_i < strand.degree(); degree_i++) { +// +// Coord vm = strand[degree_i]; +// double vm_norm2 = vm.norm2(); +// +// log_prob -= degree_i * scale * vm_norm2 / v1_norm2; +// +// #ifndef GRADIENT_NOT_REQUIRED +// //The gradient of the curve magnitude w.r.t. Vm. +// gradient[degree_i] -= vm * 2.0 * degree_i * scale / v1_norm2; +// +// //The gradient of the curve magnitude w.r.t. V1. +// gradient[1] += v1 * 2.0 * degree_i * scale * vm_norm2/(v1_norm2 * v1_norm2); +// +// for (size_t dim_i1 = 0; dim_i1 < 3; dim_i1++) +// fisher(degree_i, dim_i1, degree_i, dim_i1) += 2.0 * degree_i * scale / v1_norm2; +// +// #endif +// +// } +// +// +// return log_prob; +// +// } +// +// +// double Magnitude::log_prob_and_fisher(const Fibre::Strand& strand, Fibre::Strand& gradient, Fibre::Strand::Tensor& fisher, std::vector& fisher_gradient) { +// +// double lprob = 0.0; +// gradient.zero(); +// +// size_t vector_size = strand.vsize(); +// +// fisher.reset(strand); +// +// //TODO: Make reset function to do this +// fisher_gradient.resize(vector_size); +// for (size_t elem_i = 0; elem_i < vector_size; ++elem_i) +// fisher_gradient[elem_i].reset(strand); +// +// const Coord v1 = strand[1]; +// +// double v1_norm2 = v1.norm2(); +// +// for (size_t degree_i = 2; degree_i < strand.degree(); degree_i++) { +// +// const Triple& vm = strand[degree_i]; +// double vm_norm2 = vm.norm2(); +// +// lprob -= degree_i * scale * vm_norm2 / v1_norm2; +// +// #ifndef GRADIENT_NOT_REQUIRED +// //The gradient of the curve magnitude w.r.t. Vm. +// gradient[degree_i] -= vm * 2.0 * degree_i * scale / v1_norm2; +// +// //The gradient of the curve magnitude w.r.t. V1. +// gradient[1] += v1 * 2.0 * degree_i * scale * vm_norm2/(v1_norm2 * v1_norm2); +// +// for (size_t dim_i1 = 0; dim_i1 < 3; dim_i1++) { +// +// fisher(degree_i, dim_i1, degree_i, dim_i1) += 2.0 * degree_i * scale / v1_norm2; +// +// //TODO: Make this independent of whether the strand has an acs; +// for (size_t dim_i2 = 0; dim_i2 < 3; dim_i2++) +// fisher_gradient[dim_i2 + 3 + strand.has_var_acs()](degree_i, dim_i1, degree_i, dim_i1) -= 4.0 * degree_i * scale * v1[dim_i2] / MR::Math::pow2(v1_norm2); +// +// } +// +// +// #endif +// +// } +// +// +// return lprob; +// +// } + + } + + } + +} diff --git a/src/bts/prob/prior_component/magnitude.h b/src/bts/prob/prior_component/magnitude.h new file mode 100644 index 0000000..20d35cd --- /dev/null +++ b/src/bts/prob/prior_component/magnitude.h @@ -0,0 +1,92 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + + +#ifndef __bts_prob_prior_strand_curvature_h__ +#define __bts_prob_prior_strand_curvature_h__ + +#include "math/math.h" + +#include "bts/fibre/strand/set.h" +#include "bts/fibre/strand/tensor.h" +#include "bts/fibre/strand/set/tensor.h" + +namespace BTS { + + namespace Prob { + + namespace PriorComponent { + + class Magnitude { + + public: + + const static double SCALE_DEFAULT; + const static double AUX_SCALE_DEFAULT; + const static std::string NAME; + + //Protected member variables. + protected: + + double scale; + double aux_scale; + + public: + + Magnitude (double scale, double aux_scale) + : scale(scale), aux_scale(aux_scale) {} + + Magnitude(const Magnitude& m) + : scale(m.scale), aux_scale(aux_scale) {} + + Magnitude& operator=(const Magnitude& m) + { scale = m.scale; aux_scale = m.aux_scale; return *this; } + + ~Magnitude() {} + + Magnitude* clone() const + { return new Magnitude(*this); } + + double log_prob(const Fibre::Strand strand, Fibre::Strand gradient); + + double log_prob(const Fibre::Tractlet, Fibre::Tractlet gradient); + + double log_prob(const Fibre::Strand strand, Fibre::Strand gradient, Fibre::Strand::Tensor hessian) { throw Exception ("Not implemented yet."); } + + double log_prob_and_fisher(const Fibre::Strand strand, Fibre::Strand gradient, Fibre::Strand::Tensor fisher) { throw Exception ("Not implemented yet."); } + + + double log_prob_and_fisher(const Fibre::Strand strand, Fibre::Strand gradient, Fibre::Strand::Tensor fisher, std::vector& fisher_gradient) { throw Exception ("Not implemented yet."); } + + const std::string& get_name() + { return NAME; } + }; + + } + + } + +} + + + +#endif diff --git a/src/bts/prob/prob.h b/src/bts/prob/prob.h new file mode 100644 index 0000000..a17bd8e --- /dev/null +++ b/src/bts/prob/prob.h @@ -0,0 +1,40 @@ +/* + Copyright 2010 Brain Research Institute/National ICT Australia (NICTA), Melbourne, Australia + + Written by Thomas G Close, 5/05/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + +*/ + +#ifndef __bts_prob_prob_h__ +#define __bts_prob_prob_h__ + +#include "bts/common.h" + +namespace BTS { + + namespace Prob { + + const static size_t STRONG_ERROR = 0; + const static size_t WEAK_ERROR = 1; + + } + +} + + +#endif diff --git a/src/bts/prob/test/bayes_log_regression.cpp b/src/bts/prob/test/bayes_log_regression.cpp new file mode 100644 index 0000000..e93aa38 --- /dev/null +++ b/src/bts/prob/test/bayes_log_regression.cpp @@ -0,0 +1,176 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, 01/10/2010. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + +#include "bts/prob/test/bayes_log_regression.h" +#include "bts/mcmc/state/tensor.h" + +namespace BTS { + + namespace Prob { + + namespace Test { + + const char* BayesLogRegression::DATA_LOCATION_DEFAULT = "/home/tclose/data/prob/test/bayes_log_regression/australian.txt"; + const size_t BayesLogRegression::POLY_ORDER_DEFAULT = 1; + const float BayesLogRegression::PRIOR_VARIANCE_DEFAULT = 100.0; + + + BayesLogRegression::BayesLogRegression(const std::string& location, size_t poly_order, double alpha) + : poly_order(poly_order), alpha(alpha) { + + MR::Math::Matrix loaded_data (location); + MR::Math::Matrix X = loaded_data.sub(0, loaded_data.rows(), 0, loaded_data.columns()-1); + t = loaded_data.column(loaded_data.columns()-1); + + XX.resize(X.rows(), X.columns() * poly_order + 1); + XX.column(0) = 1.0; + + for (size_t poly_i = 0; poly_i < poly_order; ++poly_i) + for (size_t col_i = 0; col_i < X.columns(); ++col_i) + for (size_t row_i = 0; row_i < X.rows(); ++row_i) + XX(row_i, poly_i*X.columns() + col_i + 1) = MR::Math::pow(X(row_i, col_i), poly_i+1); + + + N = XX.rows(); + D = XX.columns(); + + f.resize(N); + working.resize(D,N); + v.resize(N); + p.resize(N); + V.resize(D,N); + + Z2.resize(N,D); + + + } + + + + double BayesLogRegression::log_prob (const MR::Math::Vector& w) { + + + double lprior = 0.0; + + for (size_t d = 0; d < D; ++d) + lprior -= 0.5 * MR::Math::log(2.0 * M_PI * alpha) - MR::Math::pow2(w[d]) / (2.0 * alpha); + + MR::Math::mult(f, XX, w); + + double llike = MR::Math::dot(f,t); + + for (size_t n = 0; n < N; ++n) + llike -= MR::Math::log(1.0 + MR::Math::exp(f[n])); + + return lprior + llike; + + } + + + double BayesLogRegression::log_prob (const MR::Math::Vector& w, MR::Math::Vector& d_w) { + + MR::Math::mult(f, XX, w); + + for (size_t n = 0; n < N; ++n) + v[n] = t[n] - 1.0 / ( 1.0 + MR::Math::exp(-f[n])); + + MR::Math::mult(d_w, 0.0, 1.0, CblasTrans, XX, v); + + for (size_t d = 0; d < D; ++d) + d_w[d] -= 1.0 / alpha * w[d]; + + return log_prob(w); + + } + + + double BayesLogRegression::log_prob_and_fisher (const MR::Math::Vector& w, MR::Math::Vector& d_w, MR::Math::Matrix& G) { + + assert(w.size() == D); + + G.resize(D,D); + d_w.resize(D); + + MR::Math::mult(f, XX, w); + + for (size_t n = 0; n < N; ++n) { + p[n] = 1/(1 + MR::Math::exp(-f[n])); + v[n] = p[n] * (1 - p[n]); + for (size_t d = 0; d < D; ++d) + working(d,n) = v[n] * XX(n,d); + } + + + MR::Math::mult(G, working, XX); + + for (size_t d = 0; d < D; ++d) + G(d,d) += 1.0/alpha; + + return log_prob(w, d_w); + + + } + + + double BayesLogRegression::log_prob_and_fisher (const MR::Math::Vector& w, MR::Math::Vector& d_w, MR::Math::Matrix& G, std::vector& d_G) { + + d_G.clear(); + d_G.resize(D, MCMC::State::Tensor(w)); + + Z = 0.0; + + MR::Math::mult(f, XX, w); + + for (size_t n = 0; n < N; ++n) { + p[n] = 1/(1 + MR::Math::exp(-f[n])); + v[n] = p[n] * (1 - p[n]); + for (size_t d = 0; d < D; ++d) + V(d,n) = v[n]; + } + + for (size_t d = 0; d < D; ++d) { + + for (size_t n = 0; n < N; ++n) { + double z1 = (1.0 - 2.0 * p[n]) * XX(n,d) * v[n]; + for (size_t d2 = 0; d2 < D; ++d2) + Z2(n,d2) = XX(n,d2) * z1; + } + + MR::Math::Matrix d_G_d; + + MR::Math::mult(d_G_d, 1.0, CblasTrans, XX, CblasNoTrans, Z2); + + d_G[d] = d_G_d; + + } + + + return log_prob_and_fisher(w, d_w, G); + + } + + + } + + } + +} diff --git a/src/bts/prob/test/bayes_log_regression.h b/src/bts/prob/test/bayes_log_regression.h new file mode 100644 index 0000000..0a9a335 --- /dev/null +++ b/src/bts/prob/test/bayes_log_regression.h @@ -0,0 +1,95 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, 01/10/2010. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + +#ifndef __bts_prob_test_bayeslogregression_h__ +#define __bts_prob_test_bayeslogregression_h__ + +#include +#include + +#include "math/vector.h" +#include "math/matrix.h" +#include "math/math.h" + +#include "bts/mcmc/state.h" + +namespace BTS { + + namespace Prob { + + namespace Test { + + class BayesLogRegression { + + public: + + const static char* DATA_LOCATION_DEFAULT; + const static size_t POLY_ORDER_DEFAULT; + const static float PRIOR_VARIANCE_DEFAULT; + +// protected: + + MR::Math::Matrix X; + MR::Math::Matrix XX; + MR::Math::Vector t; + + MR::Math::Vector f; + MR::Math::Matrix working; + MR::Math::Vector v; + MR::Math::Vector p; + MR::Math::Matrix V; + MR::Math::Matrix Z; + MR::Math::Matrix Z1; + MR::Math::Matrix Z2; + + size_t poly_order; + double alpha; + size_t D; + size_t N; + + + public: + + BayesLogRegression(const std::string& location, size_t poly_order = 1, double alpha = 100.0); + + + double log_prob (const MR::Math::Vector& w); + + + double log_prob (const MR::Math::Vector& w, MR::Math::Vector& d_w); + + + double log_prob_and_fisher (const MR::Math::Vector& w, MR::Math::Vector& d_w, MR::Math::Matrix& G); + + + double log_prob_and_fisher (const MR::Math::Vector& w, MR::Math::Vector& d_w, MR::Math::Matrix& G, std::vector& d_G); + + + }; + + } + + } + +} + +#endif /* __bts_prob_test_bayeslogregression_h__ */ diff --git a/src/bts/prob/test/gaussian.cpp b/src/bts/prob/test/gaussian.cpp new file mode 100644 index 0000000..bb9a067 --- /dev/null +++ b/src/bts/prob/test/gaussian.cpp @@ -0,0 +1,76 @@ +/* + * test_gaussian.cpp + * tractography + * + * Created by Tom Close on 16/12/09. + * Copyright 2009 National ICT Australia (NICTA). All rights reserved. + * + */ + +#include "bts/prob/test/gaussian.h" +#include "bts/mcmc/state/tensor.h" + +#include "bts/prob/inline_functions.h" + +#include "bts/image/buffer.cpp.h" + +namespace BTS { + + namespace Prob { + + namespace Test { + + const char* Gaussian::AXIS_SCALES_LOCATION_DEFAULT = "/home/tclose/data/prob/test/gaussian/axis_scales.sta"; + + + double Gaussian::log_prob(const MCMC::State& state) { + + double log_prob = 0.0; + + for (size_t i = 0; i < state.size(); i++) + log_prob += -MR::Math::pow2(state[i]) * axis_scales[i]; + + return log_prob; + + } + + + double Gaussian::log_prob(const MCMC::State& state, MCMC::State& gradient) { + + for (size_t i = 0; i < state.size(); i++) + gradient[i] = -2.0 * state[i] * axis_scales[i]; + + return log_prob(state); + + } + + + double Gaussian::log_prob(const MCMC::State& state, MCMC::State& gradient, MCMC::State::Tensor& hessian) { + + hessian.zero(); + + for (size_t i = 0; i < state.size(); i++) + hessian(i,i) = 2.0 * axis_scales[i]; + + return log_prob(state, gradient); + + } + + double Gaussian::log_prob_and_fisher(const MCMC::State& state, MCMC::State& gradient, MCMC::State::Tensor& fisher, std::vector& fisher_gradient) { + + fisher_gradient.resize(state.size()); + + for (size_t i = 0; i < state.size(); i++) { + fisher_gradient[i].resize(state.size(), state.size()); + fisher_gradient[i] = 0.0; + } + + return log_prob(state, gradient, fisher); + + } + + } + + } + +} diff --git a/src/bts/prob/test/gaussian.h b/src/bts/prob/test/gaussian.h new file mode 100644 index 0000000..be337e1 --- /dev/null +++ b/src/bts/prob/test/gaussian.h @@ -0,0 +1,100 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + + +#ifndef __bts_prob_testgaussian__ +#define __bts_prob_testgaussian__ + + + +#include "bts/prob/likelihood.h" +#include "bts/prob/prior.h" + +//TODO: remove +#include "bts/image/expected/buffer.h" +#include "bts/mcmc/state.h" + +namespace BTS { + + namespace Prob { + + namespace Test { + + class Gaussian { + + public: + + const static char* AXIS_SCALES_LOCATION_DEFAULT; + + + protected: + + MR::Math::Vector& axis_scales; + + public: + + //TODO: remove + BTS::Image::Expected::Buffer* exp_image; + + Gaussian(MR::Math::Vector& axis_scales) : axis_scales(axis_scales) {} + + double log_prob(const MCMC::State& test_state); + + double log_prob(const MCMC::State& test_state, MCMC::State& gradient); + + double log_prob(const MCMC::State& test_state, MCMC::State& gradient, MCMC::State::Tensor& hessian); + + double log_prob_and_fisher(const MCMC::State& test_state, MCMC::State& gradient, MCMC::State::Tensor& fisher) + { return log_prob(test_state,gradient,fisher); } + + + double log_prob_and_fisher(const MCMC::State& test_state, MCMC::State& gradient, MCMC::State::Tensor& fisher, std::vector& fisher_gradient); + + void set_assumed_snr(double assumed_snr, const std::string& ref_b0, double ref_signal) {} + + void set_enforce_bounds(bool flag) {} + + std::vector list_components() { return std::vector(); } + + template std::map get_component_values(T& t) { return std::map(); } + + + friend std::ostream& operator<< (std::ostream& stream, const Gaussian& test); + + }; + + inline std::ostream& operator<< (std::ostream& stream, const Gaussian& test) { + + + stream << "Axis scales: " << test.axis_scales << std::endl; + + return stream; + + } + + } + + } + +} + +#endif diff --git a/src/bts/prob/test/landscape.cpp b/src/bts/prob/test/landscape.cpp new file mode 100644 index 0000000..5473944 --- /dev/null +++ b/src/bts/prob/test/landscape.cpp @@ -0,0 +1,350 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + + +extern "C" { +#include +#include +} + +#include "bts/prob/test/landscape.h" +#include "bts/prob/test/landscape/peak.h" +#include "bts/prob/test/landscape/peak/writer.h" +#include "bts/prob/test/landscape/peak/reader.h" + +#include "bts/prob/inline_functions.h" + +#include "bts/image/buffer.cpp.h" +#include "bts/math/common.h" + +namespace BTS { + + namespace Prob { + + namespace Test { + + const char* Landscape::LOCATION_DEFAULT = "/home/tclose/data/prob/test/landscape/a.lnd"; + const double Landscape::WIDTH_MU_DEFAULT = 10; + const double Landscape::WIDTH_SIGMA_DEFAULT = 5; + const double Landscape::WIDTH_MIN_DEFAULT = 15; + const double Landscape::HEIGHT_VAR_DEFAULT = 6; + const double Landscape::ROI_RADIUS_DEFAULT = 10.0; + const double Landscape::FRACTION_PYRAMID_DEFAULT = 0.0; + const double Landscape::BARRIER_RATE_DEFAULT = 0.3; + + Landscape::Landscape(double roi_radius, double barrier_rate) + : roi_radius (roi_radius), barrier_rate(barrier_rate) {} + + Landscape::Landscape(const std::string& location, double roi_radius, double barrier_rate) + : roi_radius(roi_radius), barrier_rate(barrier_rate) { load(location); } + + + Landscape Landscape::randomly_generate( size_t ndims, + size_t num_peaks, + double peak_width_mu, + double peak_width_sigma, + double peak_width_min, + double peak_height_var, + double roi_radius, + double fraction_pyramid, + double barrier_rate, + size_t seed) { + + Landscape landscape; + + landscape.ndims = ndims; + landscape.roi_radius = roi_radius; + landscape.barrier_rate = barrier_rate; + + gsl_rng* rand_gen = gsl_rng_alloc(gsl_rng_taus); + gsl_rng_set(rand_gen, seed); + + for (size_t peak_i = 0; peak_i < num_peaks; peak_i++) { + + // Rejection sampling to get peaks randomly distributed within the roi_radius. + MCMC::State centre(ndims); + + for (size_t dim_i = 0; dim_i < ndims; ++dim_i) + centre[dim_i] = roi_radius; + + while (centre.norm() >= roi_radius) + for (size_t dim_i = 0; dim_i < ndims; ++dim_i) + centre[dim_i] = gsl_ran_flat(rand_gen, -roi_radius, roi_radius); + + MCMC::State::Tensor widths(ndims); + + MR::Math::Matrix eig_matrix(ndims,ndims), working(ndims,ndims); + + eig_matrix = 0; + + for (size_t dim_i = 0; dim_i < 2; dim_i++) { + double width = MR::Math::sqrt(MR::Math::pow2(gsl_ran_gaussian(rand_gen, peak_width_sigma) + peak_width_mu * (1.0 - peak_width_min)) + + MR::Math::pow2(gsl_ran_gaussian(rand_gen, peak_width_sigma) + peak_width_mu * (1.0 - peak_width_min))) / M_SQRT2; + + width += peak_width_min * peak_width_mu; + + eig_matrix(dim_i,dim_i) = 3.0 / MR::Math::pow2(width); + } + + MR::Math::Matrix rotate_matrix = Math::random_rotation(rand_gen, ndims); + + MR::Math::mult(working, eig_matrix, rotate_matrix); + MR::Math::mult(widths, 1.0, CblasTrans, rotate_matrix, CblasNoTrans, working); + + // Rayleigh distribution for peak height. + double height = gsl_ran_gaussian(rand_gen, peak_height_var); + + size_t type = 0; + + // Select the peak to be a pyramid instead of a gaussian with probability = fraction_pyramid. + if (gsl_ran_flat(rand_gen, 0.0, 1.0) < fraction_pyramid) + type = 1; + + // Create peak object. + Peak peak(ndims, centre, widths, height, type); + + landscape.peaks.push_back(peak); + + } + + gsl_rng_free(rand_gen); + + return landscape; + + } + + Landscape::~Landscape() {} + + + double Landscape::log_prob(const MCMC::State& state) { + + MCMC::State dummy; + + return log_prob(state, dummy); + + + } + + + double Landscape::log_prob(const MCMC::State& state, MCMC::State& gradient) { + + double log_prob = 0.0; + gradient.zero(); + + MCMC::State peak_gradient; + + for (std::vector::iterator peak_it = peaks.begin(); peak_it != peaks.end(); ++peak_it) { + + log_prob += peak_it->log_prob(state, peak_gradient); + + gradient += peak_gradient; + + } + + + if (state.norm() > roi_radius) { + + log_prob -= barrier_rate * MR::Math::pow2((state.norm() - roi_radius)); + gradient -= 2.0 * barrier_rate * state * (state.norm() - roi_radius) / state.norm(); + + } + + return log_prob; + + + } + + + double Landscape::log_prob(const MCMC::State& state, MCMC::State& gradient, MCMC::State::Tensor& hessian) { + + double log_prob = 0.0; + gradient.resize(state.size()); + hessian.resize(state.size(), state.size()); + + gradient.zero(); + hessian.zero(); + + MCMC::State peak_gradient; + MCMC::State::Tensor peak_hessian; + + for (std::vector::iterator peak_it = peaks.begin(); peak_it != peaks.end(); ++peak_it) { + + log_prob += peak_it->log_prob(state, peak_gradient, peak_hessian); + + gradient += peak_gradient; + + hessian += peak_hessian; + + } + + + if (state.norm() > roi_radius) { + + log_prob -= barrier_rate * MR::Math::pow2((state.norm() - roi_radius)); + gradient -= 2.0 * barrier_rate * state * (state.norm() - roi_radius) / state.norm(); + + MR::Math::Matrix hess_part = BTS::Math::outer(state, state); + hess_part *= 2.0 * barrier_rate * (-1.0 * (state.norm() - roi_radius) / MR::Math::pow3(state.norm()) + 1 / state.norm2()); + hessian -= hess_part; + + for (size_t elem_i = 0; elem_i < state.size(); elem_i++) + hessian(elem_i, elem_i) -= 2 * barrier_rate * (state.norm() - roi_radius)/ state.norm(); + + + + } + + return log_prob; + + + } + + + double Landscape::log_prob(const MCMC::State& state, MCMC::State& gradient, MCMC::State::Tensor& hessian, std::vector& rank3_hessian) { + + double log_prob = 0.0; + gradient.resize(state.size()); + hessian.resize(state.size(), state.size()); + + gradient.zero(); + hessian.zero(); + + MCMC::State peak_gradient; + MCMC::State::Tensor peak_hessian; + std::vector peak_rank3_hessian; + + for (size_t dim_i = 0; dim_i < state.size(); dim_i++) + rank3_hessian.push_back(hessian); + + + for (std::vector::iterator peak_it = peaks.begin(); peak_it != peaks.end(); ++peak_it) { + + log_prob += peak_it->log_prob(state, peak_gradient, peak_hessian, peak_rank3_hessian); + + gradient += peak_gradient; + + hessian += peak_hessian; + + for (size_t dim_i = 0; dim_i < state.size(); dim_i++) + rank3_hessian[dim_i] += peak_rank3_hessian[dim_i]; + + } + + if (state.norm() > roi_radius) { + + log_prob -= barrier_rate * MR::Math::pow2((state.norm() - roi_radius)); + gradient -= 2.0 * barrier_rate * state * (state.norm() - roi_radius) / state.norm(); + + MR::Math::Matrix hess_part = BTS::Math::outer(state, state); + hess_part *= -2.0 * barrier_rate * (-1.0 * (state.norm() - roi_radius) / MR::Math::pow3(state.norm()) + 1 / state.norm2()); + hessian += hess_part; + + for (size_t elem_i = 0; elem_i < state.size(); elem_i++) + hessian(elem_i, elem_i) -= 2 * barrier_rate * (state.norm() - roi_radius)/ state.norm(); + + + for (size_t dim_i = 0; dim_i < state.size(); dim_i++) { + + MCMC::State::Tensor& d_hessian = rank3_hessian[dim_i]; + + MR::Math::Matrix d_scalar_hess = Math::outer(state,state); + d_scalar_hess *= -2.0 * barrier_rate * state[dim_i] * (3.0 * (state.norm() - roi_radius) / MR::Math::pow5(state.norm()) - 3.0 / MR::Math::pow4(state.norm())); + + MR::Math::Matrix d_outer_hess (state.size(), state.size()); + d_outer_hess = 0.0; + d_outer_hess.column(dim_i) = state; + d_outer_hess.row(dim_i) += state; + d_outer_hess *= -2.0 * barrier_rate * (-1.0 * (state.norm() - roi_radius) / MR::Math::pow3(state.norm()) + 1 / state.norm2()); + + d_hessian += d_scalar_hess; + d_hessian += d_outer_hess; + + for (size_t dim_i2 = 0; dim_i2 < state.size(); dim_i2++) + d_hessian(dim_i2, dim_i2) -= 2.0 * barrier_rate * state[dim_i] * (1/state.norm2() - (state.norm() - roi_radius)/ MR::Math::pow3(state.norm())); + + } + + } + + return log_prob; + + + } + + + void Landscape::save(const std::string& location) { + + + Peak::Writer writer(location); + + for (std::vector::iterator peak_it = peaks.begin(); peak_it != peaks.end(); ++peak_it) + writer.append(*peak_it); + + } + + + + void Landscape::load(const std::string& location) { + + + this->peaks.clear(); + + Peak::Reader reader(location); + + Peak peak; + + ndims = 0; + + while (reader.next(peak)) { + + if (!ndims) + ndims = peak.num_dims(); + else if (ndims != peak.num_dims()) + throw Exception ("Peak dimension (" + str(peak.num_dims()) + ") does not match overall dimension (" + str(ndims) + ")."); + + this->peaks.push_back(peak); + + } + + if (!ndims) + throw Exception ("Loaded test landscape ('" + location + "') does not have any dimension."); + + + + } + + + + std::ostream& operator<< (std::ostream& stream, const Landscape& test) { + + for (std::vector::const_iterator peak_it = test.peaks.begin(); peak_it != test.peaks.end(); ++peak_it) + stream << *peak_it << std::endl; + + return stream; + + } + + } + + } + +} diff --git a/src/bts/prob/test/landscape.h b/src/bts/prob/test/landscape.h new file mode 100644 index 0000000..133958f --- /dev/null +++ b/src/bts/prob/test/landscape.h @@ -0,0 +1,189 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + +#ifndef __bts_prob_testpeaks__ +#define __bts_prob_testpeaks__ + +#define TEST_LANDSCAPE_PARAMETERS \ +\ + Option ("lnd_location", "") \ + + Argument ("lnd_location", "").type_text (Prob::Test::Landscape::LOCATION_DEFAULT), \ +\ + Option ("lnd_scale", "") \ + + Argument ("lnd_scale", "").type_float (SMALL_FLOAT, LARGE_FLOAT, 1.0), \ +\ + Option ("lnd_roi_radius", "") \ + + Argument ("lnd_roi_radius", "").type_float (SMALL_FLOAT, LARGE_FLOAT,Prob::Test::Landscape::ROI_RADIUS_DEFAULT), \ +\ + Option ("lnd_barrier_rate", "") \ + + Argument ("lnd_barrier_rate", "").type_float (SMALL_FLOAT, LARGE_FLOAT,Prob::Test::Landscape::BARRIER_RATE_DEFAULT) \ + +//Loads the 'prior' parameters into variables +#define SET_TEST_LANDSCAPE_PARAMETERS \ + std::string lnd_location = Prob::Test::Landscape::LOCATION_DEFAULT; \ + double lnd_scale = 1.0; \ + double lnd_roi_radius = Prob::Test::Landscape::ROI_RADIUS_DEFAULT; \ + double lnd_barrier_rate = Prob::Test::Landscape::BARRIER_RATE_DEFAULT; \ +\ + opt = get_options("lnd_location"); \ + if (opt.size()) \ + lnd_location = opt[0][0].c_str(); \ +\ + opt = get_options("lnd_scale"); \ + if (opt.size()) \ + lnd_scale = opt[0][0]; \ +\ + opt = get_options("lnd_roi_radius"); \ + if (opt.size()) \ + lnd_roi_radius = opt[0][0]; \ +\ + opt = get_options("lnd_barrier_rate"); \ + if (opt.size()) \ + lnd_barrier_rate = opt[0][0]; \ + +//Adds the 'prior' parameters to the properties to be saved with the data. +#define ADD_TEST_LANDSCAPE_PROPERTIES(properties) \ + properties["lnd_location"] = lnd_location; \ + properties["lnd_scale"] = str(lnd_scale); \ + properties["lnd_roi_radius"] = str(lnd_roi_radius); \ + properties["lnd_barrier_rate"] = str(lnd_barrier_rate); + +#include "bts/prob/likelihood.h" +#include "bts/prob/prior.h" + +//TODO: remove +#include "bts/image/expected/buffer.h" + +namespace BTS { + + namespace Prob { + + namespace Test { + + class Landscape { + + public: + + class Peak; + + public: + + const static char* LOCATION_DEFAULT; + + const static size_t NUM_DIMS_DEFAULT = 2; + const static size_t NUM_PEAKS_DEFAULT = 40; + const static double WIDTH_MU_DEFAULT; + const static double WIDTH_SIGMA_DEFAULT; + const static double WIDTH_MIN_DEFAULT; + const static double HEIGHT_VAR_DEFAULT; + const static double ROI_RADIUS_DEFAULT; + const static double FRACTION_PYRAMID_DEFAULT; + const static double BARRIER_RATE_DEFAULT; + + //TODO: remove + // BTS::Image::Expected::Buffer* exp_image; + + public: + + static Landscape randomly_generate( size_t num_dims, + size_t num_peaks, + double peak_width_mu, + double peak_width_sigma, + double peak_width_min, + double peak_height_var, + double roi_radius, + double fraction_pyramid, + double barrier_rate = BARRIER_RATE_DEFAULT, + size_t seed = time(NULL)); + + protected: + + size_t ndims; + + double roi_radius; + + double barrier_rate; + + std::vector peaks; + + public: + + Landscape(double roi_radius = ROI_RADIUS_DEFAULT, + double barrier_rate = BARRIER_RATE_DEFAULT); + + Landscape(const std::string& location, double roi_radius = + ROI_RADIUS_DEFAULT, double barrier_rate = BARRIER_RATE_DEFAULT); + + ~Landscape(); + + Landscape(double magnitude, size_t num_points, double spacing, + size_t seed = time(NULL)); + + double log_prob(const MCMC::State& test_state); + + double log_prob(const MCMC::State& test_state, MCMC::State& gradient); + + double log_prob(const MCMC::State& test_state, MCMC::State& gradient, MCMC::State::Tensor& hessian); + + double log_prob(const MCMC::State& test_state, MCMC::State& gradient, MCMC::State::Tensor& hessian, std::vector& rank3_hessian); + + void save(const std::string& location); + + void load(const std::string& location); + + size_t num_dims() const { + return ndims; + } + + Peak& operator[](size_t index) { + return peaks[index]; + } + + const Peak& operator[](size_t index) const { + return peaks[index]; + } + + void set_assumed_snr(double assumed_snr, const std::string& ref_b0, double ref_signal) { + } + + void set_enforce_bounds(bool flag) {} + + std::vector list_components() { return std::vector(); } + + template std::map get_component_values(T& t) { return std::map(); } + + friend std::ostream& operator<<(std::ostream& stream, + const Landscape& test); + + }; + + std::ostream& operator<<(std::ostream& stream, const Landscape& test); + + } + + } + +} + +#include "bts/prob/test/landscape/peak.h" + +#endif diff --git a/src/bts/prob/test/landscape/peak.cpp b/src/bts/prob/test/landscape/peak.cpp new file mode 100644 index 0000000..930b714 --- /dev/null +++ b/src/bts/prob/test/landscape/peak.cpp @@ -0,0 +1,233 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + + + #include "bts/prob/test/landscape/peak.h" + +#include "bts/prob/inline_functions.h" + +#include "bts/math/common.h" +#include "math/matrix.h" +#include "bts/image/buffer.cpp.h" + +namespace BTS { + + namespace Prob { + + namespace Test { + + Landscape::Peak::Peak(size_t ndims, + const MCMC::State& centre, + const MCMC::State::Tensor& widths, + double height, + size_t type) + : type(type), + ndims(ndims), + height(height), + centre(centre), + widths(widths) + + { + + if (ndims!= widths.rows()) + throw Exception ("Size of centre (" + str(ndims) + ") and length of widths (" + str(widths.rows()) + ") do not match."); + + + + } + + + double Landscape::Peak::log_prob(const MCMC::State& point, MCMC::State& gradient) { + + double log_prob; + + if (type == GAUSSIAN) + log_prob = gaussian_log_prob(point, gradient); + else if (type == PYRAMID) + log_prob = pyramid_log_prob(point, gradient); + else + throw Exception ("Unrecognised peak type, " + str(type) + "."); + + return log_prob; + + } + + + double Landscape::Peak::log_prob(const MCMC::State& point, MCMC::State& gradient, MCMC::State::Tensor& hessian) { + + double log_prob; + + if (type == GAUSSIAN) + log_prob = gaussian_log_prob(point, gradient, hessian); + else if (type == PYRAMID) + throw Exception ("Hessian is not useful for pyramid type peaks."); + else + throw Exception ("Unrecognised peak type, " + str(type) + "."); + + return log_prob; + + } + + double Landscape::Peak::log_prob(const MCMC::State& point, MCMC::State& gradient, MCMC::State::Tensor& hessian, std::vector& rank3_hessian) { + + double log_prob; + + if (type == GAUSSIAN) + log_prob = gaussian_log_prob(point, gradient, hessian, rank3_hessian); + else if (type == PYRAMID) + throw Exception ("Hessian or a 3rd order Hessian is not useful for pyramid type peaks."); + else + throw Exception ("Unrecognised peak type, " + str(type) + "."); + + return log_prob; + + } + + + double Landscape::Peak::gaussian_log_prob(const MCMC::State& point, MCMC::State& gradient, MCMC::State::Tensor& hessian) { + + MCMC::State disp = point - this->centre; + + MCMC::State widths_mult_disp(ndims); + + MR::Math::mult(widths_mult_disp, widths, disp); + + double exponent = -MR::Math::dot(disp, widths_mult_disp); + + if (exponent > 0) + throw Exception ("Tensor was not a positive definite matrix."); + + double log_prob = height * exp (exponent); + + gradient = widths_mult_disp; + gradient *= -2.0 * log_prob; + + hessian = Math::outer(widths_mult_disp, widths_mult_disp); + hessian *= 4.0 * log_prob; + + MR::Math::Matrix hess_part = widths; + hess_part *= -2.0 * log_prob; + hessian += hess_part; + + return log_prob; + + } + + + double Landscape::Peak::gaussian_log_prob(const MCMC::State& point, MCMC::State& gradient, MCMC::State::Tensor& hessian, std::vector& rank3_hessian) { + + MCMC::State disp = point - this->centre; + + MCMC::State widths_mult_disp(ndims); + + MR::Math::mult(widths_mult_disp, widths, disp); + + double exponent = -MR::Math::dot(disp, widths_mult_disp); + + if (exponent > 0) + throw Exception ("Tensor was not a positive definite matrix."); + + double log_prob = height * exp (exponent); + + gradient = widths_mult_disp; + gradient *= -2.0 * log_prob; + + MR::Math::Matrix outer_hess_part = Math::outer(widths_mult_disp, widths_mult_disp); + outer_hess_part *= 4.0 * log_prob; + + MR::Math::Matrix width_hess_part = widths; + width_hess_part *= -2.0 * log_prob; + + hessian = outer_hess_part; + hessian += width_hess_part; + + for (size_t dim_i = 0; dim_i < ndims; dim_i++) { + + rank3_hessian.push_back(MCMC::State::Tensor(point.size())); + + MCMC::State::Tensor& d_hessian = rank3_hessian[dim_i]; + + MR::Math::Matrix outer_hess_part1 = outer_hess_part; + outer_hess_part1 *= -2.0 * widths_mult_disp[dim_i]; + + MR::Math::Matrix outer_hess_part2 = Math::outer(widths.column(dim_i), widths_mult_disp); + outer_hess_part2 += Math::outer(widths_mult_disp, widths.column(dim_i)); + outer_hess_part2 *= 4.0 * log_prob; + + MR::Math::Matrix width_hess_part1 = width_hess_part; + width_hess_part1 *= -2.0 * widths_mult_disp[dim_i]; + + + d_hessian = outer_hess_part1; + d_hessian += outer_hess_part2; + d_hessian += width_hess_part1; + + + } + + return log_prob; + + } + + double Landscape::Peak::pyramid_log_prob(const MCMC::State& point, MCMC::State& gradient) { + + + MCMC::State disp = point - this->centre; + + gradient.resize(ndims); + + double log_prob = MR::Math::abs(height); + + for (size_t dim_i = 0; dim_i < ndims; dim_i++) + log_prob -= MR::Math::abs(disp[dim_i]) * widths(dim_i, dim_i); + + if (log_prob > 0) { + + for (size_t dim_i = 0; dim_i < disp.size(); dim_i++) + gradient[dim_i] = - widths(dim_i, dim_i) * Math::sign(disp[dim_i]); + + gradient *= Math::sign(height); + log_prob *= Math::sign(height); + + } else { + log_prob = 0.0; + gradient.zero(); + } + + return log_prob; + } + + + + std::ostream& operator<< (std::ostream& stream, const Landscape::Peak& peak) { + + stream << "centre: " << peak.centre << ", height: " << peak.height << " type: " << peak.type << ", widths: " << peak.widths << std::endl; + + return stream; + + } + + } + + } + +} diff --git a/src/bts/prob/test/landscape/peak.h b/src/bts/prob/test/landscape/peak.h new file mode 100644 index 0000000..45d7683 --- /dev/null +++ b/src/bts/prob/test/landscape/peak.h @@ -0,0 +1,102 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + + +#ifndef __bts_prob_testpeaks_peak__ +#define __bts_prob_testpeaks_peak__ + +#include "bts/prob/test/landscape.h" +#include "bts/mcmc/state/tensor.h" + +namespace BTS { + + namespace Prob { + + namespace Test { + + class Landscape::Peak { + + public: + + class Gaussian; + class Pyramid; + class Quartic; + + public: + + const static size_t GAUSSIAN = 0; + const static size_t PYRAMID = 1; + + public: + + class Reader; + class Writer; + + friend class Reader; + friend class Writer; + + protected: + + + size_t type; + size_t ndims; + double height; + MCMC::State centre; + MCMC::State::Tensor widths; + + public: + + Peak() {} + + Peak(size_t ndims, const MCMC::State& centre, const MCMC::State::Tensor& widths, double height, size_t type = GAUSSIAN); + + double log_prob(const MCMC::State& point, MCMC::State& gradient); + + double log_prob(const MCMC::State& point, MCMC::State& gradient, MCMC::State::Tensor& hessian); + + double log_prob(const MCMC::State& point, MCMC::State& gradient, MCMC::State::Tensor& hessian, std::vector& rank3_hessian); + + double gaussian_log_prob(const MCMC::State& point, MCMC::State& gradient) + { MCMC::State::Tensor dummy; return log_prob(point, gradient, dummy); } + + double gaussian_log_prob(const MCMC::State& point, MCMC::State& gradient, MCMC::State::Tensor& hessian); + + double gaussian_log_prob(const MCMC::State& point, MCMC::State& gradient, MCMC::State::Tensor& hessian, std::vector& rank3_hessian); + + double pyramid_log_prob(const MCMC::State& point, MCMC::State& gradient); + + size_t num_dims() const + { return ndims; } + + + friend std::ostream& operator<< (std::ostream& stream, const Peak& peak); + + }; + + } + + } + +} + + +#endif diff --git a/src/bts/prob/test/landscape/peak/reader.h b/src/bts/prob/test/landscape/peak/reader.h new file mode 100644 index 0000000..d6c66fe --- /dev/null +++ b/src/bts/prob/test/landscape/peak/reader.h @@ -0,0 +1,91 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + + +#ifndef __bts_prob_testpeaks_peak_reader__ +#define __bts_prob_testpeaks_peak_reader__ + +namespace BTS { + + namespace Prob { + + class Test::Landscape::Peak::Reader { + + protected: + + std::ifstream fin; + + public: + + Reader() {} + + Reader(const std::string& location) + { this->open(location); } + + ~Reader() { if (fin.is_open()) this->close(); } + + void open(const std::string& location) + { fin.open(location.c_str()); } + + void close() + { fin.close(); } + + bool next(Peak& peak) { + + std::string line; + bool is_next; + + if (std::getline(fin, line)) { + + std::istringstream line_stream(line); + + line_stream >> peak.type >> peak.ndims >> peak.height; + + peak.centre.resize(peak.ndims); + peak.widths.resize(peak.ndims, peak.ndims); + + for (size_t dim_i = 0; dim_i < peak.ndims; ++dim_i) + line_stream >> peak.centre[dim_i]; + + for (size_t dim_i1 = 0; dim_i1 < peak.ndims; ++dim_i1) + for (size_t dim_i2 = 0; dim_i2 < peak.ndims; ++dim_i2) + line_stream >> peak.widths(dim_i1, dim_i2); + +// line_stream >> peak.centre[X] >> peak.centre[Y] >> peak.width[X] >> peak.width[Y] >> peak.height >> peak.type; + + is_next = true; + + } else + is_next = false; + + + return is_next; + } + + + }; + + } + +} + +#endif diff --git a/src/bts/prob/test/landscape/peak/writer.h b/src/bts/prob/test/landscape/peak/writer.h new file mode 100644 index 0000000..3f7b55d --- /dev/null +++ b/src/bts/prob/test/landscape/peak/writer.h @@ -0,0 +1,76 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + + +#ifndef __bts_prob_testpeaks_peak_writer__ +#define __bts_prob_testpeaks_peak_writer__ + +namespace BTS { + + namespace Prob { + + + class Test::Landscape::Peak::Writer { + + + protected: + + std::ofstream fout; + + public: + + Writer() {} + + Writer(const std::string& location) + { this->create(location); } + + ~Writer() { if (fout.is_open()) this->close(); } + + void create(const std::string& location) + { fout.open(location.c_str()); } + + void close() + { fout.close(); } + + void append(const Peak& peak) { + + fout << peak.type << " " << peak.ndims << " " << peak.height; + + for (size_t dim_i = 0; dim_i < peak.ndims; ++dim_i) + fout << " " << peak.centre[dim_i]; + + for (size_t dim_i1 = 0; dim_i1 < peak.ndims; ++dim_i1) + for (size_t dim_i2 = 0; dim_i2 < peak.ndims; ++dim_i2) + fout << " " << peak.widths(dim_i1,dim_i2); + + fout << std::endl; + + } + + + }; + + } + +} + +#endif diff --git a/src/bts/prob/uniform.cpp b/src/bts/prob/uniform.cpp new file mode 100644 index 0000000..524c0b0 --- /dev/null +++ b/src/bts/prob/uniform.cpp @@ -0,0 +1,40 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + +#include +#include "image/header.h" +#include "bts/common.h" + +#include "bts/prob/uniform.h" + +#include "bts/prob/inline_functions.h" + +#include "bts/image/buffer.cpp.h" + +namespace BTS { + + namespace Prob { + + const std::string Uniform::NAME = "uniform"; + + } +} diff --git a/src/bts/prob/uniform.h b/src/bts/prob/uniform.h new file mode 100644 index 0000000..459b3e1 --- /dev/null +++ b/src/bts/prob/uniform.h @@ -0,0 +1,133 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + + +#ifndef __bts_prob_uniform__ +#define __bts_prob_uniform__ + +#include "bts/prob/likelihood.h" +#include "bts/prob/prior.h" +#include "bts/prob/uniform.h" + +#include "bts/mcmc/state.h" +#include "bts/mcmc/state/tensor.h" + + +namespace BTS { + + namespace Prob { + + //Used as a filler instead of adding any particular prior. + class Uniform { + + public: + + const static std::string NAME; + + public: + + + double get_scalar() + { return 1.0; } + + Uniform* clone() const + { return new Uniform(*this); } + + double log_prob(const Fibre::Strand& strand) + { return 0.0; } + + double log_prob(const Fibre::Tractlet& tractlet) + { return 0.0; } + + double log_prob(const Fibre::Strand::Set& strand) + { return 0.0; } + + double log_prob(const Fibre::Tractlet::Set& tractlet) + { return 0.0; } + + double log_prob(const Fibre::Strand& strand, Fibre::Strand& gradient) + { gradient.zero(); return 0.0; } + + double log_prob(const Fibre::Tractlet& tractlet, Fibre::Tractlet& gradient) + { gradient.zero(); return 0.0; } + + double log_prob(const Fibre::Strand::Set& strand, Fibre::Strand::Set& gradient) + { gradient.zero(); return 0.0; } + + double log_prob(const Fibre::Tractlet::Set& strand, Fibre::Tractlet::Set& gradient) + { gradient.zero(); return 0.0; } + + double log_prob(const MCMC::State& state, MCMC::State& gradient) + { gradient.zero(); return 0.0; } + + double log_prob(const double& f, double& gradient) + { gradient = 0.0; return 0.0; } + + double log_prob_and_fisher(const MCMC::State& state, MCMC::State& gradient, MCMC::State::Tensor& fisher) + { gradient.zero(); fisher.zero(); return 0.0; } + + double log_prob_and_fisher(const MCMC::State& state, MCMC::State& gradient, MCMC::State::Tensor& fisher, std::vector& fisher_gradient) + { gradient.zero(); fisher.zero(); for (size_t i =0; i < fisher_gradient.size(); ++i) fisher_gradient[i] = 0.0; return 0.0; } + + double component_log_prob(const std::string&, const BTS::Fibre::Strand& strand, BTS::Fibre::Strand& gradient) + { gradient.zero(); return 0.0; } + + double component_log_prob(const std::string&, const BTS::Fibre::Strand::Set& strands, BTS::Fibre::Strand::Set& gradient) + { gradient.zero(); return 0.0; } + + double component_log_prob(const std::string&, const BTS::Fibre::Tractlet& tractlet, BTS::Fibre::Tractlet& gradient) + { gradient.zero(); return 0.0; } + + double component_log_prob(const std::string&, const BTS::Fibre::Tractlet::Set& tractlets, BTS::Fibre::Tractlet::Set& gradient) + { gradient.zero(); return 0.0; } + + double log_prob(double expected, double observed) { return 0; } + + + double b0_log_prob(double expected, double observed) { return 0; } + + + double log_prob(double expected, double observed, double& d_lprob) { return 0; } + + + double log_prob(double expected, double observed, double& d_lprob, double& d2_lprob2) { return 0; } + + + + void set_enforce_bounds(bool flag) {} + + std::vector list_components() { return std::vector(); } + + template std::map get_component_values(T& t) { return std::map(); } + + const std::string& get_name() + { return NAME; } + + void set_assumed_snr(double assumed_snr, const std::string& ref_b0, double ref_signal) {} + + }; + + } + +} + +#endif diff --git a/src/bts/triple.cpp b/src/bts/triple.cpp new file mode 100644 index 0000000..07faa4f --- /dev/null +++ b/src/bts/triple.cpp @@ -0,0 +1,50 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, 07/08/2010. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + +#include "bts/triple.h" +#include "bts/coord.h" + +namespace BTS { + + template<> const Triple Triple::Invalid (NAN, NAN, NAN); + template<> const Triple Triple::Zeros (0.0, 0.0, 0.0); + template<> const Triple Triple::Ones(1.0,1.0,1.0); + template<> const Triple Triple::Halves(0.5,0.5,0.5); + + template<> const Triple Triple::Invalid (-999999999, -999999999,-999999999); + template<> const Triple Triple::Zeros (0, 0, 0); + template<> const Triple Triple::Ones(1,1,1); + + template<> const Triple Triple::Invalid (999999999, 999999999, 999999999); + template<> const Triple Triple::Zeros (0, 0, 0); + template<> const Triple Triple::Ones(1,1,1); + + template <> Triple::Triple (const Coord& coord) { + set (coord[0], coord[1], coord[2]); + } + + template <> Triple::Triple (const Coord& coord) { + set (coord[0], coord[1], coord[2]); + } + + +} diff --git a/src/bts/triple.h b/src/bts/triple.h new file mode 100644 index 0000000..b32abf9 --- /dev/null +++ b/src/bts/triple.h @@ -0,0 +1,461 @@ +/* + Copyright 2010 Brain Research Institute/National ICT Australia (NICTA), Melbourne, Australia + + Written by J-Donald Tournier, 27/06/08. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + +*/ + + +#include + +#include "bts/common.h" +#include "bts/coord.h" + +#ifndef __bts_triple_h__ +#define __bts_triple_h__ + +#include + +#include "mrtrix.h" +#include "math/math.h" +#include "math/vector.h" +#include "bts/utilities/reader.h" +#include "bts/utilities/writer.h" + + +namespace BTS { + + + template class Triple { + + public: + + typedef Utilities::Reader > Reader; + typedef Utilities::Writer > Writer; + + template class Tensor_tpl; //Dummy class used to get template functions in Hessian Tester to work; + typedef T Element; + + const static Triple Invalid; + const static Triple Zeros; + const static Triple Halves; + const static Triple Ones; + + const static std::string FILE_EXTENSION; + + + protected: + T p[3]; + + public: + + Triple () + { invalidate(); } + + Triple (T value) + { set(value); } + + Triple (T x_value, T y_value, T z_value) + { set (x_value, y_value, z_value); } + + Triple (const Coord& coord); + + bool operator! () const { return (isnan(p[X]) || isnan(p[Y]) || isnan(p[Z])); } + bool valid () const { return (!(isnan(p[X]) || isnan(p[Y]) || isnan(p[Z]))); } + + T* get () { return (p); } + const T* get () const { return (p); } + void copy_to(double* array) { array[X] = (double)p[X]; array[Y] = (double)p[Y]; array[Z] = (double)p[Z]; } + + Triple& set (T x_value, T y_value, T z_value) { p[X] = x_value; p[Y] = y_value; p[Z] = z_value; return *this; } + Triple& set (const T point[3]) { set(point[X], point[Y], point[Z]); return *this; } + Triple& set (T value) { set(value,value,value); return *this; } + + Triple& zero (); + Triple& invalidate (); + + Triple abs() const { return Triple(fabs(p[X]), fabs(p[Y]), fabs(p[Z]));} + + Triple invert() const { return Triple (1/p[X], 1/p[Y], 1/p[Z]); } + + T& operator[] (int idx) { return (p[idx]); } + const T& operator[] (int idx) const { return (p[idx]); } + + bool operator== (const Triple& A) const; + bool operator!= (const Triple& A) const; + + Triple operator- () const { return (Triple (-p[X], -p[Y], -p[Z])); } + + Triple& operator= (const Triple& A) { p[X] = A[X]; p[Y] = A[Y]; p[Z] = A[Z]; return (*this); } + + + MR::Math::Vector vector() const + { MR::Math::Vector vec(3); vec[X] = p[X]; vec[Y] = p[Y]; vec[Z] = p[Z]; return vec; } + + + void from_vector(const MR::Math::Vector& vec) + { assert(vec.size() == 3); p[X] = vec[X]; p[Y] = vec[Y]; p[Z] = vec[Z]; } + + //Scalar addition, subtraction, multiplication and division. + Triple& operator+= (T inc) { p[X] += inc; p[Y] += inc; p[Z] += inc; return *this; } + Triple& operator-= (T inc) { p[X] -= inc; p[Y] -= inc; p[Z] -= inc; return *this; } + Triple& operator*= (T M) { p[X]*=M; p[Y]*=M; p[Z]*=M; return *this; } + Triple& operator/= (T M) { p[X]/=M; p[Y]/=M; p[Z]/=M; return *this; } + + + Triple operator+ (T M) const { return (Triple (p[X]+M, p[Y]+M, p[Z]+M)); } + Triple operator- (T M) const { return (Triple (p[X]-M, p[Y]-M, p[Z]-M)); } + Triple operator* (T M) const { return (Triple (p[X]*M, p[Y]*M, p[Z]*M)); } + Triple operator/ (T M) const { return (Triple (p[X]/M, p[Y]/M, p[Z]/M)); } + + //Pairwise addition, subtraction, multiplication and division. + Triple operator+ (const Triple& A) const { return Triple (p[X]+A[X], p[Y]+A[Y], p[Z]+A[Z]); } + Triple operator- (const Triple& A) const { return Triple (p[X]-A[X], p[Y]-A[Y], p[Z]-A[Z]); } + Triple operator* (const Triple& A) const { return Triple (p[X]*A[X], p[Y]*A[Y], p[Z]*A[Z]); } + Triple operator/ (const Triple& A) const { return Triple (p[X]/A[X], p[Y]/A[Y], p[Z]/A[Z]); } + + Triple& operator+= (const Triple& A) { p[X] += A[X]; p[Y] += A[Y]; p[Z] += A[Z]; return *this; } + Triple& operator-= (const Triple& A) { p[X] -= A[X]; p[Y] -= A[Y]; p[Z] -= A[Z]; return *this; } + Triple& operator*= (const Triple& A) { p[X] *= A[X]; p[Y] *= A[Y]; p[Z] *= A[Z]; return *this; } + Triple& operator/= (const Triple& A) { p[X] /= A[X]; p[Y] /= A[Y]; p[Z] /= A[Z]; return *this; } + + +// //Scalar addition, subtraction, multiplication and division by doubles. +// template Triple& operator+= (U inc); +// template Triple& operator-= (U inc); +// template Triple& operator*= (U M); +// template Triple& operator/= (U M); +// +// +// template Triple operator+ (U M) const; +// template Triple operator- (U M) const; +// template Triple operator* (U M) const; +// template Triple operator/ (U M) const; + + + bool positive() const { return (p[X] > 0.0) && (p[Y] > 0.0) && (p[Z] > 0.0); } + bool non_negative() const { return (p[X] >= 0.0) && (p[Y] >= 0.0) && (p[Z] >= 0.0); } + bool non_zero() const { return p[X] || p[Y] || p[Z]; } + + template bool upper_bounded(U bound) const { return (p[X] <= (T)bound) && (p[Y] <= (T)bound) && (p[Z] <= (T)bound); } + template bool lower_bounded(U bound) const { return (p[X] >= (T)bound) && (p[Y] >= (T)bound) && (p[Z] >= (T)bound); } + + template bool upper_bounded(const Triple& bound) const { return (p[X] <= (T)bound[X]) && (p[Y] <= (T)bound[Y]) && (p[Z] <= (T)bound[Z]); } + template bool lower_bounded(const Triple& bound) const { return (p[X] >= (T)bound[X]) && (p[Y] >= (T)bound[Y]) && (p[Z] >= (T)bound[Z]); } + + T dot (const Triple& A) const { return (p[X]*A[X] + p[Y]*A[Y] + p[Z]*A[Z]); } + T dot (const Triple& t, Triple& gradient) const; + + T angle(const Triple& t) const; + + T norm2 () const { return (p[X]*p[X] + p[Y]*p[Y] + p[Z]*p[Z]); } + T norm () const { return (sqrt (norm2())); } + + + const Triple& normalise () { MR::Math::normalise (p); return (*this); } + + + Triple cross (const Triple& A) const { return (Triple (p[Y]*A[Z]-p[Z]*A[Y], p[Z]*A[X]-p[X]*A[Z], p[X]*A[Y]-p[Y]*A[X])); } + + Triple min_axis() const { Triple axis(0.0,0.0,0.0); if (fabs(p[X]) < fabs(p[Y])) { if (fabs(p[X]) < fabs(p[Z])) axis[X] = 1.0; else axis[Z] = 1.0; } else if (fabs(p[Y]) < fabs(p[Z])) axis[Y] = 1.0; else axis[Z] = 1.0; return axis; } + + + Triple sign() const { Triple s; for (size_t i = 0; i < 3; ++i) s[i] = p[i] > 0 ? 1 : (p[i] < 0 ? -1 : 0); return s; } + + + //These functions and static members are only required for Fibre::Base::Reader/Writer< Triple > functions. + void clear() {} + + size_t size() const { return 3; } + + void resize(size_t dummy) { assert(dummy == 3); } + + protected: + + explicit Triple (const T point[3]) { set (point); } + + }; + +#include "bts/coord.h" +#include "bts/common.h" + + + template <> inline Triple& Triple::zero() { + memset (p, 0, sizeof(p)); return *this; + } + + template <> inline Triple& Triple::zero() { + memset (p, 0, sizeof(p)); return *this; + } + + template <> inline Triple& Triple::zero() { + memset (p, 0, sizeof(p)); return *this; + } + + template <> inline Triple& Triple::zero() { + memset (p, 0, sizeof(p)); return *this; + } + + + template <> inline Triple& Triple::invalidate() { + p[X] = p[Y] = p[Z] = std::numeric_limits::min(); return *this; + } + + + template <> inline Triple& Triple::invalidate() { + p[X] = p[Y] = p[Z] = std::numeric_limits::max(); return *this; + } + + + template <> inline Triple& Triple::invalidate() { + p[X] = p[Y] = p[Z] = NAN; return *this; + } + + template <> inline Triple& Triple::invalidate() { + p[X] = p[Y] = p[Z] = NAN; return *this; + } + + template std::ostream& operator<< (std::ostream& stream , const Triple& pt) + { + stream << "[ " << pt[X] << ", " << pt[Y] << ", " << pt[Z] << " ]"; + return (stream); + } + + template Triple& Triple::zero() { + + p[X].zero(); + p[Y].zero(); + p[Z].zero(); + + return *this; + } + + template Triple& Triple::invalidate() { + + p[X].invalidate(); + p[Y].invalidate(); + p[Z].invalidate(); + + return *this; + } + + template bool Triple::operator== (const Triple& A) const + { return (p[X] == A[X]) && (p[Y] == A[Y]) && (p[Z] == A[Z]); }; + + template bool Triple::operator!= (const Triple& A) const + { return (p[X] != A[X]) || (p[Y] != A[Y]) || (p[Z] != A[Z]); }; + + + template<> inline bool Triple::operator== (const Triple& A) const + { return (memcmp (p, A.p, sizeof(p)) == 0); }; + + template<> inline bool Triple::operator!= (const Triple& A) const + { return (memcmp (p, A.p, sizeof(p))); }; + + template<> inline bool Triple::operator== (const Triple& A) const + { return (memcmp (p, A.p, sizeof(p)) == 0); }; + + template<> inline bool Triple::operator!= (const Triple& A) const + { return (memcmp (p, A.p, sizeof(p))); }; + + template<> inline bool Triple::operator== (const Triple& A) const + { return (memcmp (p, A.p, sizeof(p)) == 0); }; + + template<> inline bool Triple::operator!= (const Triple& A) const + { return (memcmp (p, A.p, sizeof(p))); }; + + template<> inline bool Triple::operator== (const Triple& A) const + { return (memcmp (p, A.p, sizeof(p)) == 0); }; + + template<> inline bool Triple::operator!= (const Triple& A) const + { return (memcmp (p, A.p, sizeof(p))); }; + + + + template const std::string Triple::FILE_EXTENSION = "trp"; + + template inline Triple operator* (T M, const Triple& P) + { return Triple (P[X]*M, P[Y]*(T)M, P[Z]*(T)M); } + + template inline Triple< Triple > operator* (T M, const Triple< Triple >& t) + { return Triple< Triple > (t[X] * M, t[Y] * M, t[Z] * M); } + + + inline Triple operator+ (const Triple& P, double M) { return Triple (((double)P[X])+M, ((double)P[Y])+M, ((double)P[Z])+M); } + inline Triple operator+ (const Triple& P, double M) { return Triple (((double)P[X])+M, ((double)P[Y])+M, ((double)P[Z])+M); } + inline Triple operator+ (const Triple& P, int M) { return Triple (((int)P[X])+M, ((int)P[Y])+M, ((int)P[Z])+M); } + inline Triple operator+ (int M, const Triple& P) { return Triple (((int)P[X])+M, ((int)P[Y])+M, ((int)P[Z])+M); } + + + inline Triple operator+ (double M, const Triple& P) { return Triple (((double)P[X])+M, ((double)P[Y])+M, ((double)P[Z])+M); } + inline Triple operator+ (double M, const Triple& P) { return Triple (((double)P[X])+M, ((double)P[Y])+M, ((double)P[Z])+M); } + + inline Triple operator+ (int M, const Triple& P) { return Triple (P[X]+(double)M, P[Y]+(double)M, P[Z]+(double)M); } + + inline Triple operator+ (const Triple& f, const Triple& i) { return Triple(f[X] + (double)i[X], f[Y] + (double)i[Y], f[Z] + (double)i[Z] ); } + inline Triple operator+ (const Triple& f, const Triple& ui) { return Triple(f[X] + (double)ui[X], f[Y] + (double)ui[Y], f[Z] + (double)ui[Z] ); } + + inline Triple operator+ (const Triple& i, const Triple& f) { return Triple(f[X] + (double)i[X], f[Y] + (double)i[Y], f[Z] + (double)i[Z] ); } + inline Triple operator+ (const Triple& ui, const Triple& f) { return Triple(f[X] + (double)ui[X], f[Y] + (double)ui[Y], f[Z] + (double)ui[Z] ); } + + inline Triple operator- (const Triple& P, double M) { return Triple (((double)P[X])-M, ((double)P[Y])-M, ((double)P[Z])-M); } + inline Triple operator- (const Triple& P, double M) { return Triple (((double)P[X])-M, ((double)P[Y])-M, ((double)P[Z])-M); } + + + inline Triple operator- (const Triple& f, const Triple& i) { return Triple(f[X] - (double)i[X], f[Y] - (double)i[Y], f[Z] - (double)i[Z] ); } + inline Triple operator- (const Triple& f, const Triple& ui) { return Triple(f[X] - (double)ui[X], f[Y] - (double)ui[Y], f[Z] - (double)ui[Z] ); } + + inline Triple operator- (const Triple& i, const Triple& f) { return Triple(f[X] - (double)i[X], f[Y] - (double)i[Y], f[Z] - (double)i[Z] ); } + inline Triple operator- (const Triple& ui, const Triple& f) { return Triple(f[X] - (double)ui[X], f[Y] - (double)ui[Y], f[Z] - (double)ui[Z] ); } + + + inline Triple operator* (const Triple& P, double M) { return Triple (((double)P[X])*M, ((double)P[Y])*M, ((double)P[Z])*M); } + inline Triple operator* (const Triple& P, double M) { return Triple (((double)P[X])*M, ((double)P[Y])*M, ((double)P[Z])*M); } + + inline Triple operator* (double M, const Triple& P) { return Triple (((double)P[X])*M, ((double)P[Y])*M, ((double)P[Z])*M); } + inline Triple operator* (double M, const Triple& P) { return Triple (((double)P[X])*M, ((double)P[Y])*M, ((double)P[Z])*M); } + + inline Triple operator* (int M, const Triple& P) { return Triple (P[X]*(double)M, P[Y]*(double)M, P[Z]*(double)M); } + + inline Triple operator* (const Triple& f, const Triple& i) { return Triple(f[X] * (double)i[X], f[Y] * (double)i[Y], f[Z] * (double)i[Z] ); } + inline Triple operator* (const Triple& f, const Triple& ui) { return Triple(f[X] * (double)ui[X], f[Y] * (double)ui[Y], f[Z] * (double)ui[Z] ); } + + inline Triple operator* (const Triple& i, const Triple& f) { return Triple(f[X] * (double)i[X], f[Y] * (double)i[Y], f[Z] * (double)i[Z] ); } + inline Triple operator* (const Triple& ui, const Triple& f) { return Triple(f[X] * (double)ui[X], f[Y] * (double)ui[Y], f[Z] * (double)ui[Z] ); } + + + inline Triple operator/ (const Triple& f, const Triple& i) { return Triple(f[X] / (double)i[X], f[Y] / (double)i[Y], f[Z] / (double)i[Z] ); } + inline Triple operator/ (const Triple& f, const Triple& ui) { return Triple(f[X] / (double)ui[X], f[Y] / (double)ui[Y], f[Z] / (double)ui[Z] ); } + + inline Triple operator/ (const Triple& i, const Triple& f) { return Triple(f[X] / (double)i[X], f[Y] / (double)i[Y], f[Z] / (double)i[Z] ); } + inline Triple operator/ (const Triple& ui, const Triple& f) { return Triple(f[X] / (double)ui[X], f[Y] / (double)ui[Y], f[Z] / (double)ui[Z] ); } + +// template Triple operator*(double M, const Triple& t) { return t * M; } + + + //Scalar addition, subtraction, multiplication and division by doubles. + +// +// template <> template <> inline Triple& Triple::operator+= (double inc) { throw Exception("Triple is forbidden from scalar addition with double to avoid accidental use."); } +// template <> template <> inline Triple& Triple::operator-= (double inc) { throw Exception("Triple is forbidden from scalar subtraction with double to avoid accidental use."); } +// template <> template <> inline Triple& Triple::operator*= (double M) { throw Exception("Triple is forbidden from scalar multiplication with double to avoid accidental use."); } +// template <> template <> inline Triple& Triple::operator/= (double M) { throw Exception("Triple is forbidden from scalar division with scalar double to avoid accidental use."); } +// +// template <> template <> inline Triple Triple::operator+ (double M) const { throw Exception("Triple is forbidden from scalar addition with double to avoid accidental use."); } +// template <> template <> inline Triple Triple::operator- (double M) const { throw Exception("Triple is forbidden from scalar subtraction with double to avoid accidental use."); } +// template <> template <> inline Triple Triple::operator* (double M) const { throw Exception("Triple is forbidden from scalar multiplication with double to avoid accidental use."); } +// template <> template <> inline Triple Triple::operator/ (double M) const { throw Exception("Triple is forbidden from scalar division with scalar double to avoid accidental use."); } +// +// template <> template <> inline Triple& Triple::operator+= (double inc) { throw Exception("Triple is forbidden from scalar addition with double to avoid accidental use."); } +// template <> template <> inline Triple& Triple::operator-= (double inc) { throw Exception("Triple is forbidden from scalar subtraction with double to avoid accidental use."); } +// template <> template <> inline Triple& Triple::operator*= (double M) { throw Exception("Triple is forbidden from scalar multiplication with double to avoid accidental use."); } +// template <> template <> inline Triple& Triple::operator/= (double M) { throw Exception("Triple is forbidden from scalar division with scalar double to avoid accidental use."); } +// +// template <> template <> inline Triple Triple::operator+ (double M) const { throw Exception("Triple is forbidden from scalar addition with double to avoid accidental use."); } +// template <> template <> inline Triple Triple::operator- (double M) const { throw Exception("Triple is forbidden from scalar subtraction with double to avoid accidental use."); } +// template <> template <> inline Triple Triple::operator* (double M) const { throw Exception("Triple is forbidden from scalar multiplication with double to avoid accidental use."); } +// template <> template <> inline Triple Triple::operator/ (double M) const { throw Exception("Triple is forbidden from scalar division with scalar double to avoid accidental use."); } +// +// +// template template Triple& Triple::operator+= (U inc) { p[X] += inc; p[Y] += inc; p[Z] += inc; return *this; } +// template template Triple& Triple::operator-= (U inc) { p[X] -= inc; p[Y] -= inc; p[Z] -= inc; return *this; } +// template template Triple& Triple::operator*= (U M) { p[X]*=M; p[Y]*=M; p[Z]*=M; return *this; } +// template template Triple& Triple::operator/= (U M) { p[X]/=M; p[Y]/=M; p[Z]/=M; return *this; } +// +// template template Triple Triple::operator+ (U M) const { return (Triple (p[X]+M, p[Y]+M, p[Z]+M)); } +// template template Triple Triple::operator- (U M) const { return (Triple (p[X]-M, p[Y]-M, p[Z]-M)); } +// template template Triple Triple::operator* (U M) const { return (Triple (p[X]*M, p[Y]*M, p[Z]*M)); } +// template template Triple Triple::operator/ (U M) const { return (Triple (p[X]/M, p[Y]/M, p[Z]/M)); } + + + template inline T dist2 (const Triple& a, const Triple& b) { return ((a-b).norm2()); } + template inline T dist (const Triple& a, const Triple& b) { return ((a-b).norm()); } + + + + + template T Triple::dot (const Triple& t, Triple& gradient) const { + +#ifndef GRADIENT_NOT_REQUIRED + gradient = *this; +#endif + + return dot(t); + + } + + + template T Triple::angle(const Triple& t) const { + + return MR::Math::acos(dot(t)/(norm() * t.norm())); + + } + + + + inline Triple rand_triple(double scale, gsl_rng *rand_gen) { + + Triple triple(0.0,0.0,0.0); + + for (size_t dim_i = 0; dim_i < 3; dim_i++) + triple[dim_i] = (double)gsl_ran_gaussian(rand_gen, scale); + + return triple; + + } + + + template Triple parse_triple(const std::string& s) { + + Triple triple; + + size_t start_number = 0; + size_t end_number; + + size_t dim_i = 0; + + start_number = s.find_first_of("0123456789.-"); + + while (start_number != std::string::npos && (dim_i < 3) ) { + + end_number = s.find_first_not_of("0123456789.-", start_number); + + std::string num_string = s.substr(start_number, end_number-start_number); + + + if (num_string.find_first_of('-', 1) != std::string::npos || num_string.find('.', num_string.find('.')+1) != std::string::npos) // If there is a '-' character anywhere other than the first character, or if there is more than one decimal triple then throw an error. + throw Exception("Coordinate, " + num_string + " at dim: " + str(dim_i+1) + ", is invalid");// + + triple[dim_i] = to(num_string); + + start_number = s.find_first_of("0123456789.-", end_number); + dim_i++; + + } + + if (dim_i != 3) + throw Exception("Incorrect number of values in sequence '" + s +"' for conversion to triple."); + + return triple; + + } + +} + + +#endif diff --git a/src/bts/utilities/common.h b/src/bts/utilities/common.h new file mode 100644 index 0000000..5825d7b --- /dev/null +++ b/src/bts/utilities/common.h @@ -0,0 +1,43 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, Aug 12, 2010. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + +#ifndef bts_utilities_common_h__ +#define bts_utilities_common_h__ + +#include +#include +#include + +namespace BTS { + + namespace Utilities { + + + typedef std::map Properties; + + typedef std::vector Header; + + } + +} + +#endif /* bts_utilities_common_h__ */ diff --git a/src/bts/utilities/inline_functions.h b/src/bts/utilities/inline_functions.h new file mode 100644 index 0000000..1124f9d --- /dev/null +++ b/src/bts/utilities/inline_functions.h @@ -0,0 +1,40 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, Aug 12, 2010. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + +#ifndef __bts_utilities_inlinefunctions_h__ +#define __bts_utilities_inlinefunctions_h__ + +#ifdef __bts_utilities_reader_h__ + +#include "bts/utilities/reader.cpp.h" + +#endif + + +#ifdef __bts_utilities_writer_h__ + +#include "bts/utilities/writer.cpp.h" + +#endif + + +#endif /* __bts_utilities_inlinefunctions_h__ */ diff --git a/src/bts/utilities/reader.cpp.h b/src/bts/utilities/reader.cpp.h new file mode 100644 index 0000000..ee4dbae --- /dev/null +++ b/src/bts/utilities/reader.cpp.h @@ -0,0 +1,81 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, 12/08/2010. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + +#include "bts/utilities/reader.h" +#include "bts/file.h" + +namespace BTS { + + namespace Utilities { + + template void Reader::open(const std::string& location) { + + if (File::is_file(location)) { + + fin.open((location).c_str()); + + if (!fin.good()) + throw Exception("Error opening file '" + location + "'."); + + } else + throw Exception ("No file at location '" + location + "'"); + + } + + + template bool Reader::next(T& state, Properties& properties_row) { + + if (!fin.good()) + throw Exception ("Corrupted utilities file."); + + std::string line; + std::getline(fin, line); + + if (line == "%END") + return false; + + size_t count = 0; + size_t pos = 0; + + while (pos != std::string::npos) { + pos = line.find(' ', pos+1); + count++; + } + + state.resize(count); + + std::istringstream line_stream(line); + + std::string value; + + for (size_t elem_i = 0; elem_i < state.size(); elem_i++) { + std::getline(line_stream, value, ' '); + state[elem_i] = to(value); + } + + return true; + + } + + } + +} diff --git a/src/bts/utilities/reader.h b/src/bts/utilities/reader.h new file mode 100644 index 0000000..52fad4c --- /dev/null +++ b/src/bts/utilities/reader.h @@ -0,0 +1,74 @@ +/* + Copyright 2010 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close on 16/06/2010. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + +#ifndef __bts_utilities_reader_h__ +#define __bts_utilities_reader_h__ + +#include "bts/utilities/common.h" + +namespace BTS { + + namespace Utilities { + + template class Reader { + + public: + + std::ifstream fin; + + Reader() {}; + + Reader(const std::string& location, Properties& properties, Header& key_list) + { open(location); } + + Reader(const std::string& location) + { open(location); } + + + ~Reader() + { close(); } + + void open(const std::string& location); + + void open(const std::string& location, const Properties& dummy_properties, const Header& dummy_header) + { open(location); } + + + void close() + { fin.close(); } + + bool next(T& state) + { Properties dummy; return next(state,dummy); } + + bool next(T& state, Properties& properties_row); + + + }; + + + + } + +} + + +#endif /* __bts_utilities_reader_h__ */ diff --git a/src/bts/utilities/writer.cpp.h b/src/bts/utilities/writer.cpp.h new file mode 100644 index 0000000..c2df827 --- /dev/null +++ b/src/bts/utilities/writer.cpp.h @@ -0,0 +1,65 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, 12/08/2010. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + +#include "bts/utilities/writer.h" +#include "bts/file.h" + + +namespace BTS { + + namespace Utilities { + + + template void Writer::create(const std::string& location) { + + fout.open((location).c_str()); + + if (!fout.good()) + throw Exception("Error opening file '" + location + "'."); + + fout << "%END\n"; + fout.flush(); + + } + + + template void Writer::append(const T& state) { + + if (state.size()) { + + off64_t start_pos = fout.tellp(); + start_pos -= sizeof("%END\n")-1; + fout.seekp(start_pos); + + for (size_t elem_i = 0; elem_i < state.size()-1; ++elem_i) + fout << state[elem_i] << " "; + + fout << state[state.size()-1] << "\n%END\n"; + fout.flush(); + + } else + throw Exception ("No elements found in state."); + } + + } + +} diff --git a/src/bts/utilities/writer.h b/src/bts/utilities/writer.h new file mode 100644 index 0000000..e3d7955 --- /dev/null +++ b/src/bts/utilities/writer.h @@ -0,0 +1,108 @@ +/* + Copyright 2010 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close on 16/06/2010. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + +#ifndef __bts_utilities_writer_h__ +#define __bts_utilities_writer_h__ + +#include "bts/utilities/common.h" + +namespace BTS { + + namespace Utilities { + + template class Writer { + + public: + + std::ofstream fout; + + Writer() {}; + + Writer(const std::string& location) + { create(location); } + + template Writer( const std::string& location, + const U& template_or_reader, + const std::map& properties = std::map()) + { create(location); } + + template Writer( const std::string& location, + const U& template_or_reader, + const Header& key_list, + const std::map& properties = std::map()) + { create(location); } + + + template Writer( const std::string& location, + const U& template_or_reader, + const Header& key_list, + const Header& elem_key_list, + const std::map& properties = std::map()) + { create(location); } + + ~Writer() + { close(); } + + //!Used in template functions, ignores properties. + template void create( const std::string& location, + const U& template_or_reader, + const std::map& properties = std::map()) + { create(location); } + + template void create( const std::string& location, + const U& template_or_reader, + const Header& key_list, + const std::map& properties = std::map()) + { create(location); } + + + template void create( const std::string& location, + const U& template_or_reader, + const Header& key_list, + const Header& elem_key_list, + const std::map& properties = std::map()) + { create(location); } + + + + void create(const std::string& location); + + void close() + { fout.close(); } + + //!Used in template functions, ignores properties. + void append(const T& state, std::map& properties_row) + { append(state); } + + void append(const T& state); + + + }; + + + + } + +} + + +#endif /* __bts_utilities_writer_h__ */ diff --git a/src/bts/version.h b/src/bts/version.h new file mode 100644 index 0000000..c723d5c --- /dev/null +++ b/src/bts/version.h @@ -0,0 +1,93 @@ +/* + Copyright 2008 Brain Research Institute, Melbourne, Australia + + Written by Thomas G Close, 18/02/2011. + + This file is part of MRtrix. + + MRtrix 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. + + MRtrix 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 MRtrix. If not, see . + +*/ + +#ifndef __bts_version_h__ +#define __bts_version_h__ + +namespace BTS { + + const size_t BTS_MAJOR_VERSION = 0; + const size_t BTS_MINOR_VERSION = 0; + const size_t BTS_MICRO_VERSION = 3; + const size_t BTS_NANO_VERSION = 23; + + inline std::string version_number_string() + { return str(BTS_MAJOR_VERSION) + "." + str(BTS_MINOR_VERSION) + "." + str(BTS_MICRO_VERSION) + "." + str(BTS_NANO_VERSION); } + + inline bool before_version (const std::string& version_number_string, size_t major_version, size_t minor_version = 0, size_t micro_version = 0, size_t nano_version = 0) { + + if (!version_number_string.size()) + return true; //If version number is not present assume that it is from an early version (or MRtrix). + + bool is_before = false; + + size_t major_dot_index = version_number_string.find("."); + size_t read_major = to(version_number_string.substr(0,major_dot_index)); + + if (read_major > major_version) + is_before = false; + + else if (read_major < major_version) + is_before = true; + + else { + + size_t minor_dot_index = version_number_string.find(".", major_dot_index + 1); + size_t read_minor = to(version_number_string.substr(major_dot_index + 1, minor_dot_index)); + + if (read_minor > minor_version) + is_before = false; + else if (read_minor < minor_version) + is_before = true; + else { + + size_t micro_dot_index = version_number_string.find(".", minor_dot_index + 1); + size_t read_micro = to(version_number_string.substr(minor_dot_index + 1, micro_dot_index)); + + if (read_micro > micro_version) + is_before = false; + else if (read_micro < micro_version) + is_before = true; + else { + + size_t nano_dot_index = version_number_string.find(".", micro_dot_index + 1); + size_t read_nano = to(version_number_string.substr(micro_dot_index + 1, nano_dot_index)); + + if (read_nano < nano_version) + is_before = true; + else + is_before = false; + + } + + + } + + } + + return is_before; + + } + +} + +#endif /* __bts_version_h__ */ diff --git a/src/k_means/KCtree.cpp b/src/k_means/KCtree.cpp new file mode 100644 index 0000000..5662004 --- /dev/null +++ b/src/k_means/KCtree.cpp @@ -0,0 +1,832 @@ +//---------------------------------------------------------------------- +// File: KCtree.cc +// Programmer: David Mount +// Last modified: 08/10/2005 +// Description: Old methods for kc-trees. +//---------------------------------------------------------------------- +// Copyright (C) 2004-2005 David M. Mount and University of Maryland +// All Rights Reserved. +// +// 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 2 of the License, or (at +// your option) any later version. See the file Copyright.txt in the +// main directory. +// +// The University of Maryland and the authors make no representations +// about the suitability or fitness of this software for any purpose. +// It is provided "as is" without express or implied warranty. +//---------------------------------------------------------------------- + +#include "k_means/KCtree.h" // kc-tree declarations +#include "k_means/KMfilterCenters.h" // center set structure +#include "k_means/KMrand.h" // random number includes + +#include +#include + +//---------------------------------------------------------------------- +// Declaration of local utilities. These are used in getNeighbors(). +//---------------------------------------------------------------------- +static int closestToBox( // get closest point to box center + KMctrIdxArray cands, // candidates for closest + int kCands, // number of candidates + KMorthRect &bnd_box); // bounding box of cell + +static bool pruneTest( // test whether to prune candidate + KMcenter cand, // candidate to test + KMcenter closeCand, // closest candidate + KMorthRect &bnd_box); // bounding box + +static void postNeigh( // assign neighbors to center + KCptr p, // the node posting + KMpoint sum, // the sum of coordinates + double sumSq, // the sum of squares + int n_data, // number of points + KMctrIdx ctrIdx); // center index + +//---------------------------------------------------------------------- +// KCtree constructors +// There is a skeleton kc-tree constructor which does (almost) +// all the initialization, without actually building the tree. +// The arguments are essentially the same as the constructor +// for the kc-tree. The last argument (pi) is an optional array +// for the point indices. Normally, this will be NULL (meaning +// that the constructor should initialize the array of indices), +// but for the load constructor the point indices will be set +// created and passesd through this argument. +//---------------------------------------------------------------------- + +void KCtree::skeletonTree( // construct skeleton tree + KMdataArray pa, // point array (with at least n pts) + int n, // number of points + int dd, // dimension + int n_max, // maximum number of points (optional) + KMpoint bb_lo, // bounding box low point (optional) + KMpoint bb_hi, // bounding box high point (optional) + KMdatIdxArray pi) // point indices (optional) +{ + // initialize basic elements + dim = dd; // dimension + n_pts = n; // number of points + if (n_max < n) n_max = n; // max_pts must be >= n + max_pts = n_max; // set max_pts + + if (pa == NULL) { // no points supplied? + kmError("Points must be supplied to construct tree.", KMabort); + } + pts = pa; // initialize point array + + if (pi == NULL) { // point indices provided? + pidx = new KMdataIdx[max_pts]; // no, allocate them + for (int i = 0; i < n; i++) // initialize to identity + pidx[i] = i; + } + else pidx = pi; // yes, just use them + + + if (bb_lo == NULL || bb_hi == NULL) // boundng box fully specified? + kmEnclRect(pa, pidx, n, dd, bnd_box); // no, construct from points + // save bounding box + if (bb_lo != NULL) // if lower point given, then use it + bnd_box.lo = kmAllocCopyPt(dd, bb_lo); + + if (bb_hi != NULL) // same for upper point + bnd_box.hi = kmAllocCopyPt(dd, bb_hi); + + root = NULL; // no associated tree yet +} + +//---------------------------------------------------------------------- +// OldGlobals - global variables +// To prevent long argument lists in a number of the tree traversal +// programs, we store a number of common global variables here. +// In the case of construction, these are initialized before +// calling buildKcTree. They are used in getNeighbors() and by +// sampleCtr(). +//---------------------------------------------------------------------- + +int kcDim; // dimension of space +int kcDataSize; // number of data points +KMdataArray kcPoints; // data points + +//---------------------------------------------------------------------- +// initOldGlobals - initialize basic globals +//---------------------------------------------------------------------- + +static void initOldGlobals( // initialize basic globals + int dim, // dimension + int data_size, // number of data points + KMdataArray data_pts) // data points +{ + kcDim = dim; + kcDataSize = data_size; + kcPoints = data_pts; +} + +//---------------------------------------------------------------------- +// kc-tree constructor +// This is the main constructor for kc-trees given a set of +// points. It first builds a skeleton tree, then computes the +// bounding box, and then invokes buildKcTree() to actually +// build the tree. It passes in the appropriate splitting +// routine. +// +// The constructor has a number of optional arguments. +// +// n_max Max number of points. (default: n). +// bb_lo, bb_hi Bounding box low and high points (default: +// compute bounding box from points). +// +// As long as the number of points is nonzero, or if a bounding +// box is provided, then the constructor will build a tree with +// at least one node (even an empty leaf). Otherwise, it returns +// with a null tree. +// +// Under the current implementation, point insertion generates +// leaf nodes with a bucket size of 1. If the requested bucket +// size is higher, and it looks like insertion is requested, then +// we generate a warning message. +//---------------------------------------------------------------------- + +KCtree::KCtree( // construct from point array + KMdataArray pa, // point array (with at least n pts) + int n, // number of points + int dd, // dimension + int n_max, // maximum number of points (optional) + KMpoint bb_lo, // bounding box low point (optional) + KMpoint bb_hi) : // bounding box high point (optional) + bnd_box(dd) // create initial bounding box +{ + // set up the basic stuff + skeletonTree(pa, n, dd, n_max, bb_lo, bb_hi, NULL); + initOldGlobals(dd, n, pa); // initialize globals + + root = buildKcTree(pa, pidx, n, dd, bnd_box); + + int ignoreMe1; // ignore results of call + KMpoint ignoreMe2; + double ignoreMe3; + // compute sums + root->makeSums(ignoreMe1, ignoreMe2, ignoreMe3); + assert(ignoreMe1 == n); // should be all the points +} + +//---------------------------------------------------------------------- +// buildKcTree - recursive procedure to build a kc-tree +// Builds a kc-tree for points in pa as indexed through the array +// pidx[0..n-1] (typically a subarray of the array used in the +// top-level call). This routine permutes the array pidx, but does +// not alter pa[]. +// +// The construction is based on a standard algorithm for +// constructing the kc-tree (see Friedman, Bentley, and Finkel, +// ``An algorithm for finding best matches in logarithmic expected +// time,'' ACM Transactions on Mathematical Software, 3(3):209-226, +// 1977). The procedure operates by a simple divide-and-conquer +// strategy, which determines an appropriate orthogonal cutting +// plane (see below), and splits the points. When the number of +// points falls below 1, we simply store the points in a leaf +// node's bucket. +// +// This procedure selects a cutting dimension and cutting value, +// partitions pa about these values, and returns the number of +// points on the low side of the cut. +// +// Note that this procedure is not only used for constructing full +// trees, but is also used by the insertion routine to rebuild a +// subtree. +// +//---------------------------------------------------------------------- + +KCptr KCtree::buildKcTree( // recursive construction of kc-tree + KMdataArray pa, // point array + KMdatIdxArray pidx, // point indices to store in subtree + int n, // number of points + int dim, // dimension of space + KMorthRect &bnd_box) // bounding box for current node +{ + if (n <= 1) { // n small, make a leaf node + return new KCleaf(dim, bnd_box, n, pidx); + } + else { // n large, make a splitting node + int cd; // cutting dimension + KMcoord cv; // cutting value + int n_lo; // number on low side of cut + KCptr lo, hi; // low and high children + + // invoke splitting procedure + sl_midpt_split(pa, pidx, bnd_box, n, dim, cd, cv, n_lo); + + KMcoord lv = bnd_box.lo[cd]; // save bounds for cutting dimension + KMcoord hv = bnd_box.hi[cd]; + + bnd_box.hi[cd] = cv; // modify bounds for left subtree + lo = buildKcTree( // build left subtree + pa, pidx, n_lo, // ...from pidx[0..n_lo-1] + dim, bnd_box); + bnd_box.hi[cd] = hv; // restore bounds + + bnd_box.lo[cd] = cv; // modify bounds for right subtree + hi = buildKcTree( // build right subtree + pa, pidx + n_lo, n-n_lo,// ...from pidx[n_lo..n-1] + dim, bnd_box); + bnd_box.lo[cd] = lv; // restore bounds + + // create the splitting node + KCsplit *ptr = new KCsplit(dim, bnd_box, cd, cv, + lv, hv, lo, hi); + return ptr; // return pointer to this node + } +} + +//---------------------------------------------------------------------- +// cellMidpt - return bounding box midpoint +// The result is returned by modifying the argument. +// getPoint - return point in a leaf cell +// If the leaf cell has no point, then NULL is returned. +// (This cannot be inlined in KCtree.h because of reference +// to thePoints.) +//---------------------------------------------------------------------- + +void KCnode::cellMidpt( // compute cell midpoint + KMpoint pt) // the midpoint (returned) +{ + for (int d = 0; d < kcDim; d++) { // compute box midpoint + pt[d] = (bnd_box.lo[d] + bnd_box.hi[d])/2; + } +} + +KMpoint KCleaf::getPoint() // get data point +{ return (n_data == 1 ? kcPoints[bkt[0]] : NULL); } + + +//---------------------------------------------------------------------- +// kc-tree make sums (part of constructor) +// Computes the sums of points for each node of the kc-tree, +// and the sums of squares (the sums of dot products of each +// point with itself). These values are returned through the +// arguments. +// +// The sum of points is assumed to have been allocated as part +// of the constructor, and hence already exists. +//---------------------------------------------------------------------- + +void KCsplit::makeSums( + int &n, // number of points (returned) + KMpoint &theSum, // sum (returned) + double &theSumSq) // sum of squares (returned) +{ + assert(sum != NULL); // should already be allocated + int n_child = 0; // n_data of child + KMpoint s_child = NULL; // sum of child + double ssq_child = 0; // sum of squares for child + + n_data = 0; // initialize no. points + // process each child + for (int i = KM_LO; i <= KM_HI; i++) { + // visit low child + child[i]->makeSums(n_child, s_child, ssq_child); + n_data += n_child; // increment no. points + for (int d = 0; d < kcDim; d++) { // update sum and sumSq + sum[d] += s_child[d]; + } + sumSq += ssq_child; + } + n = n_data; // return results + theSum = sum; + theSumSq = sumSq; +} + +//---------------------------------------------------------------------- +void KCleaf::makeSums( + int &n, // number of points (returned) + KMpoint &theSum, // sum (returned) + double &theSumSq) // sum of squares (returned) +{ + assert(sum != NULL); // should already be allocated + + sumSq = 0; + for (int i = 0; i < n_data; i++) { // compute sum + for (int d = 0; d < kcDim; d++) { + KMcoord theCoord = kcPoints[bkt[i]][d]; + sum[d] += theCoord; + sumSq += theCoord * theCoord; + } + } + + n = n_data; // return results + theSum = sum; + theSumSq = sumSq; +} + +//---------------------------------------------------------------------- +// kc-tree destructors - deletes kc-tree +// (The other elements of the underlying kd-tree are deleted along +// with the base class.) +// +// Because of our "dirty trick" of recasting all child pointers +// to type KCptr (from KMkd_ptr), we must be careful to not +// allow the kd-tree constructors apply themselves recursively +// to the child nodes. We do this by setting the child pointers +// to NULL after deleting them, which keeps the KMkd_split +// destructor from activating itself. +//---------------------------------------------------------------------- + +KCtree::~KCtree() // tree destructor +{ + if (root != NULL) delete root; + if (pidx != NULL) delete [] pidx; +} + +KCnode::~KCnode() // node destructor +{ + if (sum != NULL) kmDeallocPt(sum); // deallocate sum +} + +//---------------------------------------------------------------------- +// Sample a center point +// This implements an approach suggested by Matoushek for sampling +// a center point. A node of the kd-tree is selected at random. +// If this is an interior node, a point is sampled uniformly from a +// 3x expansion of the cell about its center. If the node is a +// leaf, then a data point is sampled at random from the associated +// bucket. +// +// Here is how sampling is done from an interior node. Let m +// denote the number of data points descended from this node. Then +// with probability 1/(2m-1), this cell is chosen. Otherwise, let +// mL and mR denote the number of points associated with the left +// and right subtrees, respectively. We sample from the left +// subtree with probability (2mL-1)/(2m-1) and sample from the +// right subtree with probability (2mR-1)/(2m-1). +// +// The rationale is that, assuming there is exactly one point per +// leaf node, a subtree with m points has exactly 2m-1 total nodes. +// (This should be true for this implementation, but it depends in +// general on the fact that there is exactly one point per leaf +// node.) Hence the root should be sampled with probability +// 1/(2m-1), and the subtrees should be sampled with the given +// probabilities. +//---------------------------------------------------------------------- + +void KCtree::sampleCtr(KMpoint c) // sample a point +{ + initOldGlobals(dim, n_pts, pts); // initialize globals + // _todo_ bb_save check is just for debugging. + KMorthRect bb_save(dim, bnd_box); // save bounding box + root->sampleCtr(c, bnd_box); // start at root + for (int i = 0; i < dim; i++) { // check that bnd_box unchanged + assert(bb_save.lo[i] == bnd_box.lo[i] && + bb_save.hi[i] == bnd_box.hi[i]); + } +} + +void KCsplit::sampleCtr( // sample from splitting node + KMpoint c, // the sampled point (returned) + KMorthRect &bnd_box) // bounding box for current node +{ + int r = kmRanInt(n_nodes()); // random integer [0..n_nodes-1] + if (r == 0) { // sample from this node + KMorthRect expBox(kcDim); + bnd_box.expand(kcDim, 3, expBox); // compute 3x expanded box + expBox.sample(kcDim, c); // sample c from box + } + else if (r <= child[KM_LO]->n_nodes()) { // sample from left + KMcoord save = bnd_box.hi[cut_dim]; // save old upper bound + bnd_box.hi[cut_dim] = cut_val; // modify for left subtree + child[KM_LO]->sampleCtr(c, bnd_box); + bnd_box.hi[cut_dim] = save; // restore upper bound + } + else { // sample from right subtree + KMcoord save = bnd_box.lo[cut_dim]; // save old lower bound + bnd_box.lo[cut_dim] = cut_val; // modify for right subtree + child[KM_HI]->sampleCtr(c, bnd_box); + bnd_box.lo[cut_dim] = save; // restore lower bound + } +} + +void KCleaf::sampleCtr( // sample from leaf node + KMpoint c, // the sampled point (returned) + KMorthRect &bnd_box) // bounding box for current node +{ + int ri = kmRanInt(n_data); // generate random index + kmCopyPt(kcDim, kcPoints[bkt[ri]], c); // copy to destination +} + +//---------------------------------------------------------------------- +// Printing the kc-tree +// These routines print a kc-tree in reverse inorder (high then +// root then low). (This is so that if you look at the output +// from the right side it appear from left to right in standard +// inorder.) When outputting leaves we output only the point +// indices rather than the point coordinates. There is an option +// to print the point coordinates separately. +// +// The tree printing routine calls the printing routines on the +// individual nodes of the tree, passing in the level or depth +// in the tree. The level in the tree is used to print indentation +// for readability. +//---------------------------------------------------------------------- + +void KCsplit::print( // print splitting node + int level) // depth of node in tree +{ + // print high child + child[KM_HI]->print(level+1); + + *kmOut << " "; // print indentation + for (int i = 0; i < level; i++) + *kmOut << "."; + + kmOut->precision(4); + *kmOut << "Split" // print without address + << " cd=" << cut_dim << " cv=" << setw(6) << cut_val + << " nd=" << n_data + << " sm="; kmPrintPt(sum, kcDim, true); + *kmOut << " ss=" << sumSq << "\n"; + // print low child + child[KM_LO]->print(level+1); +} + +//---------------------------------------------------------------------- +void KCleaf::print( // print leaf node + int level) // depth of node in tree +{ + *kmOut << " "; + for (int i = 0; i < level; i++) // print indentation + *kmOut << "."; + + // *kmOut << "Leaf <" << (void*) this << ">"; + *kmOut << "Leaf"; // print without address + *kmOut << " n=" << n_data << " <"; + for (int j = 0; j < n_data; j++) { + *kmOut << bkt[j]; + if (j < n_data-1) *kmOut << ","; + } + *kmOut << ">" + << " sm="; kmPrintPt(sum, kcDim, true); + *kmOut << " ss=" << sumSq << "\n"; +} + +//---------------------------------------------------------------------- +void KCtree::print( // print entire tree + bool with_pts) // print points as well? +{ + if (with_pts) { // print point coordinates + *kmOut << " Points:\n"; + for (int i = 0; i < n_pts; i++) { + *kmOut << "\t" << i << ": "; + kmPrintPt(pts[i], kcDim, true); + *kmOut << "\n"; + } + } + if (root == NULL) // empty tree? + *kmOut << " Null tree.\n"; + else { + root->print(0); // invoke printing at root + } +} + +//---------------------------------------------------------------------- +// DistGlobals - globals used in computing distortions +// To prevent long argument lists in the computation of +// distortions, we store a number of common global variables here. +// These are initialized in KCtree::getNeighbors. +// +// Note: kcDim and kcPoints (from Old Globals) are used as well. +//---------------------------------------------------------------------- + +int kcKCtrs; // number of centers +int* kcWeights; // weights of each point +KMpointArray kcCenters; // the center points +KMpointArray kcSums; // sums +double* kcSumSqs; // sum of squares +double* kcDists; // distortions +KMpoint kcBoxMidpt; // bounding-box midpoint + +//---------------------------------------------------------------------- +// initDistGlobals - initialize distortion globals +//---------------------------------------------------------------------- + +static void initDistGlobals( // initialize distortion globals + KMfilterCenters& ctrs) // the centers +{ + initOldGlobals(ctrs.getDim(), ctrs.getNPts(), ctrs.getDataPts()); + kcKCtrs = ctrs.getK(); + kcCenters = ctrs.getCtrPts(); // get ptrs to KMcenter arrays + kcWeights = ctrs.getWeights(false); + kcSums = ctrs.getSums(false); + kcSumSqs = ctrs.getSumSqs(false); + kcDists = ctrs.getDists(false); + kcBoxMidpt = kmAllocPt(kcDim); + + for (int j = 0; j < kcKCtrs; j++) { // initialize sums + kcWeights[j] = 0; + kcSumSqs[j] = 0; + for (int d = 0; d < kcDim; d++) { + kcSums[j][d] = 0; + } + } +} + +static void deleteDistGlobals() // delete distortion globals +{ + kmDeallocPt(kcBoxMidpt); +} + +//---------------------------------------------------------------------- +// getNeighbors - get neighbors for each candidate +// This is the heart of the filter-based k-means algorithm. It is +// given an array of centers (ctrs) and an array of center sums +// (sums), and an array of sums of squares (sumSqs). All three +// arrays consist of k points. It computes the sum, sum of +// squares, and weights of all the neighbors of each center, and +// stores the results in these arrays. From these quantities, the +// final centroid and distortion (mean squared error) can be +// computed. +// +// This is done by determining the set of candidates for each node +// in the kc-tree. When the number of candidates for a node is +// equal to 1 (it cannot be 0) then all of the points in the +// subtree rooted at this node are assigned as neighbors to this +// center. This means that the centroid and weight for this cell +// is added into the neighborhood centroid sum for this center. If +// this node is a leaf, then we compute (by brute-force) the +// distance from each candidate to each data point, and assign the +// data point to the closest center. +// +// The key to pruning the set of candidates for each node is +// handled by two functions. The function nearCand() finds the +// candidate that is nearest to the midpoint of the cell. The +// function pruneTest() determines whether another candidate is +// close enough to the cell to be closer to some part of the cell +// than the nearest candidate. +//---------------------------------------------------------------------- + +void KCtree::getNeighbors( // compute neighbors for centers + KMfilterCenters& ctrs) // the centers +{ + initDistGlobals(ctrs); // initialize globals + int *candIdx = new int[kcKCtrs]; // allocate center indices + for (int j = 0; j < kcKCtrs; j++) { // initialize everything + candIdx[j] = j; // initialize indices + } + root->getNeighbors(candIdx, kcKCtrs); // get neighbors for tree + delete [] candIdx; // delete center indices + deleteDistGlobals(); // delete globals +} + +//---------------------------------------------------------------------- +void KCsplit::getNeighbors( // get neighbors for internal node + KMctrIdxArray cands, // candidate centers + int kCands) // number of centers +{ + if (kCands == 1) { // only one cand left? + // post points as neighbors + postNeigh(this, sum, sumSq, n_data, cands[0]); + } + else { + // get closest cand to box + int cc = closestToBox(cands, kCands, bnd_box); + KMctrIdx closeCand = cands[cc]; // closest candidate index + // space for new candidates + KMctrIdxArray newCands = new KMctrIdx[kCands]; + int newK = 0; // number of new candidates + for (int j = 0; j < kCands; j++) { + if (j == cc || !pruneTest( // is candidate close enough? + kcCenters[cands[j]], + kcCenters[closeCand], + bnd_box)) { + newCands[newK++] = cands[j]; // yes, keep it + } + } + // apply to children + child[KM_LO]->getNeighbors(newCands, newK); + child[KM_HI]->getNeighbors(newCands, newK); + delete [] newCands; // delete new candidates + } +} + +//---------------------------------------------------------------------- +void KCleaf::getNeighbors( // get neighbors for leaf node + KMctrIdxArray cands, // candidate centers + int kCands) // number of centers +{ + if (kCands == 1) { // only one cand left? + // post points as neighbors + postNeigh(this, sum, sumSq, n_data, cands[0]); + } + else { // find closest centers + for (int i = 0; i < n_data; i++) { // for each point in bucket + KMdist minDist = KM_DIST_INF; // distance to nearest point + int minK = 0; // index of this point + KMpoint thisPt = kcPoints[bkt[i]]; // this data point + + for (int j = 0; j < kCands; j++) { // compute closest candidate + KMdist dist = kmDist(kcDim, kcCenters[cands[j]], thisPt); + if (dist < minDist) { // best so far? + minDist = dist; // yes, save it + minK = j; // ...and its index + } + } + postNeigh(this, kcPoints[bkt[i]], sumSq, 1, cands[minK]); + } + } +} + +//---------------------------------------------------------------------- +// getAssignments +// This determines the assignments of the closest center to each of +// the data points. It is basically a structural copy of the +// procedure getNeighbors, but rather than incrementing the various +// sums and sums of squares, it simply records the assignment of +// each data point to its closest center. Unlike the filtering +// search, when only one candidate remains, it does not stop the +// search, but continues to traverse all the leaves descended from +// this node in order to perform the assignments. +//---------------------------------------------------------------------- + +void KCtree::getAssignments( // compute assignments for points + KMfilterCenters& ctrs, // the current centers + KMctrIdxArray closeCtr, // closest center per point + double* sqDist) // sq'd distance to center +{ + initDistGlobals(ctrs); // initialize globals + + int *candIdx = new int[kcKCtrs]; // allocate center indices + for (int j = 0; j < kcKCtrs; j++) { // initialize everything + candIdx[j] = j; // initialize indices + } + // search the tree + root->getAssignments(candIdx, kcKCtrs, closeCtr, sqDist); + delete [] candIdx; // delete center indices + deleteDistGlobals(); // delete globals +} + +//---------------------------------------------------------------------- +void KCsplit::getAssignments( // get assignments for internal node + KMctrIdxArray cands, // candidate centers + int kCands, // number of centers + KMctrIdxArray closeCtr, // closest center per point + double* sqDist) // sq'd distance to center +{ + if (kCands == 1) { // only one cand left? + // no more pruning needed + child[KM_LO]->getAssignments(cands, kCands, closeCtr, sqDist); + child[KM_HI]->getAssignments(cands, kCands, closeCtr, sqDist); + } + else { + // get closest cand to box + int cc = closestToBox(cands, kCands, bnd_box); + KMctrIdx closeCand = cands[cc]; // closest candidate index + // space for new candidates + KMctrIdxArray newCands = new KMctrIdx[kCands]; + int newK = 0; // number of new candidates + for (int j = 0; j < kCands; j++) { + if (j == cc || !pruneTest( // is candidate close enough? + kcCenters[cands[j]], + kcCenters[closeCand], + bnd_box)) { + newCands[newK++] = cands[j]; // yes, keep it + } + } + // apply to children + child[KM_LO]->getAssignments(newCands, newK, closeCtr, sqDist); + child[KM_HI]->getAssignments(newCands, newK, closeCtr, sqDist); + delete [] newCands; // delete new candidates + } +} + +//---------------------------------------------------------------------- +void KCleaf::getAssignments( // get assignments for leaf node + KMctrIdxArray cands, // candidate centers + int kCands, // number of centers + KMctrIdxArray closeCtr, // closest center per point + double* sqDist) // sq'd distance to center +{ + for (int i = 0; i < n_data; i++) { // for each point in bucket + KMdist minDist = KM_DIST_INF; // distance to nearest point + int minK = 0; // index of this point + KMpoint thisPt = kcPoints[bkt[i]]; // this data point + + for (int j = 0; j < kCands; j++) { // compute closest candidate + KMdist dist = kmDist(kcDim, kcCenters[cands[j]], thisPt); + if (dist < minDist) { // best so far? + minDist = dist; // yes, save it + minK = j; // ...and its index + } + } + if (closeCtr != NULL) closeCtr[bkt[i]] = cands[minK]; + if (sqDist != NULL) sqDist[bkt[i]] = minDist; + } +} + +//---------------------------------------------------------------------- +// Local utilities +//---------------------------------------------------------------------- + +//---------------------------------------------------------------------- +// closestToBox - compute the closest point to the box +// This procedure is given a list of candidates (cands), the number +// of candidates (kCands), and a cell (bnd_box), and returns the +// index (in cands) of the element of cands that is closest to the +// midpoint of the cell. The global variable kcBoxMidpt is used to +// store the cell midpoint. +//---------------------------------------------------------------------- + +static int closestToBox( // get closest point to box center + KMctrIdxArray cands, // candidates for closest + int kCands, // number of candidates + KMorthRect &bnd_box) // bounding box of cell +{ + for (int d = 0; d < kcDim; d++) { // compute midpoint + kcBoxMidpt[d] = (bnd_box.lo[d] + bnd_box.hi[d])/2; + } + + KMdist minDist = KM_DIST_INF; // distance to nearest point + int minK = 0; // index of this point + + for (int j = 0; j < kCands; j++) { // compute dist to each point + KMdist dist = kmDist(kcDim, kcCenters[cands[j]], kcBoxMidpt); + if (dist < minDist) { // best so far? + minDist = dist; // yes, save it + minK = j; // ...and its index + } + } + return minK; // return closest index +} + +//---------------------------------------------------------------------- +// pruneTest - determine whether a point should be pruned +// This procedure is given a cell of the kc-tree (bnd_box or B), +// and candidate (cand or c) and the closest candidate to the +// cell (closeCand or c'). It determines whether the entire +// cell is closer to c' than it is to c. +// +// The procedure works by considering the relationship between +// two vectors. Let (a.b) denote the dot product of vectors a +// and b. Observe that a point p is closer c than to c' if and +// only if +// +// (p-c).(p-c) < (p-c').(p-c') +// +// after simple manipulations this is true if and only if +// +// (c-c').(c-c') < 2(p-c').(c-c'). +// +// We want to know whether this relation is satisfied for any +// point p in B. If so then it is satisfied for the point p +// in B that maximizes (p-c').(c-c'). Observe that p will be +// a vertex of B. To determine p, we consider the sign of each +// coordinate of (c-c'). If the d-th coordinate is positive then +// we set p[d] = B.hi[d], and otherwise we set it to B.lo[d]. +// +// NOTE: This procedure assumes that Euclidean distances are +// used. +//---------------------------------------------------------------------- + +static bool pruneTest( + KMcenter cand, // candidate to test + KMcenter closeCand, // closest candidate + KMorthRect &bnd_box) // bounding box +{ + double boxDot = 0; // holds (p-c').(c-c') + double ccDot = 0; // holds (c-c').(c-c') + for (int d = 0; d < kcDim; d++) { + double ccComp = cand[d] - closeCand[d]; // one component c-c' + ccDot += ccComp * ccComp; // increment dot product + if (ccComp > 0) { // candidate on high side + // use high side of box + boxDot += (bnd_box.hi[d] - closeCand[d]) * ccComp; + } + else { // candidate on low side + // use low side of box + boxDot += (bnd_box.lo[d] - closeCand[d]) * ccComp; + } + } + return (ccDot >= 2*boxDot); // return final result +} + +//---------------------------------------------------------------------- +// postNeigh - registers neighbors for a given candidate +// This procedure registers a set of points as neighbors +// of a given center (cand). The points are represented by +// their sum and sum of squares. A pointer to the +// node doing the posting is passed along, but it is used +// only if tracing. +//---------------------------------------------------------------------- + +static void postNeigh( + KCptr p, // the node posting + KMpoint sum, // the sum of coordinates + double sumSq, // the sum of squares + int n_data, // number of points + KMctrIdx ctrIdx) // center index +{ + for (int d = 0; d < kcDim; d++) { // increment sum + kcSums[ctrIdx][d] += sum[d]; + } + kcWeights[ctrIdx] += n_data; // increment weight + kcSumSqs[ctrIdx] += sumSq; // incr sum of squares +} diff --git a/src/k_means/KCtree.h b/src/k_means/KCtree.h new file mode 100644 index 0000000..b115701 --- /dev/null +++ b/src/k_means/KCtree.h @@ -0,0 +1,315 @@ +//---------------------------------------------------------------------- +// File: KCtree.h +// Programmer: David Mount +// Last modified: 08/10/2005 +// Description: Declarations for standard kc-tree routines +//---------------------------------------------------------------------- +// Copyright (C) 2004-2005 David M. Mount and University of Maryland +// All Rights Reserved. +// +// 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 2 of the License, or (at +// your option) any later version. See the file Copyright.txt in the +// main directory. +// +// The University of Maryland and the authors make no representations +// about the suitability or fitness of this software for any purpose. +// It is provided "as is" without express or implied warranty. +//---------------------------------------------------------------------- + +#ifndef KC_TREE_H +#define KC_TREE_H + +#include + +#include "k_means/KMeans.h" // all k-means includes +#include "k_means/KCutil.h" // kc-tree utilities + +class KMfilterCenters; // see KMfilterCenters.h + +//---------------------------------------------------------------------- +// kc-tree - the k-center tree. +// This is a stripped-down modification of the kd-tree of the ANN +// library (see ann/include/ANN/ANN.h and ann/src/kd_tree.h). +// There are a number of technical difficulties in attempting to +// design this structure through inheritance.) The main difference +// is that we do not support nearest neighbor searching, but +// instead support an operation (getNeighbors) which given a set of +// center points, computes the subset of data points in the tree +// that is closest to each center. +// +// In addition to the kd-tree information, the nodes of the kc-tree +// also store the number of data points associated with each node +// of the tree and they keep an associated sum and sums of squares +// for these points. There are also a few 'hooks' inserted for +// the eventual goal of extending this to a dynamic structure. +// +// The tree is constructed in three phases. The first phase is +// borrowed from the ANN library, and builds the kc-tree for the +// data points. The second phase computes sum and sum of squares +// for each node, by a simple postorder tree traversal. The third +// phase (which may be repeated) is given a set of centers, and +// computes the candidates for each node in the tree. +//---------------------------------------------------------------------- +class KCnode; +typedef KCnode *KCptr; // pointer to kc-node + +class KCtree { +protected: + int dim; // dimension of space + int n_pts; // number of points in tree + int max_pts; // max number of points in tree + KMdataArray pts; // the points (of size max(n,m_max)) + KMdatIdxArray pidx; // point indices (to pts) + KCptr root; // root of kc-tree + KMorthRect bnd_box; // bounding box +//---------------------------------------------------------------------- +// Protected utilities +// skeletonTree Initializes the basic tree elements (without +// building the tree). +// builtKc_tree Recursive utility that actually builds the +// kc-tree from a set of points. +//---------------------------------------------------------------------- + void skeletonTree( // construct skeleton tree + KMdataArray pa, // point array (with at least n pts) + int n, // number of points + int dd, // dimension + int n_max, // maximum number of points (optional) + KMpoint bb_lo, // bounding box low point (optional) + KMpoint bb_hi, // bounding box high point (optional) + KMdatIdxArray pi); // point indices (optional) + + KCptr buildKcTree( // recursive construction of kc-tree + KMdataArray pa, // point array + KMdatIdxArray pidx, // point indices to store in subtree + int n, // number of points + int dim, // dimension of space + KMorthRect &bnd_box); // bounding box for current node + +public: + KCtree( // build from point array + KMdataArray pa, // point array + int n, // number of points + int dd, // dimension + int n_max = 0, // max num of points (def = n) + KMpoint bb_lo = NULL, // bounding box low point + KMpoint bb_hi = NULL); // bounding box high point + + // compute neighbors for centers + void getNeighbors(KMfilterCenters& ctrs); + + void getAssignments( // compute assignments for points + KMfilterCenters& ctrs, // the current centers + KMctrIdxArray closeCtr, // closest center per point + double* sqDist); // sq'd distance to center + + ~KCtree(); // tree destructor + + void sampleCtr(KMpoint c); // sample a center point c + + void print( // print the tree (for debugging) + bool with_pts); // print points as well? +}; + +//---------------------------------------------------------------------- +// Generic kc-tree node +// Nodes in kc-trees are of two types, splitting nodes which contain +// splitting information (a splitting hyperplane orthogonal to one +// of the coordinate axes) and leaf nodes which contain point +// information (an array of points stored in a bucket). This is +// handled by making a generic class kc-node. The kc-node contains +// the following basic information. +// +// n_data The number of data points associated +// with this node. +// sum This is the sum of points (i.e., the +// weighted centroid) of all the points +// associated with this node. +// sumSq This is the sum of squares (i.e., the +// sum of the dot products of each point +// with itself). +// bnd_box Bounding box for the cell. +// +// NOTE: The constructor does no (interesting) initialization. +// This is handled in getSums(). +//---------------------------------------------------------------------- + +class KCnode { // generic kc-tree node +protected: + const int multCand; // multiple candidate flag + int n_data; // number of data points + KMpoint sum; // sum of points + double sumSq; // sum of squares + KMorthRect bnd_box; // bounding box for cell +public: + KCnode( // basic constructor + int dim, // dimension + KMorthRect &bb) // bounding box + : multCand(-1), bnd_box(dim, bb)// create bounding box + { sum = kmAllocPt(dim, 0); sumSq = 0; } + + virtual ~KCnode(); // destructor + + void cellMidpt(KMpoint pt); // get cell's midpoint (pt modified) + + KMorthRect &bndBox() // get cell's bounding box + { return bnd_box; } + + virtual void makeSums( // compute sums of points + int &n, // number of points (returned) + KMpoint &theSum, // sum (returned) + double &theSumSq) = 0; // sum of squares (returned) + + virtual void getNeighbors( // compute neighbors for centers + KMctrIdxArray cands, // candidate centers + int kCands) = 0; // number of centers + + virtual void getAssignments( // get assignments for leaf node + KMctrIdxArray cands, // candidate centers + int kCands, // number of centers + KMctrIdxArray closeCtr, // closest center per point + double* sqDist) = 0; // sq'd distance to center + + // sample a center point c + virtual void sampleCtr(KMpoint c, KMorthRect& bb) = 0; + // + virtual void print(int level) = 0; // print node + + int n_nodes() // number of nodes in this subtree + { return 2*n_data - 1; } // this assumes bucket size=1! + + friend class KCtree; // allow kc-tree to access us +}; + +//---------------------------------------------------------------------- +// Leaf kc-tree node +// Leaf nodes of the kc-tree store the set of points associated +// with this bucket, stored as an array of point indices. These +// are indices in the array points, which resides with the +// root of the kc-tree. We also store the number of points +// that reside in this bucket. +//---------------------------------------------------------------------- + +class KCleaf: public KCnode +{ +protected: + KMidxArray bkt; // bucket of points +public: + KCleaf( // constructor + int dim, // dimension + KMorthRect &bb, // bounding box + int n, // number of points + KMdatIdxArray b) // the bucket + : KCnode(dim, bb) // create kc-node + { assert(n <= 1); n_data = n; bkt = b; } + + virtual ~KCleaf() {} // destructor (none) + + KMpoint getPoint(); // get data point + + virtual void makeSums( // compute sums + int &n, // number of points (returned) + KMpoint &theSum, // sum (returned) + double &theSumSq); // sum of squares (returned) + + virtual void getNeighbors( // compute neighbors for centers + KMctrIdxArray cands, // candidate centers + int kCands); // number of centers + + virtual void getAssignments( // get assignments for leaf node + KMctrIdxArray cands, // candidate centers + int kCands, // number of centers + KMctrIdxArray closeCtr, // closest center per point + double* sqDist); // sq'd distance to center + + // sample a center point c + virtual void sampleCtr(KMpoint c, KMorthRect& bb); + + // print node + virtual void print(int level); +}; + +//---------------------------------------------------------------------- +// kc-tree splitting node. +// Splitting nodes contain a cutting dimension and a cutting value. +// These indicate the axis-parellel plane which subdivide the +// box for this node. The extent of the bounding box along the +// cutting dimension is maintained (this is used to speed up point +// to box distance calculations) [we do not store the entire bounding +// box since this may be wasteful of space in high dimensions]. +// We also store pointers to the 2 children. +//---------------------------------------------------------------------- + +class KCsplit : public KCnode // splitting node of a kc-tree +{ +protected: + int cut_dim; // dim orthogonal to cutting plane + KMcoord cut_val; // location of cutting plane + KMcoord cd_bnds[2]; // lower and upper bounds of + // rectangle along cut_dim + KCptr child[2]; // left and right children +public: + KCsplit( // constructor + int dim, // cutting dimension + KMorthRect &bb, // bounding box + int cd, // cutting dimension + KMcoord cv, // cutting value + KMcoord lv, KMcoord hv, // low and high values + KCptr lc=NULL, KCptr hc=NULL) // children + : KCnode(dim, bb) // create kc-node + { + cut_dim = cd; // cutting dimension + cut_val = cv; // cutting value + cd_bnds[KM_LO] = lv; // lower bound for rectangle + cd_bnds[KM_HI] = hv; // upper bound for rectangle + child[KM_LO] = lc; // left child + child[KM_HI] = hc; // right child + } + + virtual ~KCsplit() // destructor + { + if (child[KM_LO] != NULL) delete child[KM_LO]; + if (child[KM_HI] != NULL) delete child[KM_HI]; + } + + virtual void makeSums( // compute sums + int &n, // number of points (returned) + KMpoint &theSum, // sum (returned) + double &theSumSq); // sum of squares (returned) + + virtual void getNeighbors( // compute neighbors for centers + KMctrIdxArray cands, // candidate centers + int kCands); // number of centers + + virtual void getAssignments( // get assignments for leaf node + KMctrIdxArray cands, // candidate centers + int kCands, // number of centers + KMctrIdxArray closeCtr, // closest center per point + double* sqDist); // sq'd distance to center + + // sample a center point c + virtual void sampleCtr(KMpoint c, KMorthRect& bb); + + // print node + virtual void print(int level); +}; + +//---------------------------------------------------------------------- +// kc-splitting function: +// kd_splitter is a pointer to a splitting procedure for preprocessing. +// Different splitting procedures result in different strategies +// for building the tree. +//---------------------------------------------------------------------- + +typedef void (*KMkd_splitter)( // splitting procedure for kd-trees + KMpointArray pa, // point array (unaltered) + KMidxArray pidx, // point indices (permuted on return) + const KMorthRect &bnds, // bounding rectangle for cell + int n, // number of points + int dim, // dimension of space + int &cut_dim, // cutting dimension (returned) + KMcoord &cut_val, // cutting value (returned) + int &n_lo); // num of points on low side (returned) + +#endif diff --git a/src/k_means/KCutil.cpp b/src/k_means/KCutil.cpp new file mode 100644 index 0000000..093b8ff --- /dev/null +++ b/src/k_means/KCutil.cpp @@ -0,0 +1,240 @@ +//---------------------------------------------------------------------- +// File: KCutil.h +// Programmer: David Mount +// Last modified: 03/27/02 +// Description: Utilities for kc-tree splitting rules +//---------------------------------------------------------------------- +// Copyright (C) 2004-2005 David M. Mount and University of Maryland +// All Rights Reserved. +// +// 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 2 of the License, or (at +// your option) any later version. See the file Copyright.txt in the +// main directory. +// +// The University of Maryland and the authors make no representations +// about the suitability or fitness of this software for any purpose. +// It is provided "as is" without express or implied warranty. +//---------------------------------------------------------------------- + +#include "k_means/KCutil.h" // kc-utility declarations + +//---------------------------------------------------------------------- +// NOTE: Virtually all point indexing is done through an +// index (i.e. permutation) array pidx. Consequently, +// a reference to the d-th coordinate of the i-th point +// is pa[pidx[i]][d]. The macro PA(i,d) is a shorthand +// for this. +//---------------------------------------------------------------------- + // standard 2-d indirect indexing +#define PA(i,d) (pa[pidx[(i)]][(d)]) + // accessing a single point +#define PP(i) (pa[pidx[(i)]]) + // swap two points +#define PASWAP(a,b) { int tmp = pidx[a];\ + pidx[a] = pidx[b];\ + pidx[b] = tmp; } + +//---------------------------------------------------------------------- +// Constants +//---------------------------------------------------------------------- + +const double ERR = 0.001; // a small value + +//---------------------------------------------------------------------- +// kmEnclRect, kmEnclCube +// These utilities compute the smallest rectangle and cube enclosing +// a set of points, respectively. +//---------------------------------------------------------------------- + +void kmEnclRect( + KMpointArray pa, // point array + KMidxArray pidx, // point indices + int n, // number of points + int dim, // dimension + KMorthRect &bnds) // bounding cube (returned) +{ + for (int d = 0; d < dim; d++) { // find smallest enclosing rectangle + KMcoord lo_bnd = PA(0,d); // lower bound on dimension d + KMcoord hi_bnd = PA(0,d); // upper bound on dimension d + for (int i = 0; i < n; i++) { + if (PA(i,d) < lo_bnd) lo_bnd = PA(i,d); + else if (PA(i,d) > hi_bnd) hi_bnd = PA(i,d); + } + bnds.lo[d] = lo_bnd; + bnds.hi[d] = hi_bnd; + } +} + +//---------------------------------------------------------------------- +// kmSpread - find spread along given dimension +// kmMinMax - find min and max coordinates along given dimension +// kmMaxSpread - find dimension of max spread +//---------------------------------------------------------------------- + +KMcoord kmSpread( // compute point spread along dimension + KMpointArray pa, // point array + KMidxArray pidx, // point indices + int n, // number of points + int d) // dimension to check +{ + KMcoord min = PA(0,d); // compute max and min coords + KMcoord max = PA(0,d); + for (int i = 1; i < n; i++) { + KMcoord c = PA(i,d); + if (c < min) min = c; + else if (c > max) max = c; + } + return (max - min); // total spread is difference +} + +void kmMinMax( // compute min and max coordinates along dim + KMpointArray pa, // point array + KMidxArray pidx, // point indices + int n, // number of points + int d, // dimension to check + KMcoord &min, // minimum value (returned) + KMcoord &max) // maximum value (returned) +{ + min = PA(0,d); // compute max and min coords + max = PA(0,d); + for (int i = 1; i < n; i++) { + KMcoord c = PA(i,d); + if (c < min) min = c; + else if (c > max) max = c; + } +} + +//---------------------------------------------------------------------- +// kmPlaneSplit - split point array about a cutting plane +// Split the points in an array about a given plane along a +// given cutting dimension. On exit, br1 and br2 are set so +// that: +// +// pa[ 0 ..br1-1] < cv +// pa[br1..br2-1] == cv +// pa[br2.. n -1] > cv +// +// All indexing is done indirectly through the index array pidx. +//---------------------------------------------------------------------- + +void kmPlaneSplit( // split points by a plane + KMpointArray pa, // points to split + KMidxArray pidx, // point indices + int n, // number of points + int d, // dimension along which to split + KMcoord cv, // cutting value + int &br1, // first break (values < cv) + int &br2) // second break (values == cv) +{ + int l = 0; + int r = n-1; + for(;;) { // partition pa[0..n-1] about cv + while (l < n && PA(l,d) < cv) l++; + while (r >= 0 && PA(r,d) >= cv) r--; + if (l > r) break; + PASWAP(l,r); + l++; r--; + } + br1 = l; // now: pa[0..br1-1] < cv <= pa[br1..n-1] + r = n-1; + for(;;) { // partition pa[br1..n-1] about cv + while (l < n && PA(l,d) <= cv) l++; + while (r >= br1 && PA(r,d) > cv) r--; + if (l > r) break; + PASWAP(l,r); + l++; r--; + } + br2 = l; // now: pa[br1..br2-1] == cv < pa[br2..n-1] +} + +//---------------------------------------------------------------------- +// sl_midpt_split - sliding midpoint splitting rule +// +// This is a modification of midpt_split, which has the nonsensical +// name "sliding midpoint". The idea is that we try to use the +// midpoint rule, by bisecting the longest side. If there are +// ties, the dimension with the maximum spread is selected. If, +// however, the midpoint split produces a trivial split (no points +// on one side of the splitting plane) then we slide the splitting +// (maintaining its orientation) until it produces a nontrivial +// split. For example, if the splitting plane is along the x-axis, +// and all the data points have x-coordinate less than the x-bisector, +// then the split is taken along the maximum x-coordinate of the +// data points. +// +// Intuitively, this rule cannot generate trivial splits, and +// hence avoids midpt_split's tendency to produce trees with +// a very large number of nodes. +// +//---------------------------------------------------------------------- + +void sl_midpt_split( + KMpointArray pa, // point array + KMidxArray pidx, // point indices (permuted on return) + const KMorthRect &bnds, // bounding rectangle for cell + int n, // number of points + int dim, // dimension of space + int &cut_dim, // cutting dimension (returned) + KMcoord &cut_val, // cutting value (returned) + int &n_lo) // num of points on low side (returned) +{ + int d; + + KMcoord max_length = bnds.hi[0] - bnds.lo[0]; + for (d = 1; d < dim; d++) { // find length of longest box side + KMcoord length = bnds.hi[d] - bnds.lo[d]; + if (length > max_length) { + max_length = length; + } + } + KMcoord max_spread = -1; // find long side with most spread + for (d = 0; d < dim; d++) { + // is it among longest? + if ((bnds.hi[d] - bnds.lo[d]) >= (1-ERR)*max_length) { + // compute its spread + KMcoord spr = kmSpread(pa, pidx, n, d); + if (spr > max_spread) { // is it max so far? + max_spread = spr; + cut_dim = d; + } + } + } + // ideal split at midpoint + KMcoord ideal_cut_val = (bnds.lo[cut_dim] + bnds.hi[cut_dim])/2; + + KMcoord min, max; + kmMinMax(pa, pidx, n, cut_dim, min, max); // find min/max coordinates + + if (ideal_cut_val < min) // slide to min or max as needed + cut_val = min; + else if (ideal_cut_val > max) + cut_val = max; + else + cut_val = ideal_cut_val; + + // permute points accordingly + int br1, br2; + kmPlaneSplit(pa, pidx, n, cut_dim, cut_val, br1, br2); + //------------------------------------------------------------------ + // On return: pa[pidx[[0..br1-1]] < cut_val + // pa[pidx[[br1..br2-1]] = cut_val + // pa[pidx[[br2..n-1]] > cut_val + // + // We can set n_lo to any value in the range [br1..br2] to satisfy + // the exit conditions of the procedure. + // + // if ideal_cut_val < min (implying br2 >= 1), + // then we select n_lo = 1 (so there is one point on left) and + // if ideal_cut_val > max (implying br1 <= n-1), + // then we select n_lo = n-1 (so there is one point on right). + // Otherwise, we select n_lo as close to n/2 as possible within + // [br1..br2]. + //------------------------------------------------------------------ + if (ideal_cut_val < min) n_lo = 1; + else if (ideal_cut_val > max) n_lo = n-1; + else if (br1 > n/2) n_lo = br1; + else if (br2 < n/2) n_lo = br2; + else n_lo = n/2; +} diff --git a/src/k_means/KCutil.h b/src/k_means/KCutil.h new file mode 100644 index 0000000..342bf12 --- /dev/null +++ b/src/k_means/KCutil.h @@ -0,0 +1,70 @@ +//---------------------------------------------------------------------- +// File: KCutil.h +// Programmer: David Mount +// Last modified: 03/27/02 +// Description: Declarations for kc-tree utilities +//---------------------------------------------------------------------- +// Copyright (C) 2004-2005 David M. Mount and University of Maryland +// All Rights Reserved. +// +// 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 2 of the License, or (at +// your option) any later version. See the file Copyright.txt in the +// main directory. +// +// The University of Maryland and the authors make no representations +// about the suitability or fitness of this software for any purpose. +// It is provided "as is" without express or implied warranty. +//---------------------------------------------------------------------- + +#ifndef KC_UTIL_H +#define KC_UTIL_H + +#include "k_means/KCtree.h" // kc-tree declarations + +//---------------------------------------------------------------------- +// externally accessible functions +//---------------------------------------------------------------------- + +void kmEnclRect( // compute smallest enclosing rectangle + KMpointArray pa, // point array + KMidxArray pidx, // point indices + int n, // number of points + int dim, // dimension + KMorthRect &bnds); // bounding cube (returned) + +KMcoord kmSpread( // compute point spread along dimension + KMpointArray pa, // point array + KMidxArray pidx, // point indices + int n, // number of points + int d); // dimension to check + +void kmMinMax( // compute min and max coordinates along dim + KMpointArray pa, // point array + KMidxArray pidx, // point indices + int n, // number of points + int d, // dimension to check + KMcoord& min, // minimum value (returned) + KMcoord& max); // maximum value (returned) + +void kmPlaneSplit( // split points by a plane + KMpointArray pa, // points to split + KMidxArray pidx, // point indices + int n, // number of points + int d, // dimension along which to split + KMcoord cv, // cutting value + int &br1, // first break (values < cv) + int &br2); // second break (values == cv) + +void sl_midpt_split( // sliding midpoint kd-splitter + KMpointArray pa, // point array (unaltered) + KMidxArray pidx, // point indices (permuted on return) + const KMorthRect &bnds, // bounding rectangle for cell + int n, // number of points + int dim, // dimension of space + int &cut_dim, // cutting dimension (returned) + KMcoord &cut_val, // cutting value (returned) + int &n_lo); // num of points on low side (returned) + +#endif diff --git a/src/k_means/KM_ANN.cpp b/src/k_means/KM_ANN.cpp new file mode 100644 index 0000000..d6ad2ec --- /dev/null +++ b/src/k_means/KM_ANN.cpp @@ -0,0 +1,191 @@ +//---------------------------------------------------------------------- +// File: KM_ANN.cc +// Programmer: David Mount +// Last modified: 03/27/02 +// Description: Utilities from ANN +//---------------------------------------------------------------------- +// Copyright (C) 2004-2005 David M. Mount and University of Maryland +// All Rights Reserved. +// +// 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 2 of the License, or (at +// your option) any later version. See the file Copyright.txt in the +// main directory. +// +// The University of Maryland and the authors make no representations +// about the suitability or fitness of this software for any purpose. +// It is provided "as is" without express or implied warranty. +//---------------------------------------------------------------------- + +#include "k_means/KM_ANN.h" // KM-ANN includes +#include "k_means/KMrand.h" // random number includes + +//---------------------------------------------------------------------- +// Point methods +//---------------------------------------------------------------------- + +//---------------------------------------------------------------------- +// Distance utility. +// (Note: In the nearest neighbor search, most distances are +// computed using partial distance calculations, not this +// procedure.) +//---------------------------------------------------------------------- + +KMdist kmDist( // interpoint squared distance + int dim, + KMpoint p, + KMpoint q) +{ + register int d; + register KMcoord diff; + register KMcoord dist; + + dist = 0; + for (d = 0; d < dim; d++) { + diff = p[d] - q[d]; + dist = KM_SUM(dist, KM_POW(diff)); + } + return dist; +} + +//---------------------------------------------------------------------- +// kmEqualPts - test two points for equality +//---------------------------------------------------------------------- +bool kmEqualPts( // are two points equal? + int dim, // dimension + KMpoint p1, // the points + KMpoint p2) +{ + for (int d = 0; d < dim; d++) { + if (p1[d] != p2[d]) return false; + } + return true; +} + +//---------------------------------------------------------------------- +// Point allocation/deallocation/copying: +//---------------------------------------------------------------------- +KMpoint kmAllocPt(int dim, KMcoord c) // allocate a point +{ + KMpoint p = new KMcoord[dim]; + for (int i = 0; i < dim; i++) p[i] = c; + return p; +} + +void kmDeallocPt(KMpoint &p) // deallocate one point +{ + delete [] p; + p = NULL; +} + +KMpointArray kmAllocPts(int n, int dim) // allocate n pts in dim +{ + KMpointArray pa = new KMpoint[n]; // allocate points + KMpoint p = new KMcoord[n*dim]; // allocate space for coords + for (int i = 0; i < n; i++) { + pa[i] = &(p[i*dim]); + } + return pa; +} + +void kmDeallocPts(KMpointArray &pa) // deallocate points +{ + delete [] pa[0]; // dealloc coordinate storage + delete [] pa; // dealloc points + pa = NULL; +} + +//---------------------------------------------------------------------- +// Point and other type copying: +//---------------------------------------------------------------------- + +KMpoint kmAllocCopyPt( // allocate and copy point + int dim, + const KMpoint source) +{ + KMpoint p = new KMcoord[dim]; + for (int i = 0; i < dim; i++) p[i] = source[i]; + return p; +} + +void kmCopyPt( // copy point w/o allocation + int dim, + const KMpoint source, + KMpoint dest) +{ + for (int i = 0; i < dim; i++) dest[i] = source[i]; +} + +void kmCopyPts( // copy point array w/o allocation + int n, // number of points + int dim, // dimension + const KMpointArray source, // source point + KMpointArray dest) // destination point +{ + for (int j = 0; j < n; j++) { + for (int i = 0; i < dim; i++) { + dest[j][i] = source[j][i]; + } + } +} + +KMpointArray kmAllocCopyPts( // allocate and copy point array + int n, // number of points + int dim, // dimension + const KMpointArray source) // source point +{ + KMpointArray dest = kmAllocPts(n, dim); + for (int j = 0; j < n; j++) { + for (int i = 0; i < dim; i++) { + dest[j][i] = source[j][i]; + } + } + return dest; +} + +//---------------------------------------------------------------------- +// Methods for orthogonal rectangles: +// kmAssignRect() assigns the coordinates of one rectangle to +// another. The two rectangles must have the same dimension +// (and it is not possible to test this here). +// +// inside() returns true if a point lies inside the (closed) +// rectangle and false otherwise. +// +// expand(d,x,r) expands this rectangle by a factor of x, centrally +// about its origin and stores the resulting rectangle in r. +//---------------------------------------------------------------------- + + // assign one rect to another +void kmAssignRect(int dim, KMorthRect &dest, const KMorthRect &source) +{ + for (int i = 0; i < dim; i++) { + dest.lo[i] = source.lo[i]; + dest.hi[i] = source.hi[i]; + } +} + // is point inside rectangle? +bool KMorthRect::inside(int dim, KMpoint p) +{ + for (int i = 0; i < dim; i++) { + if (p[i] < lo[i] || p[i] > hi[i]) return false; + } + return true; +} + // expand by factor x +void KMorthRect::expand(int dim, double x, KMorthRect r) +{ + for (int i = 0; i < dim; i++) { + KMcoord wid = hi[i] - lo[i]; + r.lo[i] = lo[i] - (wid/2)*(x - 1); + r.hi[i] = hi[i] + (wid/2)*(x - 1); + } +} + // sample uniformly +void KMorthRect::sample(int dim, KMpoint p) +{ + for (int i = 0; i < dim; i++) + p[i] = kmRanUnif(lo[i], hi[i]); +} + diff --git a/src/k_means/KM_ANN.h b/src/k_means/KM_ANN.h new file mode 100644 index 0000000..0b94fee --- /dev/null +++ b/src/k_means/KM_ANN.h @@ -0,0 +1,416 @@ +//---------------------------------------------------------------------- +// File: KM_ANN.h +// Programmer: David Mount +// Last modified: 05/14/04 +// Description: Stripped down ANN utilities +//---------------------------------------------------------------------- +// Copyright (C) 2004-2005 David M. Mount and University of Maryland +// All Rights Reserved. +// +// 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 2 of the License, or (at +// your option) any later version. See the file Copyright.txt in the +// main directory. +// +// The University of Maryland and the authors make no representations +// about the suitability or fitness of this software for any purpose. +// It is provided "as is" without express or implied warranty. +//---------------------------------------------------------------------- +// This file contains basic definitions for points, rectangles and +// distance computations, which have been taken from ANN. These +// are heavily used by the kc-tree, which was adapted from ANN's +// kd-tree routines. +//---------------------------------------------------------------------- + +#ifndef KM_ANN_H +#define KM_ANN_H + +//---------------------------------------------------------------------- +// basic includes +//---------------------------------------------------------------------- +#include // standard libs and definitions +#include // file I/O streams +#include // I/O manipulators (for setw) +#include // for INT_MAX +#include // for DBL_MAX +#include // for system clock +#include // assertion checking +#include // STL strings +#include // numeric limits + +//---------------------------------------------------------------------- +// Old Types: KMcoord, KMdist, KMidx +// KMcoord and KMdist are the types used for representing +// point coordinates and distances. They can be modified by the +// user, with some care. It is assumed that they are both numeric +// types, and that KMdist is generally of an equal or higher type +// from KMcoord. A variable of type KMdist should be large +// enough to store the sum of squared components of a variable +// of type KMcoord for the number of dimensions needed in the +// application. For example, the following combinations are +// legal: +// +// KMcoord KMdist +// --------- ------------------------------- +// short short, int, long, float, double +// int int, long, float, double +// long long, float, double +// float float, double +// double double +// +// It is the user's responsibility to make sure that overflow does +// not occur in distance calculation. +// +// The code assumes that there is an infinite distance, KM_DIST_INF +// (as large as any legal distance). Possible values are given below: +// +// Examples: +// KMdist: double, float, long, int, short +// KM_DIST_INF: DBL_MAX, FLT_MAX, LONG_MAX, INT_MAX, SHRT_MAX +// +// The routine that dumps a tree needs to know roughly how many +// significant digits there are in a KMcoord, so it can output +// points to full precision. This is defined in KMcoordPrec. +// If you have ANSI C++, you should be able to use the following +// values from values.h to help in computing this: +// +// KMcoord KMcoordBits +// -------------------- ------------------------------- +// short, int, long,... BITS(short), BITS(int), ... +// float FSIGNIF +// double DSIGNIF +// +// Then KMcoordPrec = KMcoordBits/(log_2 10) where log_2 10 +// is the base 2 logarithm of 10. +// +// KMidx is a point index. When the data structure is built, +// the points are given as an array. Nearest neighbor results are +// returned as an index into this array. To make it clearer when +// this is happening, we define the integer type KMidx. +// +//---------------------------------------------------------------------- + +typedef double KMcoord; // coordinate data type +typedef double KMdist; // distance data type +typedef int KMidx; // point index + + // largest possible distance +const KMdist KM_DIST_INF = DBL_MAX; + +#ifdef DSIGNIF // number of sig. digits in KMcoord + const int KMcoordPrec = DBL_DIG; +#else + const int KMcoordPrec = 15; // default precision +#endif + +//---------------------------------------------------------------------- +// Norms and metrics: +// KM supports any Minkowski norm for defining distance. In +// particular, for any p >= 1, the L_p Minkowski norm defines the +// length of a d-vector (v0, v1, ..., v(d-1)) to be +// +// (|v0|^p + |v1|^p + ... + |v(d-1)|^p)^(1/p), +// +// (where ^ denotes exponentiation, and |.| denotes absolute +// value). The distance between two points is defined to be +// the norm of the vector joining them. Some common distance +// metrics include +// +// Euclidean metric p = 2 +// Manhattan metric p = 1 +// Max metric p = infinity +// +// In the case of the max metric, the norm is computed by +// taking the maxima of the absolute values of the components. +// KM is highly "coordinate-based" and does not support general +// distances functions (e.g. those obeying just the triangle +// inequality). It also does not support distance functions +// based on inner-products. +// +// For the purpose of computing nearest neighbors, it is not +// necessary to compute the final power (1/p). Thus the only +// component that is used by the program is |v(i)|^p. +// +// KM parameterizes the distance computation through the following +// macros. (Macros are used rather than procedures for efficiency.) +// Recall that the distance between two points is given by the length +// of the vector joining them, and the length or norm of a vector v +// is given by formula: +// +// |v| = ROOT(POW(v0) # POW(v1) # ... # POW(v(d-1))) +// +// where ROOT, POW are unary functions and # is an associative and +// commutative binary operator satisfying: +// +// ** POW: coord --> dist +// ** #: dist x dist --> dist +// ** ROOT: dist (>0) --> double +// +// For early termination in distance calculation (partial distance +// calculation) we assume that POW and # together are monotonically +// increasing on sequences of arguments, meaning that for all +// v0..vk and y: +// +// POW(v0) #...# POW(vk) <= (POW(v0) #...# POW(vk)) # POW(y). +// +// Due to the use of incremental distance calculations in the code +// for searching k-d trees, we assume that there is an incremental +// update function DIFF(x,y) for #, such that if: +// +// s = x0 # ... # xi # ... # xk +// +// then if s' is s with xi replaced by y, that is, +// +// s' = x0 # ... # y # ... # xk +// +// can be computed by: +// +// s' = s # DIFF(xi,y). +// +// Thus, if # is + then DIFF(xi,y) is (yi-x). For the L_infinity +// norm we make use of the fact that in the program this function +// is only invoked when y > xi, and hence DIFF(xi,y)=y. +// +// Finally, for approximate nearest neighbor queries we assume +// that POW and ROOT are related such that +// +// v*ROOT(x) = ROOT(POW(v)*x) +// +// Here are the values for the various Minkowski norms: +// +// L_p: p even: p odd: +// ------------------------- ------------------------ +// POW(v) = v^p POW(v) = |v|^p +// ROOT(x) = x^(1/p) ROOT(x) = x^(1/p) +// # = + # = + +// DIFF(x,y) = y - x DIFF(x,y) = y - x +// +// L_inf: +// POW(v) = |v| +// ROOT(x) = x +// # = max +// DIFF(x,y) = y +// +// By default the Euclidean norm is assumed. To change the norm, +// uncomment the appropriate set of macros below. +// +//---------------------------------------------------------------------- + +//---------------------------------------------------------------------- +// Use the following for the Euclidean norm +//---------------------------------------------------------------------- +#define KM_POW(v) ((v)*(v)) +#define KM_ROOT(x) sqrt(x) +#define KM_SUM(x,y) ((x) + (y)) +#define KM_DIFF(x,y) ((y) - (x)) + +//---------------------------------------------------------------------- +// Array types +// +// KMpoint: +// A point is represented as a (dimensionless) vector of +// coordinates, that is, as a pointer to KMcoord. It is the +// user's responsibility to be sure that each such vector has +// been allocated with enough components. Because only +// pointers are stored, the values should not be altered +// through the lifetime of the nearest neighbor data structure. +// KMpointArray is a dimensionless array of KMpoint. +// KMdistArray is a dimensionless array of KMdist. +// KMidxArray is a dimensionless array of KMidx. This is used for +// storing buckets of points in the search trees, and for returning +// the results of k nearest neighbor queries. +//---------------------------------------------------------------------- + +typedef KMcoord *KMpoint; // a point +typedef KMpoint *KMpointArray; // an array of points +typedef KMdist *KMdistArray; // an array of distances +typedef KMidx *KMidxArray; // an array of point indices + +//---------------------------------------------------------------------- +// Point utilities: +// +// kmDist(dim, p, q) +// Returns the squared distances between p and q. +// +// kmEqualPts(dim, p, q) +// Returns true if p and q are the same points. +// +//---------------------------------------------------------------------- +//---------------------------------------------------------------------- +// Point and Point-array Allocation/Deallocation: +// +// Because points (somewhat like strings in C) are stored as +// pointers. Consequently, creating and destroying copies of +// points may require storage allocation. These procedures do +// this. +// +// p = kmAllocPt(dim, c=0) +// Allocates storage for a single point, and return a pointer +// to it. The second argument is used to initialize all the +// points components. +// +// kmDeallocPt(p) +// Deallocates a point allocated by kmAllocPt(). +// +// pa = kmAllocPts(n, dim) +// Allocates an array of n points in dimension d. It performs +// no initialization. +// +// kmDeallocPts(pa) +// Deallocates points allocated by kmAllocPts(). +//---------------------------------------------------------------------- + +KMdist kmDist( // compute squared distance + int dim, // dimension of space + KMpoint p, // points + KMpoint q); + +bool kmEqualPts( // are two points equal? + int dim, // dimension + KMpoint p1, // the points + KMpoint p2); + +KMpoint kmAllocPt( // allocate point storage + int dim, // dimension + KMcoord c = 0); // coordinate value (all equal) + +void kmDeallocPt( // deallocate a point + KMpoint &p); + +KMpointArray kmAllocPts( // allocate point array + int n, // number of points + int dim); // dimension + +void kmDeallocPts( // deallocate a point array + KMpointArray &pa); // the array + +//---------------------------------------------------------------------- +// Point and other type copying: +// +// kmCopyPt(dim, source, dest) +// Copies point source to point dest, without allocation. +// +// dest = kmAllocCopyPt(dim, source) +// Allocates storage for and copies a point source to dest. +// +// kmCopyPts(n, dim, source, dest) +// Copies point array source to point dest, without allocation. +// +// dest = kmAllocCopyPts(n, dim, source) +// Allocates storage for and copies a point array source to dest. +// +// kmCopy(n, source, dest) +// A generic copy routine for any time for which "=" is defined. +// +// kmAllocCopy(n, source, dest) +// A generic allocate and copy routine for any time for which +// "=" is defined. +//---------------------------------------------------------------------- + +void kmCopyPt( // copy point without allocation + int dim, // dimension + KMpoint source, // source point + KMpoint dest); // destination point + +KMpoint kmAllocCopyPt( // allocate and copy point + int dim, // dimension + KMpoint source); // point to copy + +void kmCopyPts( // copy point array without allocation + int n, // number of points + int dim, // dimension + const KMpointArray source, // source point + KMpointArray dest); // destination point + +KMpointArray kmAllocCopyPts( // allocate and copy point array + int n, // number of points + int dim, // dimension + const KMpointArray source); // source point + +template +void kmCopy( // copy anything without allocation + int n, // number of object + const Object* source, // source array + Object* dest) // destination array +{ + for (int i = 0; i < n; i++) { // copy contents + dest[i] = source[i]; + } +} + +template +Object* kmAllocCopy( // allocate and copy anything + int n, // number of object + const Object* source) // source array +{ + Object* dest = new Object[n]; // allocate array + for (int i = 0; i < n; i++) { // copy contents + dest[i] = source[i]; + } + return dest; +} + +//---------------------------------------------------------------------- +// Global constants and types +//---------------------------------------------------------------------- +enum KMtreeType {KM_KD_TREE, KM_BD_TREE}; // tree types +enum {KM_LO=0, KM_HI=1}; // splitting indices +enum {KM_IN=0, KM_OUT=1}; // shrinking indices + +const int KM_STRING_LEN = 100; // default string length + +//---------------------------------------------------------------------- +// Orthogonal (axis aligned) rectangle +// Orthogonal rectangles are represented by two points, one +// for the lower left corner (min coordinates) and the other +// for the upper right corner (max coordinates). +// +// The constructor initializes from either a pair of coordinates, +// pair of points, or another rectangle. Note that all constructors +// allocate new point storage. The destructor deallocates this +// storage. +// +// BEWARE: Orthogonal rectangles should be passed ONLY BY BASIC_IMAGE. +// (C++'s default copy constructor will not allocate new point +// storage, then on return the destructor free's storage, and then +// you get into big trouble in the calling procedure.) +//---------------------------------------------------------------------- + +class KMorthRect { +public: + KMpoint lo; // rectangle lower bounds + KMpoint hi; // rectangle upper bounds +// + KMorthRect( // basic constructor + int dd, // dimension of space + KMcoord l=0, // default is empty + KMcoord h=0) + { lo = kmAllocPt(dd, l); hi = kmAllocPt(dd, h); } + + KMorthRect( // (almost a) copy constructor + int dd, // dimension + const KMorthRect &r) // rectangle to copy + { lo = kmAllocCopyPt(dd, r.lo); hi = kmAllocCopyPt(dd, r.hi); } + + KMorthRect( // construct from points + int dd, // dimension + KMpoint l, // low point + KMpoint h) // hight point + { lo = kmAllocCopyPt(dd, l); hi = kmAllocCopyPt(dd, h); } + + ~KMorthRect() // destructor + { kmDeallocPt(lo); kmDeallocPt(hi); } + + bool inside(int dim, KMpoint p); // is point p inside rectangle? + // expand by factor x and store in r + void expand(int dim, double x, KMorthRect r); + void sample(int dim, KMpoint p); // sample point p uniformly +}; + +void kmAssignRect( // assign one rect to another + int dim, // dimension (both must be same) + KMorthRect &dest, // destination (modified) + const KMorthRect &source); // source + +#endif diff --git a/src/k_means/KMcenters.cpp b/src/k_means/KMcenters.cpp new file mode 100644 index 0000000..74ab946 --- /dev/null +++ b/src/k_means/KMcenters.cpp @@ -0,0 +1,61 @@ +//---------------------------------------------------------------------- +// File: KMcenters.cc +// Programmer: David Mount +// Last modified: 03/27/02 +// Description: Functions for KMcenters +//---------------------------------------------------------------------- +// Copyright (C) 2004-2005 David M. Mount and University of Maryland +// All Rights Reserved. +// +// 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 2 of the License, or (at +// your option) any later version. See the file Copyright.txt in the +// main directory. +// +// The University of Maryland and the authors make no representations +// about the suitability or fitness of this software for any purpose. +// It is provided "as is" without express or implied warranty. +//---------------------------------------------------------------------- + +#include "k_means/KMcenters.h" + // standard constructor +KMcenters::KMcenters(int k, KMdata& p) + : kCtrs(k), pts(&p) { + ctrs = kmAllocPts(kCtrs, p.getDim()); +} + // copy constructor +KMcenters::KMcenters(const KMcenters& s) + : kCtrs(s.kCtrs), pts(s.pts) { + ctrs = kmAllocCopyPts(kCtrs, s.getDim(), s.ctrs); +} + // assignment operator +KMcenters& KMcenters::operator=(const KMcenters& s) { + if (this != &s) { // avoid self assignment (x=x) + // size change? + if (kCtrs != s.kCtrs || getDim() != s.getDim()) { + kmDeallocPts(ctrs); // reallocate points + ctrs = kmAllocPts(s.kCtrs, s.getDim()); + } + kCtrs = s.kCtrs; + pts = s.pts; + kmCopyPts(kCtrs, s.getDim(), s.ctrs, ctrs); + } + return *this; +} + +KMcenters::~KMcenters() { // destructor + kmDeallocPts(ctrs); +} + +void KMcenters::resize(int k) { // resize array (if needed) + if (k == kCtrs) return; + kCtrs = k; + kmDeallocPts(ctrs); + ctrs = kmAllocPts(kCtrs, pts->getDim()); +} + +void KMcenters::print( // print centers + bool fancy) { + kmPrintPts("Center_Points", ctrs, getK(), fancy); +} diff --git a/src/k_means/KMcenters.h b/src/k_means/KMcenters.h new file mode 100644 index 0000000..b42f315 --- /dev/null +++ b/src/k_means/KMcenters.h @@ -0,0 +1,77 @@ +//---------------------------------------------------------------------- +// File: KMCenters.h +// Programmer: David Mount +// Last modified: 03/27/02 +// Description: Include file for KMcenters +//---------------------------------------------------------------------- +// Copyright (C) 2004-2005 David M. Mount and University of Maryland +// All Rights Reserved. +// +// 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 2 of the License, or (at +// your option) any later version. See the file Copyright.txt in the +// main directory. +// +// The University of Maryland and the authors make no representations +// about the suitability or fitness of this software for any purpose. +// It is provided "as is" without express or implied warranty. +//---------------------------------------------------------------------- + +#ifndef KM_CENTERS_H +#define KM_CENTERS_H + +#include "k_means/KMeans.h" // kmeans includes +#include "k_means/KMdata.h" // provides KMdata + +//---------------------------------------------------------------------- +// KMcenters - set of centers +// This object encodes the information needed for describing a set +// of centers. It also stores a pointer to the data set. +// +// When copying this object, we allocate new storage for the center +// points, but we just copy the pointer to the data set. +//---------------------------------------------------------------------- + +class KMcenters { +protected: + int kCtrs; // number of centers + KMdata* pts; // the data points + KMcenterArray ctrs; // the centers +public: // constructors, etc. + KMcenters(int k, KMdata& p); // standard constructor + KMcenters(const KMcenters& s); // copy constructor + // assignment operator + KMcenters& operator=(const KMcenters& s); + virtual ~KMcenters(); // virtual destructor +public: // accessors + int getDim() const { // get dimension + return pts->getDim(); + } + int getNPts() const { // get number of points + return pts->getNPts(); + } + int getK() const { // get number of centers + return kCtrs; + } + KMdata& getData() { // get the data point structure + return *pts; + } + KMpointArray getDataPts() const { // get the data point array + return pts->getPts(); + } + KMcenterArray getCtrPts() const { // get the center points + return ctrs; + } + KMcenter& operator[](int i) { // index centers + return ctrs[i]; + } + const KMcenter& operator[](int i) const { + return ctrs[i]; + } + void resize(int k); // resize array + + virtual void print( // print centers + bool fancy = true); +}; +#endif diff --git a/src/k_means/KMdata.cpp b/src/k_means/KMdata.cpp new file mode 100644 index 0000000..09869b6 --- /dev/null +++ b/src/k_means/KMdata.cpp @@ -0,0 +1,101 @@ +//---------------------------------------------------------------------- +// File: KMdata.cc +// Programmer: David Mount +// Last modified: 03/27/02 +// Description: Functions for KMdata +//---------------------------------------------------------------------- +// Copyright (C) 2004-2005 David M. Mount and University of Maryland +// All Rights Reserved. +// +// 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 2 of the License, or (at +// your option) any later version. See the file Copyright.txt in the +// main directory. +// +// The University of Maryland and the authors make no representations +// about the suitability or fitness of this software for any purpose. +// It is provided "as is" without express or implied warranty. +//---------------------------------------------------------------------- + +#include "k_means/KMdata.h" +#include "k_means/KMrand.h" // provides kmRanInt() + + // standard constructor +KMdata::KMdata(int d, int n) : dim(d), maxPts(n), nPts(n) { + pts = kmAllocPts(n, d); + kcTree = NULL; +} + +KMdata::~KMdata() { // destructor + kmDeallocPts(pts); // deallocate point array + delete kcTree; // deallocate kc-tree +} + +void KMdata::buildKcTree() { // build kc-tree for points + if (kcTree != NULL) delete kcTree; // destroy existing tree + kcTree = new KCtree(pts, nPts, dim); // construct the tree +} + +void KMdata::resize(int d, int n) { // resize point array + if (d != dim || n != nPts) { // size change? + dim = d; + nPts = n; + kmDeallocPts(pts); // deallocate old points + pts = kmAllocPts(nPts, dim); + } + if (kcTree != NULL) { // kc-tree exists? + delete kcTree; // deallocate kc-tree + kcTree = NULL; + } +} + +//------------------------------------------------------------------------ +// sampleCtr - Sample a center point at random. +// Generates a randomly sampled center point. +//------------------------------------------------------------------------ + +void KMdata::sampleCtr( // sample a center point + KMcenter sample) // where to store sample +{ + int ri = kmRanInt(nPts); // generate random index + kmCopyPt(dim, pts[ri], sample); // copy to destination +} + +//------------------------------------------------------------------------ +// sampleCtrs - Sample center points at random. +// Generates a set of center points by sampling (allowing or +// disallowing duplicates) from this point set. It is assumed that +// the point storage has already been allocated. +//------------------------------------------------------------------------ + +void KMdata::sampleCtrs( // sample points randomly + KMcenterArray sample, // where to store sample + int k, // number of points to sample + bool allowDuplicate) // sample with replacement? +{ + if (!allowDuplicate) // duplicates not allowed + assert(k <= nPts); // can't do more than nPts + + int* sampIdx = new int[k]; // allocate index array + + for (int i = 0; i < k; i++) { // sample each point of sample + int ri = kmRanInt(nPts); // random index in pts + if (!allowDuplicate) { // duplicates not allowed? + bool dupFound; // duplicate found flag + do { // repeat until successful + dupFound = false; + for (int j = 0; j < i; j++) { // search for duplicates + if (sampIdx[j] == ri) { // duplicate found + dupFound = true; + ri = kmRanInt(nPts); // try again + break; + } + } + } while (dupFound); + } + kmCopyPt(dim, pts[ri], sample[i]); // copy sample point + sampIdx[i] = ri; // save index + } + delete [] sampIdx; +} diff --git a/src/k_means/KMdata.h b/src/k_means/KMdata.h new file mode 100644 index 0000000..012fe98 --- /dev/null +++ b/src/k_means/KMdata.h @@ -0,0 +1,107 @@ +//---------------------------------------------------------------------- +// File: KMData.h +// Programmer: David Mount +// Last modified: 03/27/02 +// Description: Include file for KMdata +//---------------------------------------------------------------------- +// Copyright (C) 2004-2005 David M. Mount and University of Maryland +// All Rights Reserved. +// +// 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 2 of the License, or (at +// your option) any later version. See the file Copyright.txt in the +// main directory. +// +// The University of Maryland and the authors make no representations +// about the suitability or fitness of this software for any purpose. +// It is provided "as is" without express or implied warranty. +//---------------------------------------------------------------------- + +#ifndef KM_DATA_H +#define KM_DATA_H + +#include "k_means/KMeans.h" // kmeans includes +#include "k_means/KCtree.h" // kc-tree includes + +//---------------------------------------------------------------------- +// KMdata - data point set +// This object represents a set of data points in d-space. The +// array can be resized. Doing so destroys the existing contents. +// +// In addition to the points, we also (optionally) provide a +// kc-tree data structure for the points as well. This is +// constructed by first initializing the points and then calling +// buildKcTree(). +// +// We support a virtual function samplePt and samplePts, which +// sample one or a set of random center points. In this version, +// the sample is just a random sample of the point set. However, +// it is possible to derive classes from this in which sampling is +// done by some more sophisticated method. +// +// Note that this structure does not support copying or +// assignments. If you want to resuse the structure, the only way +// to do so is to first apply resize(), which destroys the kc-tree +// (if it exists), and then assign to it a new set of points. +//---------------------------------------------------------------------- + +class KMdata { +private: + int dim; // dimension + int maxPts; // max number of points + int nPts; // number of data points + KMdataArray pts; // the data points + KCtree* kcTree; // kc-tree for the points +private: // copy functions (not implemented) + KMdata(const KMdata& p) // copy constructor + { assert(false); } + KMdata& operator=(const KMdata& p) // assignment operator + { assert(false); return *this; } +public: + KMdata(int d, int n); // standard constructor + + int getDim() const { // get dimension + return dim; + } + int getNPts() const { // get number of points + return nPts; + } + KMdataArray getPts() const { // get the points + return pts; + } + KCtree* getKcTree() const { // get kc-tree + return kcTree; + } + KMdataPoint& operator[](int i) { // index + return pts[i]; + } + const KMdataPoint& operator[](int i) const { + return pts[i]; + } + void setNPts(int n) { // set number of points + assert(n <= maxPts); // can't be more than array size + nPts = n; + } + void buildKcTree(); // build the kc-tree for points + + virtual void sampleCtr( // sample a center point + KMpoint sample); // where to store sample + + virtual void sampleCtrs( // sample center points + KMpointArray sample, // where to store sample + int k, // number of points to sample + bool allowDuplicate); // allowing duplicates? + + void resize(int d, int n); // resize array + + void print( // print data points + bool fancy = true) { // nicely formatted? + kmPrintPts("Data_Points", pts, nPts, dim, fancy); + } + + virtual ~KMdata(); // destructor +}; + +typedef KMdata* KMdataPtr; // pointer to KMdata +#endif diff --git a/src/k_means/KMeans.cpp b/src/k_means/KMeans.cpp new file mode 100644 index 0000000..22d628f --- /dev/null +++ b/src/k_means/KMeans.cpp @@ -0,0 +1,114 @@ +//---------------------------------------------------------------------- +// File: KMeans.cc +// Programmer: David Mount +// Last modified: 05/14/04 +// Description: Shared utilities for k-means. +//---------------------------------------------------------------------- +// Copyright (C) 2004-2005 David M. Mount and University of Maryland +// All Rights Reserved. +// +// 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 2 of the License, or (at +// your option) any later version. See the file Copyright.txt in the +// main directory. +// +// The University of Maryland and the authors make no representations +// about the suitability or fitness of this software for any purpose. +// It is provided "as is" without express or implied warranty. +//---------------------------------------------------------------------- + +#include // C++ I/O + +#include "k_means/KMeans.h" // kmeans includes +#include "k_means/KCtree.h" // kc tree +#include "k_means/KMrand.h" // random number generators + +//------------------------------------------------------------------------ +// Global data (shared by all files) +// The following variables are used by all the procedures and are +// initialized in kmInitGlobals(). kmInitTime is the CPU time +// needed to initialize things before the first stage. +//------------------------------------------------------------------------ + +StatLev kmStatLev = SILENT; // global stats output level +ostream* kmOut = &std::cout; // standard output stream +ostream* kmErr = &std::cerr; // output error stream +istream* kmIn = &std::cin; // input stream + +//---------------------------------------------------------------------- +// Output utilities +//---------------------------------------------------------------------- + +void kmPrintPt( // print a point + KMpoint p, // the point + int dim, // the dimension + bool fancy) // print plain or fancy? +{ + if (fancy) *kmOut << "[ "; + for (int i = 0; i < dim; i++) { + *kmOut << setw(8) << p[i]; + if (i < dim-1) *kmOut << " "; + } + if (fancy) *kmOut << " ]"; +} + +void kmPrintPts( // print points + string title, // name of point set + KMpointArray pa, // the point array + int n, // number of points + int dim, // the dimension + bool fancy) // print plain or fancy? +{ + *kmOut << " (" << title << ":\n"; + for (int i = 0; i < n; i++) { + *kmOut << " " << i << "\t"; + kmPrintPt(pa[i], dim, fancy); + *kmOut << "\n"; + } + *kmOut << " )" << endl; +} + +//------------------------------------------------------------------------ +// kmError - print error message +// If KMerr is KMabort we also abort the program. +//------------------------------------------------------------------------ + +void kmError( // error routine + const string &msg, // error message + KMerr level) // abort afterwards +{ + if (level == KMabort) { + *kmErr << "kmlocal: ERROR------->" << msg << "<-------------ERROR" + << endl; + *kmOut << "kmlocal: ERROR------->" << msg << "<-------------ERROR" + << endl; + kmExit(1); + } + else { + *kmErr << "kmlocal: WARNING----->" << msg << "<-------------WARNING" + << endl; + *kmOut << "kmlocal: WARNING----->" << msg << "<-------------WARNING" + << endl; + } +} + +//------------------------------------------------------------------------ +// kmExit - exit from program +// This is used because some Windows implementations create a +// tempoarary window, which is removed immediately on exit. +// This keeps until the user verifies termination. +//------------------------------------------------------------------------ + + +void kmExit(int status) // exit program +{ + #ifdef WAIT_FOR_CONFIRM + char ch; + if (kmIn == &cin) { // input from std in + cerr << "Hit return to continue..." << endl; + kmIn->get(ch); + } + #endif + exit(status); +} diff --git a/src/k_means/KMeans.h b/src/k_means/KMeans.h new file mode 100644 index 0000000..9220b48 --- /dev/null +++ b/src/k_means/KMeans.h @@ -0,0 +1,145 @@ +//---------------------------------------------------------------------- +// File: KMeans.h +// Programmer: David Mount +// Last modified: 08/10/05 +// Description: Include file for kmeans algorithms. +//---------------------------------------------------------------------- +// Copyright (C) 2004-2005 David M. Mount and University of Maryland +// All Rights Reserved. +// +// 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 2 of the License, or (at +// your option) any later version. See the file Copyright.txt in the +// main directory. +// +// The University of Maryland and the authors make no representations +// about the suitability or fitness of this software for any purpose. +// It is provided "as is" without express or implied warranty. +//---------------------------------------------------------------------- +// History: (Changes to source code) +// Version 1.0 04/29/2002 +// Initial release. +// Version: 1.01 10/02/2002 +// Modified output levels. +// Version: 1.1 04/08/2003 +// Added EZ_Hybrid and dampening. Fixed memory leaks. +// Version: 1.2 09/13/2003 +// Added sample programs, kmlsample.cpp and kmlminimal.cpp. +// Version: 1.5 05/14/2004 +// Changed sample program kmlsample to allow random point +// generation. Made minor changes for compilation under Redhat +// Linux and Visual Studio.NET. +// Version: 1.6 03/09/2005 +// Fixed memory leak in KMfilterCenters.cpp. Fixed random +// number error for Microsoft Visual C++. +// Version: 1.7 08/10/2005 +// Added capability for reporting final assignment to clusters. +//---------------------------------------------------------------------- + +#ifndef KMEANS_H +#define KMEANS_H + +#include "k_means/KM_ANN.h" // basic definitions + +using namespace std; // make standard names available + +//---------------------------------------------------------------------- +// Important strings +//---------------------------------------------------------------------- +const string KMshortName = "KMlocal"; +const string KMlongName = "KMlocal (k-means clustering by local search)"; +const string KMversion = "1.7"; +const string KMversionCmt = "(Use at your own risk)"; +const string KMcopyright = "David M. Mount"; +const string KMlatestRev = "August 10, 2005"; + +//------------------------------------------------------------------------ +// Type definitions +// Although data points and centers are of the same type +// as a KMpoint, we distinguish these types here for the +// sake of making the code a little easier to interpret. +// +// KMdataPoint Used for k-means data points. +// KMcenter Used for k-means center points. +// KMpoint Used for any other points and intermediate +// results used in the program. +//------------------------------------------------------------------------ + +typedef KMpoint KMdataPoint; // data point +typedef KMpoint KMcenter; // center point + +typedef KMpointArray KMdataArray; // array of data points +typedef KMpointArray KMcenterArray; // array of center + +typedef KMidx KMdataIdx; // a data point index +typedef KMidx KMctrIdx; // a center point index +typedef KMdataIdx *KMdatIdxArray; // array of data indices +typedef KMctrIdx *KMctrIdxArray; // array of center indices + +//------------------------------------------------------------------------ +// Global constants +//------------------------------------------------------------------------ + +const double KM_ERR = 1E-6; // epsilon (for floating compares) +const double KM_HUGE = DBL_MAX; // huge double value +const int KM_HUGE_INT = INT_MAX; // huge int value + +enum KMerr {KMwarn = 0, KMabort = 1}; // what to do in case of error + +enum StatLev { // output statistics levels + SILENT, // no output + EXEC_TIME, // just execution time + SUMMARY, // summary of entire algorithm + PHASE, // summary of each phase + RUN, // summary of each run + STAGE, // summary of each stage + STEP, // summary of each step + CENTERS, // output centers with each step + TREE, // output tree and points + N_STAT_LEVELS}; // number of levels + +enum KMalg { // k-means algorithm names + LLOYD, // Lloyd's (using filtering) + SWAP, // swap heuristic + HYBRID, // hybrid algorithm + EZ_HYBRID, // EZ-hybrid algorithm + RANDOM, // random centers + N_KM_ALGS}; // number of algorithms + +//---------------------------------------------------------------------- +// Global variables +//---------------------------------------------------------------------- + +extern StatLev kmStatLev; // statistics output level +extern ostream* kmOut; // standard output stream +extern ostream* kmErr; // error output stream +extern istream* kmIn; // input stream + +//---------------------------------------------------------------------- +// Printing utilities +//---------------------------------------------------------------------- + +void kmPrintPt( // print a point + KMpoint p, // the point + int dim, // the dimension + bool fancy = true); // print plain or fancy? + +void kmPrintPts( // print points + string title, // name of point set + KMpointArray pa, // the point array + int n, // number of points + int dim, // the dimension + bool fancy = true); // print plain or fancy? + +//---------------------------------------------------------------------- +// Utility function declarations +//---------------------------------------------------------------------- + +void kmError( // error routine + const string &msg, // error message + KMerr level); // abort afterwards + +void kmExit(int x = 0); // exit the program + +#endif diff --git a/src/k_means/KMfilterCenters.cpp b/src/k_means/KMfilterCenters.cpp new file mode 100644 index 0000000..76b1b3b --- /dev/null +++ b/src/k_means/KMfilterCenters.cpp @@ -0,0 +1,237 @@ +//---------------------------------------------------------------------- +// File: KMfilterCenters.cc +// Programmer: David Mount +// Last modified: 08/10/2005 +// Description: Member functions for KMfilterCenters +//---------------------------------------------------------------------- +// Copyright (C) 2004-2005 David M. Mount and University of Maryland +// All Rights Reserved. +// +// 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 2 of the License, or (at +// your option) any later version. See the file Copyright.txt in the +// main directory. +// +// The University of Maryland and the authors make no representations +// about the suitability or fitness of this software for any purpose. +// It is provided "as is" without express or implied warranty. +//---------------------------------------------------------------------- + +#include "k_means/KMfilterCenters.h" +#include "k_means/KMrand.h" + + // standard constructor +KMfilterCenters::KMfilterCenters(int k, KMdata& p, double df) + : KMcenters(k, p) { + if (p.getKcTree() == NULL) { // kc-tree not yet built? + kmError("Building kc-tree", KMwarn); + p.buildKcTree(); // build it now + } + sums = kmAllocPts(kCtrs, getDim()); + sumSqs = new double[kCtrs]; + weights = new int[kCtrs]; + dists = new double[kCtrs]; + currDist = KM_HUGE; + dampFactor = df; + invalidate(); // distortions are initially invalid +} + // copy constructor +KMfilterCenters::KMfilterCenters(const KMfilterCenters& s) + : KMcenters(s) { + sums = kmAllocCopyPts(kCtrs, getDim(), s.sums); + sumSqs = kmAllocCopy(kCtrs, s.sumSqs); + weights = kmAllocCopy(kCtrs, s.weights); + dists = kmAllocCopy(kCtrs, s.dists); + currDist = s.currDist; + dampFactor = s.dampFactor; + valid = s.valid; +} + // assignment operator +KMfilterCenters& KMfilterCenters::operator=(const KMfilterCenters& s) { + if (this != &s) { // avoid self copy (x=x) + // different sizes? + if (kCtrs != s.kCtrs || getDim() != s.getDim()) { + kmDeallocPts(sums); // deallocate old storage + delete [] sumSqs; + delete [] weights; + delete [] dists; + // allocate new storage + sums = kmAllocPts(s.kCtrs, s.getDim()); + sumSqs = new double[s.kCtrs]; + weights = new int[s.kCtrs]; + dists = new double[s.kCtrs]; + } + KMcenters& base = *this; + base.operator=(s); // copy base class + // copy array contents + kmCopyPts(kCtrs, getDim(), s.sums, sums); + kmCopy(kCtrs, s.sumSqs, sumSqs); + kmCopy(kCtrs, s.weights, weights); + kmCopy(kCtrs, s.dists, dists); + valid = s.valid; + } + currDist = s.currDist; + dampFactor = s.dampFactor; + return *this; +} + // virtual destructor +KMfilterCenters::~KMfilterCenters() { + kmDeallocPts(sums); + delete [] sumSqs; + delete [] weights; + delete [] dists; +} + +//---------------------------------------------------------------------- +// computeDistortion +// This procedure computes the total and individual distortions for +// a set of center points. It invokes getNeighbors() on the +// kc-tree for the point set,which computes the values of weights, +// sums, and sumSqs, from which the distortion is computed as +// follows. +// +// Distortion Computation: +// ----------------------- +// Assume that some center has been fixed (indexed by j in the code +// below). Let SUM_i denote a summation over all (wgt[j]) +// neighbors of the given center. The data points (p[i]) and +// center points (c[j]) are vectors, and the product of two vectors +// means the dot product (u*v = (u.v), u^2 = (u.u)). The +// distortion for a single center j, denoted dists[j], is defined +// to be the sum of squared distances from each point to its +// closest center, That is: +// +// dists[j] = SUM_i (p[i] - c[j])^2 +// = SUM_i (p[i]^2 - 2*c[j]*p[i] + c[j]^2) +// = SUM_i p[i]^2 - 2*c[j]*SUM_i p[i] + wgt[j]*c[j]^2 +// = sumSqs[j] - 2*(c[j].sums[j]) + wgt[j]*(c[j]^2) +// +// Thus the individual distortion can be computed from these +// quantities. The total distortion is the sum of the individual +// distortions. +//---------------------------------------------------------------------- + +void KMfilterCenters::computeDistortion() // compute distortions +{ + // *kmOut << "------------------------------Computing Distortions" << endl; + KCtree* t = getData().getKcTree(); + assert(t != NULL); // tree better exist + t->getNeighbors(*this); // get neighbors + double totDist = 0; + for (int j = 0; j < kCtrs; j++) { + double cDotC = 0; // init: (c[j] . c[j]) + double cDotS = 0; // init: (c[j] . sum[j]) + for (int d = 0; d < getDim(); d++) { // compute dot products + cDotC += ctrs[j][d] * ctrs[j][d]; + cDotS += ctrs[j][d] * sums[j][d]; + } + // final distortion + dists[j] = sumSqs[j] - 2*cDotS + weights[j]*cDotC; + totDist += dists[j]; + } + currDist = totDist; // save total distortion + + validate(); // distortions are now valid +} + +//---------------------------------------------------------------------- +// getAssignments +// This procedure computes the assignment of points to centers. +// It simply passes the request along to the associated kc-tree. +// +// Even though this makes a full traversal of the kc-tree, it does +// not update the sum or sum of squares, etc., but it does not +// modify them either. Thus, we do not change the validation +// status. +//---------------------------------------------------------------------- +// +void KMfilterCenters::getAssignments( // get point assignments + KMctrIdxArray closeCtr, // closest center per point + double* sqDist) // sq'd dist to center +{ + KCtree* t = getData().getKcTree(); + assert(t != NULL); // tree better exist + t->getAssignments(*this, closeCtr, sqDist); // ask KC tree to do it +} + +//---------------------------------------------------------------------- +// moveToCentroid +// This procedure moves each center point to the centroid of its +// associated cluster. We call computeDistortion() if necessary to +// compute the weights and sums. The centroid is the weighted +// average of the sum of neighbors. Thus the +// +// ctrs[j] = sums[j] / weights[j]. +// +// We generally allow a dampening factor on the motion, which is a +// floating quantity between 0 (full dampening) and 1 (no +// dampening). Given the dampening factor df, the above formula +// is: +// ctrs[j] = (1-df) * ctrs[j] + df * sums[j]/ weights[j] +// +//---------------------------------------------------------------------- + +void KMfilterCenters::moveToCentroid() // move center to cluster centroid +{ + if (!valid) computeDistortion(); // compute sums if needed + for (int j = 0; j < kCtrs; j++) { + int wgt = weights[j]; // weight of this center + if (wgt > 0) { // update only if weight > 0 + for (int d = 0; d < getDim(); d++) { + ctrs[j][d] = (1 - dampFactor) * ctrs[j][d] + + dampFactor * sums[j][d]/wgt; + } + } + } + invalidate(); // distortions now invalid +} + +//---------------------------------------------------------------------- +// swapOneCenter +// Swaps one center point with a sample point. Optionally we make +// sure that the new point is not a duplicate of any of the centers +// (including the point being replaced). +//---------------------------------------------------------------------- +void KMfilterCenters::swapOneCenter( // swap one center + bool allowDuplicate) // allow duplicate centers +{ + int rj = kmRanInt(kCtrs); // index of center to replace + int dim = getDim(); + KMpoint p = kmAllocPt(dim); // alloc replacement point + pts->sampleCtr(p); // sample a replacement + if (!allowDuplicate) { // duplicates not allowed? + bool dupFound; // was a duplicate found? + do { // repeat until successful + dupFound = false; + for (int j = 0; j < kCtrs; j++) { // search for duplicates + if (kmEqualPts(dim, p, ctrs[j])) { + dupFound = true; + pts->sampleCtr(p); // try again + break; + } + } + } while (dupFound); + } + kmCopyPt(dim, p, ctrs[rj]); // copy sampled point + if (kmStatLev >= STEP) { // output swap info + *kmOut << "\tswapping: "; + kmPrintPt(p, getDim(), true); + *kmOut << "<-->Center[" << rj << "]\n"; + } + kmDeallocPt(p); // deallocate point storage + invalidate(); // distortions now invalid +} + +//---------------------------------------------------------------------- +// print centers and distortions +//---------------------------------------------------------------------- + +void KMfilterCenters::print(bool fancy) // print centers and distortion +{ + for (int j = 0; j < kCtrs; j++) { + *kmOut << " " << setw(4) << j << "\t"; + kmPrintPt(ctrs[j], getDim(), true); + *kmOut << " dist = " << setw(8) << dists[j] << endl; + } +} diff --git a/src/k_means/KMfilterCenters.h b/src/k_means/KMfilterCenters.h new file mode 100644 index 0000000..855021e --- /dev/null +++ b/src/k_means/KMfilterCenters.h @@ -0,0 +1,185 @@ +//---------------------------------------------------------------------- +// File: KMfilterCenters.h +// Programmer: David Mount +// Last modified: 08/10/2005 +// Description: Include file for KMfilterCenters +//---------------------------------------------------------------------- +// Copyright (C) 2004-2005 David M. Mount and University of Maryland +// All Rights Reserved. +// +// 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 2 of the License, or (at +// your option) any later version. See the file Copyright.txt in the +// main directory. +// +// The University of Maryland and the authors make no representations +// about the suitability or fitness of this software for any purpose. +// It is provided "as is" without express or implied warranty. +//---------------------------------------------------------------------- + +#ifndef KM_FILTER_CENTERS_H +#define KM_FILTER_CENTERS_H + +#include "k_means/KMcenters.h" // provides KMcenters + +//---------------------------------------------------------------------- +// KMfilterCenters +// This extends the KMcenters class, by providing a more efficient +// algorithm for computing distortions, by the filtering algorithm. +// This algorithm makes use of a data structure called a kc-tree, +// which is given in the file KCtree.h. In addition to the +// KMcenter functions we provide the following additional +// functions: +// +// getDist() +// getDists() +// Computes the total and individual distortions, +// respectively, for the centers points (see definitions +// below). +// moveToCentroid() +// Moves the center points to the centroids of their +// associated neighborhoods. +// getAssignments() +// Computes the assignment of points to the closest center. +// +// These functions are not computed independently. In particular, +// for a given set of centers, they can each be computed very +// efficiently (in O(k*d) time) provided that some intermediate +// values has already been computed. We maintain a status variable +// "valid," which indicates whether these intermediate values have +// been computed and are current. The intermediate values are +// computed by computeDistortion(). +// +// >> If you modify this class note that any function that << +// >> modifies the center or data points must set run << +// >> invalidate() or equivalently, set valid=false. << +// +// Immediate access: +// ----------------- +// To disable the automatic recomputation of distortions on +// getDist() and getDists(), call them with a "false" argument. +// +// Distortion Overview: +// -------------------- +// Let C[j] denote the j-th center. For each j in [0..k-1], define +// the j-th neighborhood V(j), to be the set of data points that +// are closer to j than to any other center. The "j-th distortion" +// is defined to be the sum of squared distances of every point in +// V(j) to the j-th center. The "total distortion" is the sum of +// the distortions over all the centers. +// +// Intermediate Values: +// -------------------- +// Instead of computing distortions from scratch by brute force +// (which would take O(n*k*d) time), we use an algorithm called the +// filtering algorithm. This algorithm does not compute the +// distortion directly, but instead computes the following +// intermediate values, from which the distortion can be computed +// efficiently. Let j be an index in [0..k-1]. The notation (u.v) +// denotes the dot product of vectors u and v. +// +// KMpoint sums[j] Vector sum of points in V(j) +// double sumsSqs[j] Sum of (u.u) for all u in V(j) +// double weights[j] Number of data points such that +// this C[j] is closest +// +// See the function computeDistortion() and moveToCentroid() for +// explanations of how these quantities are combined to compute +// the total distortion and move centers to their centroids. +// +// Final Values: +// ------------- +// Given the above intermediate values, we then compute the +// following final distortion values. +// +// double dists[j] Total distortion for points of V(j) +// double currDist Current total distortion +// +// Although they are not used by this program, the center +// distortions are useful, because they may be used in a more +// general clustering algorithm to determine whether clusters +// should be split or merged. +//---------------------------------------------------------------------- + +class KMfilterCenters : public KMcenters{ +protected: // intermediates + KMpointArray sums; // vector sum of points + double* sumSqs; // sum of squares + int* weights; // the weight of each center +protected: // distortion data + double* dists; // individual distortions + double currDist; // current total distortion + bool valid; // are sums/distortions valid? + double dampFactor; // dampening factor [0,1] +protected: // local utilities + void computeDistortion(); // compute distortions + void moveToCentroid(); // move centers to cluster centroids + // swap one center + void swapOneCenter(bool allowDuplicate = true); + void validate() // make valid + { valid = true; } + void invalidate() { // make invalid + if (kmStatLev >= CENTERS) print();// print centers + valid = false; + } +public: + // standard constructor + KMfilterCenters(int k, KMdata& p, double df = 1); + // copy constructor + KMfilterCenters(const KMfilterCenters& s); + // assignment operator + KMfilterCenters& operator=(const KMfilterCenters& s); + + virtual ~KMfilterCenters(); // virtual destructor + +public: // public accessors + // returns sums + KMpointArray getSums(bool autoUpdate = true) { + if (autoUpdate && !valid) computeDistortion(); + return sums; + } + // returns sums of squares + double* getSumSqs(bool autoUpdate = true) { + if (autoUpdate && !valid) computeDistortion(); + return sumSqs; + } + // returns weights + int* getWeights(bool autoUpdate = true) { + if (autoUpdate && !valid) computeDistortion(); + return weights; + } + // returns total distortion + double getDist(bool autoUpdate = true) { + if (autoUpdate && !valid) computeDistortion(); + return currDist; + } + // returns average distortion + double getAvgDist(bool autoUpdate = true) { + if (autoUpdate && !valid) computeDistortion(); + return currDist/double(getNPts()); + } + // returns individual distortions + double* getDists(bool autoUpdate = true) { + if (autoUpdate && !valid) computeDistortion(); + return dists; + } + + void getAssignments( // get point assignments + KMctrIdxArray closeCtr, // closest center per point + double* sqDist); // sq'd dist to center + + void genRandom() { // generate random centers + pts->sampleCtrs(ctrs, kCtrs, false); + invalidate(); + } + void lloyd1Stage() { // one stage of LLoyd's algorithm + moveToCentroid(); + } + void swap1Stage() { // one stage of swap heuristic + swapOneCenter(); + } + virtual void print( // print centers + bool fancy = true); +}; +#endif diff --git a/src/k_means/KMlocal.cpp b/src/k_means/KMlocal.cpp new file mode 100644 index 0000000..60f4eaa --- /dev/null +++ b/src/k_means/KMlocal.cpp @@ -0,0 +1,57 @@ +//---------------------------------------------------------------------- +// File: KMlocal.cc +// Programmer: David Mount +// Last modified: 03/27/02 +// Description: k-means clustering by local search +//---------------------------------------------------------------------- +// Copyright (C) 2004-2005 David M. Mount and University of Maryland +// All Rights Reserved. +// +// 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 2 of the License, or (at +// your option) any later version. See the file Copyright.txt in the +// main directory. +// +// The University of Maryland and the authors make no representations +// about the suitability or fitness of this software for any purpose. +// It is provided "as is" without express or implied warranty. +//---------------------------------------------------------------------- + +#include "k_means/KMlocal.h" // KMlocal includes + +//---------------------------------------------------------------------- +// execute - execute the clustering algorithm +// This function executes the clustering algorithm. See the file +// KMlocal.h for a description of this algorithm. +//---------------------------------------------------------------------- + +KMfilterCenters KMlocal::execute() // execute the algorithm +{ + reset(); // resets everything + while (!isDone()) { // while not done + beginRun(); // start a new run + do { // do while run is not done + beginStage(); // start of stage processing + KMalg method = selectMethod(); // select a method + switch(method) { // apply one stage + case LLOYD: // Lloyd's algorithm + curr.lloyd1Stage(); + break; + case SWAP: // swap heuristic + curr.swap1Stage(); + break; + case RANDOM: // get random centers + curr.genRandom(); + break; + default: // shouldn't come here + assert(false); + break; + } + endStage(); // end of stage processing + } while (!isRunDone()); // while run is not done + endRun(); // end of run processing + tryAcceptance(); // accept if appropriate + } + return best; // return best solution +} diff --git a/src/k_means/KMlocal.h b/src/k_means/KMlocal.h new file mode 100644 index 0000000..fe45e78 --- /dev/null +++ b/src/k_means/KMlocal.h @@ -0,0 +1,846 @@ +//---------------------------------------------------------------------- +// File: KMlocal.h +// Programmer: David Mount +// Last modified: 05/14/04 +// Description: Include file for generic local search kmeans. +//---------------------------------------------------------------------- +// Copyright (C) 2004-2005 David M. Mount and University of Maryland +// All Rights Reserved. +// +// 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 2 of the License, or (at +// your option) any later version. See the file Copyright.txt in the +// main directory. +// +// The University of Maryland and the authors make no representations +// about the suitability or fitness of this software for any purpose. +// It is provided "as is" without express or implied warranty. +//---------------------------------------------------------------------- + +#ifndef KM_LOCAL_H +#define KM_LOCAL_H + +//---------------------------------------------------------------------- +// basic includes +//---------------------------------------------------------------------- +#include // math includes (exp, log) +#include "k_means/KMeans.h" // kmeans includes +#include "k_means/KMdata.h" // data points +#include "k_means/KMfilterCenters.h" // centers +#include "k_means/KMterm.h" // termination conditions +#include "k_means/KMrand.h" // random number generation + +class KMlocal; +typedef KMlocal* KMlocalPtr; // generic algorithm pointer + +//------------------------------------------------------------------------ +// Generic Local Search Overview +// KMlocal provides a generic algorithm for k-means clustering by +// local search. This generic algorithm is controlled by a class, +// KMlocal, whose methods provide the particular elements of each +// algorithm. +// +// Overview: +// --------- +// The generic algorithm begins by generating an initial solution +// "curr" and saving it in "best". These objects are local to the +// KMlocal structure. The value of "curr" reflects the current +// solution and "best" reflects the best solution seen so far. +// +// The algorithm consists of some number of basic iterations, +// called "stages". Each stage involves the execution of one step +// of either the swap heuristic or Lloyd's algorithm. +// +// Stages are grouped into "runs". Intuitively, a run involves a +// (small) number of stages in search of a better solution. A run +// might end, say, because a better solution was found or a fixed +// number of stages have been performed without any improvement. +// +// After a run is finished, we check to see whether we want to +// "accept" the solution. Presumably this happens if the cost is +// lower, but it may happen even if the cost is inferior in other +// circumstances (e.g., as part of a simulated annealing approach). +// Accepting a solution means copying the current solution to the +// saved solution. In some cases, the acceptance may involve +// reseting the current solution to a random solution. +// +// Generic Algorithm: +// ------------------ +// The generic local search algorithm is shown below. The various +// functions are overridden by the specific classes which provide +// the concrete details. +// +// reset() // resets curr and best +// while ( !isDone() ) { // while not done +// beginRun() // begin a new run +// do { // do while run is not done +// beginStage() // end of stage processing +// method = selectMethod() // select a method +// switch( method ) { // apply the method +// LLOYD: curr.Lloyd(); break +// SWAP: curr.Swap(); break +// RANDOM: curr.Random(); break +// } +// endStage() // end of stage processing +// } while ( !isRunDone() ) // while run is not done +// tryAcceptance() // accept if appropriate +// endRun() // end of run processing +// } +// return best // return best solution +// +// Termination Parameters +// ---------------------- +// Each algorithm relies on various parameter settings to determine +// termination conditions for runs and phases. These settings are +// stored in a class KMterm (see KMterm.h). +// +// Parameters (in term) +// -------------------- +// maxTotStage +// Maximum number of stages total. +//------------------------------------------------------------------------ + +class KMlocal { // generic local search +protected: + // fixed quantities + int nPts; // number of points + int kCtrs; // number of centers + int dim; // dimension + KMterm term; // termination conditions + int maxTotStage; // max total stages (from term) + // varying quantities + int stageNo; // current stage number + int runInitStage; // stage at which run started + KMfilterCenters curr; // current solution + KMfilterCenters best; // saved solution +protected: // utility functions + virtual void printStageStats() { // print stage information + if (kmStatLev >= STAGE) { + *kmOut << "\t" << endl; + } + } +public: + // constructor + KMlocal(const KMfilterCenters &sol, const KMterm &t) + : term(t), curr(sol), best(sol) { + nPts = sol.getNPts(); + kCtrs = sol.getK(); + dim = sol.getDim(); + stageNo = 0; + maxTotStage = term.getMaxTotStage(kCtrs, nPts); + } + + virtual ~KMlocal() { } // virtual destructor + virtual KMfilterCenters execute(); // execute the algorithm + + int getTotalStages() const { // return total no. of stages + return stageNo; + } + +protected: // overridden by subclasses + virtual void reset() { // reset everything + stageNo = 0; + runInitStage = 0; + curr.genRandom(); // generate random centers + curr.getDist(); // compute initial distortion + best = curr; + } + virtual bool isDone() const { // are we done? + return stageNo >= maxTotStage; + } + virtual void beginRun() { // begin of run processing + runInitStage = stageNo; + } + virtual void beginStage() { } // start of stage processing + virtual KMalg selectMethod() = 0; // method: LLOYD or SWAP + virtual void endStage() { // end of stage processing + stageNo++; + } + virtual bool isRunDone() { // is run done? + return isDone(); + } + virtual void endRun() { } // end of run processing + virtual void tryAcceptance() { // test acceptance + if (curr.getDist() < best.getDist()) { // is current distortion lower? + best = curr; // then best the current + } + } +}; + +//------------------------------------------------------------------------ +// Concrete Implementations +// The generic KMlocal class is an abstract class. Each derived +// class provides concrete implementation of the various member +// functions, such as selectMethod() and isRunDone(). +// +// +// Relative Distortion Loss (RDL): +// ------------------------------- +// There are some concepts that are important to run/phase +// transitions. One is the maximum number of stages. Most +// algorithms provide some sort of parameter that limits the number +// of stages that the algorithm can spend in a particular run +// (before giving up). The second is the relative distortion loss, +// or RDL. (See also KMterm.h.) The RDL is defined: +// +// initDistortion - currDistortion +// RDL = ------------------------------- +// initDistortion +// +// Note that a positive value indicates that the distortion has +// decreased. The definition of "initDistortion" depends on the +// algorithm. It may be the distortion of the previous stage +// (RDL = consecutive RDL), or it may be the distortion at the +// beginning of the run (RDL = accumulated RDL). +//------------------------------------------------------------------------ + +//------------------------------------------------------------------------ +// KMlocalLloyds - Lloyd's algorithm with random restarts +// The algorithm is broken into phases, and each phase is broken +// into runs. Each phase starts by sampling center points at +// random. Each run is provided two parameters, a maximum number +// of runs per stage (maxRunStage) and a minimum accumulated +// relative distortion loss (minAccumRDL). If the accumulated RDL +// for the run exceeds this value, then the run ends in success. +// If the number of stages is exceeded before this happens, the run +// ends in failure. The phase ends with the first failed run. +// +// This multi-level algorithm is implemented as follows. When a +// run is finished, we test whether the accumlated RDL exceeds the +// minAccumRDL. If not, then the run is unsuccessful and so we +// need to end the phase. +// +// Parameters (in term) +// -------------------- +// maxRunStage +// Maximum number of stages per run. +// minAccumRDL +// Minimum accumlated RDL for stage to be considered +// successful. +// +// State variables +// --------------- +// initRunDist +// The distortion at the start of the run. +// isNewPhase +// True if this is the first stage at the start of a new +// phase. If true, then random centers are generated. +// Note that since random centers have been generated as +// part of reset(), the initial value is false. +// +// Overridden methods +// ------------------ +// reset() +// Do base class resetting. Initialize isNewPhase to false +// and save the initial run distortion. +// selectMethod() +// If new phase starting the select centers at random, +// otherwise do Lloyds algorithm. +// endStage() +// Do base class endStage processing. If there has been +// an improvement, save the current solution. Output stage +// information. +// isRunDone() +// If the number of stages exceeds the maximum runs per +// stages, then we are done. If this is the first stage of +// the phase, then we are not done, and we do beginning of +// phase processing (by resetting the isNewPhase flag and +// save the current distortion). Otherwise, if the +// relative distortion loss (RDL) is greater than +// minAccumRDL then we are done (success). +// endRun() +// If accumulated RDL < minAccumRDL then the run ended +// unsuccessfully (too many stages) and we request the +// start of a new phase. Otherwise the run has ended +// successfully, and we start a new run by saving the +// current run distortion. +//------------------------------------------------------------------------ + +class KMlocalLloyds : public KMlocal { +private: + double initRunDist; // initial run distortion + bool isNewPhase; // starting new phase +protected: + double accumRDL() // relative RDL for run + { return (initRunDist - curr.getDist()) / initRunDist; } + virtual void printStageStats() { // print end of stage info + if (kmStatLev >= STAGE) { + *kmOut << "\t" << endl; + } + } + virtual void printRunStats() { // print end of run info + if (kmStatLev >= STAGE) { + *kmOut << " " << endl; + } + } +public: + // constructor + KMlocalLloyds(const KMfilterCenters &sol, const KMterm &t) + : KMlocal(sol, t) { } +protected: // overridden methods + virtual void reset() { + KMlocal::reset(); // reset base class + isNewPhase = false; // first phase was started + initRunDist = curr.getDist(); // initialize run dist + printStageStats(); + } + virtual KMalg selectMethod() { // method = Lloyd's + return (isNewPhase ? RANDOM : LLOYD); // ...unless start of phase + } + virtual void endStage() { // end of stage processing + KMlocal::endStage(); // base class processing + // get distortions + if (curr.getAvgDist() < best.getAvgDist()) + best = curr; // update if better + printStageStats(); + } + virtual bool isRunDone() { // is run done + if (KMlocal::isRunDone() || // check base conditions + stageNo - runInitStage >= term.getMaxRunStage()) { + return true; // too many stages + } + else if (isNewPhase) { // start of new phase? + isNewPhase = false; // remove flag + initRunDist = curr.getDist(); // initialize run distortion + return false; // run is just starting + } + else { // continue if improvement + return accumRDL() >= term.getMinAccumRDL(); + } + } + virtual void endRun() { // end of run processing + if (accumRDL() < term.getMinAccumRDL()){// unsuccessful run? + isNewPhase = true; // start a new phase + } + else { + initRunDist = curr.getDist(); // next run distortion + } + printRunStats(); + } +}; + +//------------------------------------------------------------------------ +// KMlocalSwap - an implementation of the p-Swap heuristic +// Each run consists of p executions of the swap heuristic. Each +// sequence of swaps is treated as a single stage. +// +// Parameters (in term) +// -------------------- +// (none) +// +// State variables +// --------------- +// maxSwaps +// Maximum number of swaps per run. +// swapNo Number of swaps so far this run. +// +// Overridden methods +// ------------------ +// beginRun() +// Reset count of swaps. +// selectMethod() +// Swap +// endStage() +// (Does nothing, since stage doesn't end until run ends). +// isRunDone() +// If the number of swaps (incremented) exceeds maxSwaps. +// endRun() +// Gets new distortion and increments stage counter. This +// is the real end of a stage. +// tryAcceptance() +// If distortion decreased copy current to best, else +// restore best centers. +//------------------------------------------------------------------------ + +class KMlocalSwap : public KMlocal { +private: + const int maxSwaps; // maximum swaps per run + int swapNo; // no. of swaps this run +public: + // constructor + KMlocalSwap(const KMfilterCenters &sol, const KMterm &t, int p = 1) + : KMlocal(sol, t), maxSwaps(p) { + } +protected: // overridden methods + virtual void reset() { + KMlocal::reset(); // reset base class + printStageStats(); + } + virtual void beginRun() { // start of run processing + KMlocal::beginRun(); // base class processing + swapNo = 0; // init number of swaps + } + virtual KMalg selectMethod() { // method = Swap + return SWAP; + } + virtual void endStage() { } // do nothing + virtual bool isRunDone() { // run is done + return KMlocal::isRunDone() || // base class say's done + ++swapNo >= maxSwaps; // or enough swaps done + } + + virtual void endRun() { // end of run processing + curr.getDist(); + stageNo++; + printStageStats(); // print stage info + } + virtual void tryAcceptance() { // test acceptance + if (curr.getDist() < best.getDist()) { // current distortion lower? + best = curr; // then save the current + } + else { // current distortion worse + curr = best; // restore old centers + } + } +}; + +//------------------------------------------------------------------------ +// KMlocalHybrid - a hybrid version combining Lloyd's and swaps. +// +// Overview +// -------- +// This implements a hybrid algorithm, which combines both of the +// previous methods along with something like simulated annealing. +// Because this uses a fast annealing schedule (T = T*timeFact) it +// should probably be called simulated quenching. +// +// The algorithm's execution is broken into the following different +// groups. +// +// Stage: One invocation of the Swap or Lloyd's algorithm. +// Run: A run consists of a consecutive sequence of swaps +// followed by a consecutive sequence of Lloyd's steps. A +// graphical representation of one run is presented below. +// +// +--+ +---+ +--------> save -----> +// | | | | Y| +// V | V | | N +// ----> Swap ------> Lloyd's ----> Accept? ----> restore --> +// old +// +// Decisions +// --------- +// There are three decisions which this algorithm needs to make. +// +// Continue swapping or move on to Lloyd's? +// This is based on the simulated annealing decision choice, +// based on the consecutive RDL. +// +// Make another pass through Lloyd's or go to acceptance? +// This is based on whether the relative improvement since the +// last stage (consecutive relative distortion loss) is above a +// certain fixed threshold (minConsecRDL). +// +// Accept the current solution: +// If the current solution is better than the saved solution, +// then yes. Otherwise, use the simulated annealing decision +// choice, based on the accumulated RDL. +// +// Simulated Annealing Choice +// -------------------------- +// Following the principal of simulated annealing, we somtimes +// chose to accept a solution, even if it is not an improvement. +// This choice occurs with probability: +// +// exp(RDL/T), +// +// where RDL is the relative distortion loss (relative to the +// saved solution), and T is the current temperature. Note that +// if RDL > 0 (improvement) then this quantity is > 1, and so we +// always accept. (Note that this is not formally correct, since +// in simulated annealing the probability should be based on the +// absolute distortion change not the relative distortion change.) +// +// Annealing Schedule +// ------------------ +// The temperature value T is a decreasing function of the number +// of the number of stages. It starts at some initial value T0 and +// decreases slowly over time. Rather than using the standard (slow) +// Boltzman annealing schedule, we use the following fast annealing +// schedule, every L stages we set +// +// T = TF * T, +// +// where: +// L (= tempRunLength) is an integer parameter set by the +// user. (Presumably it depends on the number of +// centers and the dimension of the space.) +// TF (= tempReducFactor) is a real number of the form 1-x, +// for some small x. +// +// These parameters are provided by the user and are stored in the +// termination condition class. +// +// Initial Temperature +// ------------------- +// The initial temperature T0 is a tricky thing to set. The user +// supplies a parameter p0 = initProbAccept, the initial +// probability of accepting a random swap. However, the +// probability of acceting a swap depends on the given RDL value. +// To estimate this, for the first L runs we use p0 as the +// probability. Over these runs we compute the average rdl value. +// Once the first L runs have completed, we set T0 so that: +// +// exp(-averageRDL/T0) = initProbAccept, +// +// or equivalently +// +// T0 = -averageRDL/(ln initProbAccept). +// +// Parameters (in term) +// -------------------- +// initProbAccept +// Initial probability of accepting an solution that does +// not alter the distortion. +// tempRunLength +// The number of stages before chaning the temperature. +// tempReducFactor +// The factor by which temperature is reduced at the end of +// a temperature run. +// minConsecRDL +// Minimum consecutive RDL needed to keep Lloyd's algorithm +// going. +// +// State variables +// --------------- +// temperature +// Temperature parameter for simulated annealing. +// initTempRunStage +// The stage number at the start of a temperature run. +// areSwapping +// True if we are still in swapping portion of a run, and +// false if we are in the Lloyd's portion of the run. +// prevDist +// In order to compute the consecutive RDL we need to save +// the distortion at the start of each trip through Lloyd's +// algorithm. +// save Simulated annealing may move to a worse solution at +// times. The "best" solution stores the global best. The +// "save" solution is the solution that simulated annealing +// falls back to if a solution is not accepted. +// sumTrials +// Sum of rdl values during the initial trials, where we +// are trying to estimate the mean RDL value. +// trialCt +// A counter which starts at the number of initial trials. +// When it reaches 0, we compute the average RDL value and +// set the initial temperature value. +// +// Utilities particular to Simulated Annealing +// ------------------------------------------- +// simAnnealAccept() +// Random acceptance test for simulated annealing. +// initTempRun() +// Initialize a temperature run process by computing the +// initial temperature value and saving the current +// stage number in initTempRunStage. +// isTempRunDone() +// Check whether the current temperature run is done. +// endTempRun() +// End a temperature run by updating the temperature value +// and saving the current stage number in initTempRunStage. +// +// Overridden methods +// ------------------ +// reset() +// Do base class resetting. Initialize areSwapping to +// true. Save the current solution in save. Initialize +// temperature runs. +// beginStage() +// Save current distortion in prevDist (for computing +// consecutive RDL). +// selectMethod() +// If we are swapping, use Swap, and otherwise use Lloyd's. +// endStage() +// Increment the stage number, get the distortion, and print +// the end-of-stage information. +// isRunDone() +// If we are swapping, then compute the simulated annealing +// random choice. If it rejects, then we have ended the +// swapping process and are transitioning to Lloyd's +// algorithm. In either case, return false. +// +// If we are doing Lloyd's, return true if the consecutive +// RDL is less than minConsecRDL, meaning that Lloyd's +// algorithm has converged. +// endRun() +// If temperature run is done then do processing for the +// end of a temperature run. Set areSwapping to true. +// tryAcceptance() +// At this point we have completed all the swaps and all +// the Lloyd's iterations. If the distortion has improved +// or if the simulated annealing random choice says to, +// save the current solution (and update the overall best +// if needed). Otherwise, restore the previously saved +// solution. +//------------------------------------------------------------------------ + +template // min function +T kmMin(const T& x, const T& y) +{ return (x < y ? x : y); } + +template // max function +T kmMax(const T& x, const T& y) +{ return (x > y ? x : y); } + +class KMlocalHybrid : public KMlocal { +private: + double temperature; // temperature used in SA + int initTempRunStage; // stage when temp run started + bool areSwapping; // are we swapping? (or Lloyd's) + double prevDist; // distortion from prev stage + double sumTrials; // sum of RDL's over trials + int trialCt; // trial count + KMfilterCenters save; // saved solution +protected: // local utilities + double accumRDL() // accumulated RDL + { return (save.getDist() - curr.getDist()) / save.getDist(); } + + double consecRDL() // consecutive RDL + { return (prevDist - curr.getDist()) / prevDist; } + + virtual void printStageStats() { // print end of stage info + if (kmStatLev >= STAGE) { + *kmOut << " " << endl; + } + } + virtual void printRunStats() { // print end of run info + if (kmStatLev >= STAGE) { + *kmOut << " " << endl; + } + } +protected: // SA utilities + int nTrials() // number of trials + { return kmMax(20, term.getTempRunLength()); } + + bool simAnnealAccept(double rdl) { // random accept choice + double prob; + if (--trialCt >= 0) { // still in trial phase? + sumTrials += fabs(rdl); // increment sum of RDLs + if (trialCt == 0) { // last trial? get temp + temperature = -sumTrials/(nTrials()*log(term.getInitProbAccept())); + initTempRunStage = stageNo; // start counting stages + } + prob = term.getInitProbAccept(); // use initial probability + } + else { // use SA probability + prob = kmMin(term.getInitProbAccept(), exp(rdl/temperature)); + } + return prob > kmRanUnif(); + } + + void initTempRuns() { // initialize for temp runs + sumTrials = 0; + trialCt = nTrials(); + initTempRunStage = KM_HUGE_INT; // not counting stages + } + + bool isTempRunDone() // end of temperature run? + { return stageNo - initTempRunStage >= term.getTempRunLength(); } + + void endTempRun() { // process end of temp run + temperature *= term.getTempReducFact(); // reduce temperature + initTempRunStage = stageNo; + } + +public: + // constructor + KMlocalHybrid(const KMfilterCenters &sol, const KMterm &t) + : KMlocal(sol, t), save(sol) { } +protected: // overridden methods + virtual void reset() { + KMlocal::reset(); // reset base class + save = curr; // save initial centers + areSwapping = true; // start with swapping + initTempRuns(); // initialize sim. annealing + printStageStats(); + } + virtual void beginStage() { // start of stage processing + prevDist = curr.getDist(); // save previous distortion + } + virtual KMalg selectMethod() { // select method + return (areSwapping ? SWAP : LLOYD ); + } + virtual void endStage() { // end of stage processing + stageNo++; // increment stage number + curr.getDist(); // get distortion + printStageStats(); + } + virtual bool isRunDone() { // run is done + if (areSwapping) { // swapping? + if (!simAnnealAccept(consecRDL())) { // check SA acceptance + areSwapping = false; // transition to Lloyd's + } + return false; + } + else { // doing Lloyd's algorithm + return consecRDL() <= term.getMinConsecRDL(); // test for convergence + } + } + virtual void endRun() { // end of run processing + if (isTempRunDone()) endTempRun(); // check/process end of temp run + areSwapping = true; // return to swapping + printRunStats(); + } + virtual void tryAcceptance() { // test acceptance + if (accumRDL() > 0) { // improvement over saved? + save = curr; // save this one + if (save.getDist() < best.getDist()) { // new best? + best = save; + } + } + else if (simAnnealAccept(accumRDL())) { // SA says save anyway + save = best; + } + else { // reject, restore old solution + curr = save; + } + } +}; + +//------------------------------------------------------------------------ +// KMlocalEZ_Hybrid - a simpler hybrid combination of Lloyd's and swaps. +// +// Overview +// -------- +// This implements a simpler hybrid algorithm, than the previous +// one. The algorithm performs only one swap, followed by some +// number of iterations of Lloyd's algorithm. Lloyd's algorithm +// is repeated until the consecutive RDL falls below a given +// threshold. +// +// Stage: One invocation of the Swap or Lloyd's algorithm. +// Run: A run consists of a single swap followed by a consecutive +// sequence of Lloyd's steps. A graphical representation +// of one run is presented below. +// +// +---+ +// | | +// V | +// ----> Swap -------> Lloyd's -----> +// +// Decisions +// --------- +// Make another pass through Lloyd's or go to acceptance? +// This is based on whether the relative improvement since the +// last stage (consecutive relative distortion loss) is above a +// certain fixed threshold (minConsecRDL). +// +// Parameters (in term) +// -------------------- +// minConsecRDL +// Minimum consecutive RDL needed to keep Lloyd's algorithm +// going. +// +// State variables +// --------------- +// areSwapping +// True if we are still in swapping portion of a run, and +// false if we are in the Lloyd's portion of the run. +// prevDist +// In order to compute the consecutive RDL we need to save +// the distortion at the start of each trip through Lloyd's +// algorithm. +// +// Overridden methods +// ------------------ +// reset() +// Do base class resetting. Initialize areSwapping to +// true. +// beginStage() +// Save current distortion in prevDist (for computing +// consecutive RDL). +// selectMethod() +// If we are swapping, use Swap, and otherwise use Lloyd's. +// endStage() +// Increment the stage number, get the distortion, and print +// the end-of-stage information. +// isRunDone() +// If we are swapping, transition to Lloyd's and return +// false. If we are doing Lloyd's, return true if the +// consecutive RDL is less than minConsecRDL, meaning that +// Lloyd's algorithm has converged. +// endRun() +// Set areSwaping to true. +// tryAcceptance() +// At this point we have completed the swap and the Lloyd's +// iterations. Update the overall best if appropriate. +//------------------------------------------------------------------------ + +class KMlocalEZ_Hybrid : public KMlocal { +private: + bool areSwapping; // are we swapping? (or Lloyd's) + double prevDist; // distortion from prev stage +protected: // local utilities + double consecRDL() // consecutive RDL + { return (prevDist - curr.getDist()) / prevDist; } + + virtual void printStageStats() { // print end of stage info + if (kmStatLev >= STAGE) { + *kmOut << " " << endl; + } + } + virtual void printRunStats() { // print end of run info + if (kmStatLev >= STAGE) { + *kmOut << " " << endl; + } + } +public: + // constructor + KMlocalEZ_Hybrid(const KMfilterCenters &sol, const KMterm &t) + : KMlocal(sol, t) { } +protected: // overridden methods + virtual void reset() { + KMlocal::reset(); // reset base class + areSwapping = true; // start with swapping + printStageStats(); + } + virtual void beginStage() { // start of stage processing + prevDist = curr.getDist(); // save previous distortion + } + virtual KMalg selectMethod() { // select method + return (areSwapping ? SWAP : LLOYD ); + } + virtual void endStage() { // end of stage processing + stageNo++; // increment stage number + curr.getDist(); // get distortion + printStageStats(); + } + virtual bool isRunDone() { // run is done + if (areSwapping) { // swapping? + areSwapping = false; // transition to Lloyd's + return false; + } + else { // doing Lloyd's algorithm + return consecRDL() <= term.getMinConsecRDL(); // test for convergence + } + } + virtual void endRun() { // end of run processing + areSwapping = true; // return to swapping + printRunStats(); + } + virtual void tryAcceptance() { // test acceptance + if (curr.getDist() < best.getDist()) { // new best? + best = curr; + } + } +}; + +#endif diff --git a/src/k_means/KMrand.cpp b/src/k_means/KMrand.cpp new file mode 100644 index 0000000..0c84ffb --- /dev/null +++ b/src/k_means/KMrand.cpp @@ -0,0 +1,609 @@ +//---------------------------------------------------------------------- +// File: KMrand.cpp +// Programmer: Sunil Arya and David Mount +// Last modified: 05/14/04 +// Description: Routines for random point generation +//---------------------------------------------------------------------- +// Copyright (C) 2004-2005 David M. Mount and University of Maryland +// All Rights Reserved. +// +// 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 2 of the License, or (at +// your option) any later version. See the file Copyright.txt in the +// main directory. +// +// The University of Maryland and the authors make no representations +// about the suitability or fitness of this software for any purpose. +// It is provided "as is" without express or implied warranty. +//---------------------------------------------------------------------- + +#include "k_means/KMrand.h" // random generator declarations + +#ifdef WIN32 // Visual C++ (no srandom/random) +void srandom(unsigned int seed) { srand(seed); } +long random(void) { return long(rand()); } +#endif + +//---------------------------------------------------------------------- +// Globals +//---------------------------------------------------------------------- +int kmIdum = 0; // used for random number generation + +//------------------------------------------------------------------------ +// kmRan0 - (safer) uniform random number generator +// +// The code given here is taken from "Numerical Recipes in C" by +// William Press, Brian Flannery, Saul Teukolsky, and William +// Vetterling. The task of the code is to do an additional randomizing +// shuffle on the system-supplied random number generator to make it +// safer to use. +// +// Returns a uniform deviate between 0.0 and 1.0 using the +// system-supplied routine "random()". Set kmIdum to any negative value +// to initialise or reinitialise the sequence. +//------------------------------------------------------------------------ + +static double kmRan0() +{ + int j; + + static double y, maxran, v[98]; // The exact number 98 is unimportant + static int iff = 0; + + // As a precaution against misuse, we will always initialize on the first + // call, even if "kmIdum" is not set negative. Determine "maxran", the + // next integer after the largest representable value of type int. We + // assume this is a factor of 2 smaller than the corresponding value of + // type unsigned int. + + if (kmIdum < 0 || iff == 0) { // initialize + /* compute maximum random number */ +#ifdef WIN32 // Microsoft Visual C++ + maxran = RAND_MAX; +#else + unsigned i, k; + i = 2; + do { + k = i; + i <<= 1; + } while (i); + maxran = (double) k; +#endif + iff = 1; + + srandom(kmIdum); + kmIdum = 1; + + for (j = 1; j <= 97; j++) // exercise the system routine + random(); // (value intentionally ignored) + + for (j = 1; j <= 97; j++) // Then save 97 values and a 98th + v[j] = random(); + y = random(); + } + + // This is where we start if not initializing. Use the previously saved + // random number y to get an index j between 1 and 97. Then use the + // corresponding v[j] for both the next j and as the output number. */ + + j = 1 + (int) (97.0 * (y / maxran)); + y = v[j]; + v[j] = random(); // Finally, refill the table entry + // with the next random number from + // "random()" + return(y / maxran); +} + +//------------------------------------------------------------------------ +// kmRanInt - generate a random integer from {0,1,...,n-1} +// +// If n == 0, then -1 is returned. +//------------------------------------------------------------------------ + +int kmRanInt( + int n) +{ + int r = (int) (kmRan0()*n); + if (r == n) r--; // (in case kmRan0() == 1 or n == 0) + return r; +} + +//------------------------------------------------------------------------ +// kmRanUnif - generate a random uniform in [lo,hi] +//------------------------------------------------------------------------ + +double kmRanUnif( + double lo, + double hi) +{ + return kmRan0()*(hi-lo) + lo; +} + +//------------------------------------------------------------------------ +// kmRanGauss - Gaussian random number generator +// Returns a normally distributed deviate with zero mean and unit +// variance, using kmRan0() as the source of uniform deviates. +//------------------------------------------------------------------------ + +static double kmRanGauss() +{ + static int iset=0; + static double gset; + + if (iset == 0) { // we don't have a deviate handy + double v1, v2; + double r = 2.0; + while (r >= 1.0) { + //------------------------------------------------------------ + // Pick two uniform numbers in the square extending from -1 to + // +1 in each direction, see if they are in the circle of radius + // 1. If not, try again + //------------------------------------------------------------ + v1 = kmRanUnif(-1, 1); + v2 = kmRanUnif(-1, 1); + r = v1 * v1 + v2 * v2; + } + double fac = sqrt(-2.0 * log(r) / r); + //----------------------------------------------------------------- + // Now make the Box-Muller transformation to get two normal + // deviates. Return one and save the other for next time. + //----------------------------------------------------------------- + gset = v1 * fac; + iset = 1; // set flag + return v2 * fac; + } + else { // we have an extra deviate handy + iset = 0; // so unset the flag + return gset; // and return it + } +} + +//------------------------------------------------------------------------ +// kmRanLaplace - Laplacian random number generator +// Returns a Laplacian distributed deviate with zero mean and +// unit variance, using kmRan0() as the source of uniform deviates. +// +// prob(x) = b/2 * exp(-b * |x|). +// +// b is chosen to be sqrt(2.0) so that the variance of the Laplacian +// distribution [2/(b^2)] becomes 1. +//------------------------------------------------------------------------ + +static double kmRanLaplace() +{ + const double b = 1.4142136; + + double laprand = -log(kmRan0()) / b; + double sign = kmRan0(); + if (sign < 0.5) laprand = -laprand; + return(laprand); +} + +//---------------------------------------------------------------------- +// kmUniformPts - Generate uniformly distributed points +// A uniform distribution over [-1,1]. +//---------------------------------------------------------------------- + +void kmUniformPts( // uniform distribution + KMpointArray pa, // point array (modified) + int n, // number of points + int dim) // dimension +{ + for (int i = 0; i < n; i++) { + for (int d = 0; d < dim; d++) { + pa[i][d] = (KMcoord) (kmRanUnif(-1,1)); + } + } +} + +//---------------------------------------------------------------------- +// kmGaussPts - Generate Gaussian distributed points +// A Gaussian distribution with zero mean and the given standard +// deviation. +//---------------------------------------------------------------------- + +void kmGaussPts( // Gaussian distribution + KMpointArray pa, // point array (modified) + int n, // number of points + int dim, // dimension + double std_dev) // standard deviation +{ + for (int i = 0; i < n; i++) { + for (int d = 0; d < dim; d++) { + pa[i][d] = (KMcoord) (kmRanGauss() * std_dev); + } + } +} + +//---------------------------------------------------------------------- +// kmLaplacePts - Generate Laplacian distributed points +// Generates a Laplacian distribution (zero mean and unit variance). +//---------------------------------------------------------------------- + +void kmLaplacePts( // Laplacian distribution + KMpointArray pa, // point array (modified) + int n, // number of points + int dim) // dimension +{ + for (int i = 0; i < n; i++) { + for (int d = 0; d < dim; d++) { + pa[i][d] = (KMcoord) kmRanLaplace(); + } + } +} + +//---------------------------------------------------------------------- +// kmCoGaussPts - Generate correlated Gaussian distributed points +// Generates a Gauss-Markov distribution of zero mean and unit +// variance. +//---------------------------------------------------------------------- + +void kmCoGaussPts( // correlated-Gaussian distribution + KMpointArray pa, // point array (modified) + int n, // number of points + int dim, // dimension + double correlation) // correlation +{ + double std_dev_w = sqrt(1.0 - correlation * correlation); + for (int i = 0; i < n; i++) { + double previous = kmRanGauss(); + pa[i][0] = (KMcoord) previous; + for (int d = 1; d < dim; d++) { + previous = correlation*previous + std_dev_w*kmRanGauss(); + pa[i][d] = (KMcoord) previous; + } + } +} + +//---------------------------------------------------------------------- +// kmCoLaplacePts - Generate correlated Laplacian distributed points +// Generates a Laplacian-Markov distribution of zero mean and unit +// variance. +//---------------------------------------------------------------------- + +void kmCoLaplacePts( // correlated-Laplacian distribution + KMpointArray pa, // point array (modified) + int n, // number of points + int dim, // dimension + double correlation) // correlation +{ + double wn; + double corr_sq = correlation * correlation; + + for (int i = 0; i < n; i++) { + double previous = kmRanLaplace(); + pa[i][0] = (KMcoord) previous; + for (int d = 1; d < dim; d++) { + double temp = kmRan0(); + if (temp < corr_sq) + wn = 0.0; + else + wn = kmRanLaplace(); + previous = correlation * previous + wn; + pa[i][d] = (KMcoord) previous; + } + } +} + +//---------------------------------------------------------------------- +// kmClusGaussPts - Generate clusters of Gaussian distributed points +// Cluster centers are uniformly distributed over [-1,1], and the +// standard deviation within each cluster is fixed. +// +// Note: Once cluster centers have been set, they are not changed, +// unless new_clust = true. This is so that subsequent calls generate +// points from the same distribution. It follows, of course, that any +// attempt to change the dimension or number of clusters without +// generating new clusters is asking for trouble. +// +// Note: Cluster centers are not generated by a call to uniformPts(). +// Although this could be done, it has been omitted for +// compatibility with kmClusGaussPts() in the colored version, +// rand_c.cc. +// +// As a side effect we compute the cluster separation. This is +// defined to be min_{i != j} dist(cc[i],cc[j])/std, where cc[i] is +// the i-th cluster center and std is the global deviation. It is +// defined to be the square root of the trace of the covariance +// matrix, which is equivalent to the std_dev for each coordinate +// times sqrt(d). +//---------------------------------------------------------------------- +static KMpointArray cgClusters = NULL; // cluster storage + +void kmClusGaussPts( // clustered-Gaussian distribution + KMpointArray pa, // point array (modified) + int n, // number of points + int dim, // dimension + int n_col, // number of colors + bool new_clust, // generate new clusters. + double std_dev, // standard deviation within clusters + double* clus_sep) // cluster separation (returned) +{ + if (cgClusters == NULL || new_clust) {// need new cluster centers + if (cgClusters != NULL) // clusters already exist + kmDeallocPts(cgClusters); // get rid of them + cgClusters = kmAllocPts(n_col, dim); + // generate cluster center coords + for (int i = 0; i < n_col; i++) { + for (int d = 0; d < dim; d++) { + cgClusters[i][d] = (KMcoord) kmRanUnif(-1,1); + } + } + } + + double minDist = double(dim); // minimum inter-center sq'd distance + for (int i = 0; i < n_col; i++) { // compute minimum separation + for (int j = i+1; j < n_col; j++) { + double dist = kmDist(dim, cgClusters[i], cgClusters[j]); + if (dist < minDist) minDist = dist; + } + } + // cluster separation + if (clus_sep != NULL) + *clus_sep = sqrt(minDist)/(sqrt(double(dim))*std_dev); + + for (int i = 0; i < n; i++) { + int c = kmRanInt(n_col); // generate cluster index + for (int d = 0; d < dim; d++) { + pa[i][d] = (KMcoord) (std_dev*kmRanGauss() + cgClusters[c][d]); + } + } +} + +KMpointArray kmGetCGclusters() // get clustered gauss cluster centers +{ + return cgClusters; +} + +//---------------------------------------------------------------------- +// kmClusOrthFlats - points clustered along orthogonal flats +// +// This distribution consists of a collection points clustered +// among a collection of low dimensional flats (hyperplanes) in +// the hypercube [-1,1]^d. A set of n_col orthogonal flats are +// generated, each whose dimension is a random number between 1 +// and max_dim. The points are evenly distributed among the clusters. +// For each cluster, we generate points uniformly distributed along +// the flat within the hypercube. +// +// This is done as follows. Each cluster is defined by a d-element +// control vector whose components are either: +// +// CO_FLAG indicating that this component is to be generated +// uniformly in [-1,1], +// x a value other than CO_FLAG in the range [-1,1], +// which indicating that this coordinate is to be +// generated as x plus a Gaussian random deviation +// with the given standard deviation. +// +// The number of zero components is the dimension of the flat, which +// is a random integer in the range from 1 to max_dim. The points +// are disributed between clusters in nearly equal sized groups. +// +// Note: Once cluster centers have been set, they are not changed, +// unless new_clust = true. This is so that subsequent calls generate +// points from the same distribution. It follows, of course, that any +// attempt to change the dimension or number of clusters without +// generating new clusters is asking for trouble. +// +// To make this a bad scenario at query time, query points should be +// selected from a different distribution, e.g. uniform or Gaussian. +// +// We use a little programming trick to generate groups of roughly +// equal size. If n is the total number of points, and n_col is +// the number of clusters, then the c-th cluster (0 <= c < n_col) +// is given floor((n+c)/n_col) points. It can be shown that this +// will exactly consume all n points. +// +//---------------------------------------------------------------------- + +void kmClusOrthFlats( // clustered along orthogonal flats + KMpointArray pa, // point array (modified) + int n, // number of points + int dim, // dimension + int n_col, // number of colors + bool new_clust, // generate new clusters. + double std_dev, // standard deviation within clusters + int max_dim) // maximum dimension of the flats +{ + const double CO_FLAG = 999; // special flag value + static KMpointArray control = NULL; // control vectors + + if (control == NULL || new_clust) { // need new cluster centers + if (control != NULL) { // clusters already exist + kmDeallocPts(control); // get rid of them + } + control = kmAllocPts(n_col, dim); + + for (int c = 0; c < n_col; c++) { // generate clusters + int n_dim = 1 + kmRanInt(max_dim); // number of dimensions in flat + for (int d = 0; d < dim; d++) { // generate side locations + // prob. of picking next dim + double Prob = ((double) n_dim)/((double) (dim-d)); + if (kmRan0() < Prob) { // add this one to flat + control[c][d] = CO_FLAG; // flag this entry + n_dim--; // one fewer dim to fill + } + else { // don't take this one + control[c][d] = kmRanUnif(-1,1);// random value in [-1,1] + } + } + } + } + + int next = 0; // next slot to fill + for (int c = 0; c < n_col; c++) { // generate clusters + int pick = (n+c)/n_col; // number of points to pick + for (int i = 0; i < pick; i++) { + for (int d = 0; d < dim; d++) { + if (control[c][d] == CO_FLAG) // dimension on flat + pa[next][d] = (KMcoord) kmRanUnif(-1,1); + else // dimension off flat + pa[next][d] = + (KMcoord) (std_dev*kmRanGauss() + control[c][d]); + } + next++; + } + } +} + +//---------------------------------------------------------------------- +// kmClusEllipsoids - points clustered around ellipsoids +// +// This distribution consists of a collection points clustered +// among a collection of low dimensional ellipsoids in the +// hypercube [-1,1]^d. The objective is to model distributions +// in which the points are distributed in lower dimensional +// subspaces, and within this lower dimensional space the points +// are distributed with a Gaussian distribution (with no +// correlation between the dimensions). +// +// The distribution is given the number of clusters or "colors" +// (n_col), maximum number of dimensions (max_dim) of the lower +// dimensional subspace, a "small" standard deviation (std_dev_small), +// and a "large" standard deviation range (std_dev_lo, std_dev_hi). +// +// The algorithm generates n_col cluster centers uniformly from the +// hypercube [-1,1]^d. For each cluster, it selects the dimension +// of the subspace as a random number r between 1 and max_dim. +// These are the dimensions of the ellipsoid. Then it generates +// a d-element std dev vector whose entries are the standard +// deviation for the coordinates of each cluster in the distribution. +// Among the d-element control vector, r randomly chosen values are +// chosen uniformly from the range [std_dev_lo, std_dev_hi]. The +// remaining values are set to std_dev_small. +// +// Note that kmClusGaussPts is a special case of this in which +// max_dim = 0, and std_dev = std_dev_small. +// +// If the flag new_clust is set, then new cluster centers are +// generated. +// +//---------------------------------------------------------------------- + +void kmClusEllipsoids( // clustered around ellipsoids + KMpointArray pa, // point array (modified) + int n, // number of points + int dim, // dimension + int n_col, // number of colors + bool new_clust, // generate new clusters. + double std_dev_small, // small standard deviation + double std_dev_lo, // low standard deviation for ellipses + double std_dev_hi, // high standard deviation for ellipses + int max_dim) // maximum dimension of the flats +{ + static KMpointArray clusters = NULL; // cluster centers + static KMpointArray stdDev = NULL; // standard deviations + + if (clusters == NULL || new_clust) { // need new cluster centers + if (clusters != NULL) // clusters already exist + kmDeallocPts(clusters); // get rid of them + if (stdDev != NULL) // std deviations already exist + kmDeallocPts(stdDev); // get rid of them + + clusters = kmAllocPts(n_col, dim); // alloc new clusters and devs + stdDev = kmAllocPts(n_col, dim); + + for (int i = 0; i < n_col; i++) { // gen cluster center coords + for (int d = 0; d < dim; d++) { + clusters[i][d] = (KMcoord) kmRanUnif(-1,1); + } + } + for (int c = 0; c < n_col; c++) { // generate cluster std dev + int n_dim = 1 + kmRanInt(max_dim); // number of dimensions in flat + for (int d = 0; d < dim; d++) { // generate std dev's + // prob. of picking next dim + double Prob = ((double) n_dim)/((double) (dim-d)); + if (kmRan0() < Prob) { // add this one to ellipse + // generate random std dev + stdDev[c][d] = kmRanUnif(std_dev_lo, std_dev_hi); + n_dim--; // one fewer dim to fill + } + else { // don't take this one + stdDev[c][d] = std_dev_small;// use small std dev + } + } + } + } + + int next = 0; // next slot to fill + for (int c = 0; c < n_col; c++) { // generate clusters + int pick = (n+c)/n_col; // number of points to pick + for (int i = 0; i < pick; i++) { + for (int d = 0; d < dim; d++) { + pa[next][d] = (KMcoord) + (stdDev[c][d]*kmRanGauss() + clusters[c][d]); + } + next++; + } + } +} + +//---------------------------------------------------------------------- +// kmMultiClus - multi-sized clusters +// This distribution is designed to be a challenge for clustering +// algorithm. It consists of a clusters of varying sizes, located +// within the cube [-1,1]^d. The cluster centers are uniformly +// distributed. We generate clusters one by one. For each +// cluster, the size of the cluster m is chosen so that the +// probability of generating a cluster of size 2^i is 1/2^i. +// +// We want each cluster to have a similar total squared distortion +// (variance). Thus a group of size m is generated from a gaussian +// distribution with a standard deviation of B*sqrt(1/m). We call +// B the base standard deviation, which is given as an argument. +// +// The expected number of clusters is (lg n)-2, but there is a very +// high variance here. The total distortion in each dimension then +// is B^2*((lg n)-2) (but don't trust me here, since this is just +// based on back-of- the-envelope computations). Hence the expected +// average distortion, for n points in dim d would be: +// +// d*B^2*((log n)-2)/n +// +// The reason that this is challenging is that each cluster has an +// equal claim to a center (since distortions are similar) but many +// sampling based methods will favor placing clusters in the +// relatively few clusters with a large number of points. +//---------------------------------------------------------------------- + +void kmMultiClus( // multi-sized clusters + KMpointArray pa, // point array (modified) + int n, // number of points + int dim, // dimension + int &k, // number of clusters (returned) + double base_dev) // base standard deviation +{ + int next = 0; // next point in array + int nSamp = 0; // number of points sampled + k = 0; // number of clusters generated + KMpoint clusCenter = kmAllocPt(dim); // allocate center storage + while (nSamp < n) { // until we have sampled enough + int remain = n - nSamp; // number remaining to sample + int clusSize = 2; + // repeatedly double cluster size + // with prob 1/2 + while ((clusSize < remain) && (kmRan0() < 0.5)) + clusSize *= 2; + // don't exceed upper limit + if (clusSize > remain) clusSize = remain; + + // generate center uniformly + for (int d = 0; d < dim; d++) { + clusCenter[d] = (KMcoord) kmRanUnif(-1,1); + } + // desired std dev for cluster + double stdDev = base_dev*sqrt(1.0/clusSize); + // generate cluster points + for (int i = 0; i < clusSize; i++) { + for (int d = 0; d < dim; d++) { + pa[next][d] = (KMcoord) (stdDev*kmRanGauss()+clusCenter[d]); + } + next++; + } + nSamp += clusSize; // update number sampled + k++; // one more cluster + } + kmDeallocPt(clusCenter); +} diff --git a/src/k_means/KMrand.h b/src/k_means/KMrand.h new file mode 100644 index 0000000..d8c3b22 --- /dev/null +++ b/src/k_means/KMrand.h @@ -0,0 +1,113 @@ +//---------------------------------------------------------------------- +// File: KMrand.h +// Programmer: Sunil Arya and David Mount +// Last modified: 03/27/02 +// Description: Old include file for random point generators +//---------------------------------------------------------------------- +// Copyright (C) 2004-2005 David M. Mount and University of Maryland +// All Rights Reserved. +// +// 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 2 of the License, or (at +// your option) any later version. See the file Copyright.txt in the +// main directory. +// +// The University of Maryland and the authors make no representations +// about the suitability or fitness of this software for any purpose. +// It is provided "as is" without express or implied warranty. +//---------------------------------------------------------------------- + +#ifndef KM_RAND_H +#define KM_RAND_H + +//---------------------------------------------------------------------- +// Old includes +//---------------------------------------------------------------------- +#include // standard C++ includes +#include // math routines +#include "k_means/KMeans.h" // KMeans includes + +//---------------------------------------------------------------------- +// Globals +//---------------------------------------------------------------------- +extern int kmIdum; // used for random number generation + +//---------------------------------------------------------------------- +// External entry points +//---------------------------------------------------------------------- + +int kmRanInt( // random integer + int n); // in the range [0,n-1] + +double kmRanUnif( // random uniform in [lo,hi] + double lo = 0.0, + double hi = 1.0); + +void kmUniformPts( // uniform distribution + KMpointArray pa, // point array (modified) + int n, // number of points + int dim); // dimension + +void kmGaussPts( // Gaussian distribution + KMpointArray pa, // point array (modified) + int n, // number of points + int dim, // dimension + double std_dev); // standard deviation + +void kmCoGaussPts( // correlated-Gaussian distribution + KMpointArray pa, // point array (modified) + int n, // number of points + int dim, // dimension + double correlation); // correlation + +void kmLaplacePts( // Laplacian distribution + KMpointArray pa, // point array (modified) + int n, // number of points + int dim); // dimension + +void kmCoLaplacePts( // correlated-Laplacian distribution + KMpointArray pa, // point array (modified) + int n, // number of points + int dim, // dimension + double correlation); // correlation + +void kmClusGaussPts( // clustered-Gaussian distribution + KMpointArray pa, // point array (modified) + int n, // number of points + int dim, // dimension + int n_col, // number of colors (clusters) + bool new_clust = true, // generate new cluster centers + double std_dev = 0.1, // std deviation within clusters + double* clus_sep = NULL); // cluster separation (returned) + +KMpointArray kmGetCGclusters(); // get clustered-gauss cluster centers + +void kmClusOrthFlats( // clustered along orthogonal flats + KMpointArray pa, // point array (modified) + int n, // number of points + int dim, // dimension + int n_col, // number of colors + bool new_clust, // generate new clusters. + double std_dev, // standard deviation within clusters + int max_dim); // maximum dimension of the flats + +void kmClusEllipsoids( // clustered around ellipsoids + KMpointArray pa, // point array (modified) + int n, // number of points + int dim, // dimension + int n_col, // number of colors + bool new_clust, // generate new clusters. + double std_dev_small, // small standard deviation + double std_dev_lo, // low standard deviation for ellipses + double std_dev_hi, // high standard deviation for ellipses + int max_dim); // maximum dimension of the flats + +void kmMultiClus( // multi-sized clusters + KMpointArray pa, // point array (modified) + int n, // number of points + int dim, // dimension + int &k, // number of clusters (returned) + double base_dev); // base standard deviation + +#endif diff --git a/src/k_means/KMterm.cpp b/src/k_means/KMterm.cpp new file mode 100644 index 0000000..cf172a1 --- /dev/null +++ b/src/k_means/KMterm.cpp @@ -0,0 +1,70 @@ +//---------------------------------------------------------------------- +// File: KMterm.cc +// Programmer: David Mount +// Last modified: 03/27/02 +// Description: Functions for KMterm.h +//---------------------------------------------------------------------- +// Copyright (C) 2004-2005 David M. Mount and University of Maryland +// All Rights Reserved. +// +// 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 2 of the License, or (at +// your option) any later version. See the file Copyright.txt in the +// main directory. +// +// The University of Maryland and the authors make no representations +// about the suitability or fitness of this software for any purpose. +// It is provided "as is" without express or implied warranty. +//---------------------------------------------------------------------- + +#include // math includes +#include "k_means/KMterm.h" + +//---------------------------------------------------------------------- +// Default constructor +// These are not reasonable values. Use the standard constructor if +// you want meaningful results. +//---------------------------------------------------------------------- +KMterm::KMterm() { // default constructor + for (int i = 0; i < KM_TERM_VEC_LEN; i++) { + maxTotStageVec[i] = 0; + } + minConsecRDL = 0; + minAccumRDL = 0; + maxRunStage = 0; + initProbAccept = 0; + tempRunLength = 0; + tempReducFact = 0; +} + +//---------------------------------------------------------------------- +// Standard constructor +//---------------------------------------------------------------------- +KMterm::KMterm( // standard constructor + double a, double b, double c, double d, // maxTotStage + double mcr, double mar, int mrs, + double ipa, int trl, double trf) +{ + maxTotStageVec[0] = a; maxTotStageVec[1] = b; + maxTotStageVec[2] = c; maxTotStageVec[3] = d; + minConsecRDL = mcr; + minAccumRDL = mar; + maxRunStage = mrs; + initProbAccept = ipa; + tempRunLength = trl; + tempReducFact = trf; +} + +int KMterm::maxStage(const double param[KM_TERM_VEC_LEN], + int k, int n) const +{ + double count = param[KM_TERM_CONST]; + if (param[KM_TERM_POW] != 0) { + double sum = param[KM_TERM_LIN_K] * k + param[KM_TERM_LIN_N] * n; + count += pow(sum, param[KM_TERM_POW]); + } + assert(count >= 0 && count <= INT_MAX); // should be positive integer + if (count <= 0) count = INT_MAX; // 0 means infinity + return int(count); +} diff --git a/src/k_means/KMterm.h b/src/k_means/KMterm.h new file mode 100644 index 0000000..c84981c --- /dev/null +++ b/src/k_means/KMterm.h @@ -0,0 +1,158 @@ +//---------------------------------------------------------------------- +// File: KMterm.h +// Programmer: David Mount +// Last modified: 03/27/02 +// Description: Include file for kmeans algorithms. +//---------------------------------------------------------------------- +// Copyright (C) 2004-2005 David M. Mount and University of Maryland +// All Rights Reserved. +// +// 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 2 of the License, or (at +// your option) any later version. See the file Copyright.txt in the +// main directory. +// +// The University of Maryland and the authors make no representations +// about the suitability or fitness of this software for any purpose. +// It is provided "as is" without express or implied warranty. +//---------------------------------------------------------------------- + +#ifndef KM_TERM_H +#define KM_TERM_H + +#include "k_means/KMeans.h" + +//------------------------------------------------------------------------ +// KMterm - termination condition +// This structure is used for storing information controlling the +// termination and phase changes of the various algorithms. +// +// Maximum Total Stages: +// --------------------- +// The algorithm is terminated after some maximum number of stages +// have been performed. Rather than computing this as a fixed +// constant, it is given as a function of n (number of data points) +// and k (number of centers). We use the following formula, where +// the coefficients a, ..., d are supplied by the user (see +// kmltest.cpp). +// +// MAX_STAGE = a + (b*k + c*n)^d +// +// Parameters Determining Phase/Run Transitions: +// --------------------------------------------- +// The local improvement algorithms consist of a series of stages, +// which are grouped into "runs" and series of runs are grouped in +// "phases". The meaning of these groupings depends on the +// particular algorithm. (See KMlocal.h for more information.) The +// transition between runs and phases are either based on the +// number of stages performed or on the change in distortion over +// the course of the run. +// +// maxRunStage +// This is used to limit the maximum number of stages in +// any run. +// +// Some transitions are defined in terms of a quantity called the +// "relative distortion loss" (RDL), which is defined to be the +// relative decrease in the distortion. (See KMlocal.h for +// definition.) The relative distortion loss between the current +// and previous stages is called the "consecutive RDL" and the +// relative distortion loss since the start of a run is called the +// "accumulated RDL". +// +// minConsecRDL +// This is used in the hybrid's algorithm. If the RDL of +// two consecutive runs is less than this value, Lloyd's +// algorithm is deemed to have converged. +// minAccumRDL +// This is used in run-based algorithms. It is the RDL of +// the current distortion relative to the distortion at +// some prior time (e.g. the start of a run). +// +// Parameters used in Simulated Annealing +// -------------------------------------- +// initProbAccept +// Initial probability of accepting an solution that does +// not alter the distortion. +// tempRunLength +// The number of stages before chaning the temperature. +// tempReducFactor +// The factor by which temperature is reduced at the end of +// a temperature run. +//------------------------------------------------------------------------ + +enum { // entry names + KM_TERM_CONST, // constant term + KM_TERM_LIN_K, // linear k multiplier + KM_TERM_LIN_N, // linear n multiplier + KM_TERM_POW, // power exponent + KM_TERM_VEC_LEN}; // length of termination param vector + +class KMterm { +private: + double maxTotStageVec[KM_TERM_VEC_LEN]; // max total stages + double minConsecRDL; // min consecutive RDL + double minAccumRDL; // min accumulated RDL + int maxRunStage; // max stages/run for Lloyd's + double initProbAccept; // initial prob. of acceptance + int tempRunLength; // length of temp run + double tempReducFact; // temperature reduction factor + +protected: // stage count + int maxStage(const double param[KM_TERM_VEC_LEN], int k, int n) const; +public: + KMterm(); // default constructor + KMterm( // standard constructor + double a, double b, double c, double d, // maxTotStage + double mcr, double mar, int mrs, + double ipa, int trl, double trf); + + void setMaxTotStage(int i, double val) { // set max stage parameters + assert(i >= 0 && i < KM_TERM_VEC_LEN); + maxTotStageVec[i] = val; + } + void setAbsMaxTotStage(int s) { // set max number of stages + maxTotStageVec[KM_TERM_CONST] = s; + maxTotStageVec[KM_TERM_POW] = 0; + } + int getMaxTotStage(int k, int n) const // max total stages + { return maxStage(maxTotStageVec, k, n); } + + double getMinConsecRDL() const // return min consec RDL + { return minConsecRDL; } + + double getMinAccumRDL() const // return min accum RDL + { return minAccumRDL; } + + int getMaxRunStage() const // return max runs per stage + { return maxRunStage; } + + void setMinConsecRDL(double rdl) // set min consec RDL + { minConsecRDL = rdl; } + + void setMinAccumRDL(double rdl) // set min accum RDL + { minAccumRDL = rdl; } + + void setMaxRunStage(int ms) // set max runs per stage + { maxRunStage = ms; } + + double getInitProbAccept() const // return init. prob. accept + { return initProbAccept; } + + void setInitProbAccept(double ipa) // set init. prob. accept + { initProbAccept = ipa; } + + int getTempRunLength() const // return temperature run len. + { return tempRunLength; } + + void setTempRunLength(int trl) // set temperature run length + { tempRunLength = trl; } + + double getTempReducFact() const // return temp. reduction fact. + { return tempReducFact; } + + void setTempReducFact(double trf) // set temp. reduction fact. + { tempReducFact = trf; } +}; +#endif diff --git a/src/phantom/draw_rois/draw_rois.cpp b/src/phantom/draw_rois/draw_rois.cpp new file mode 120000 index 0000000..4bd77eb --- /dev/null +++ b/src/phantom/draw_rois/draw_rois.cpp @@ -0,0 +1 @@ +/home/tclose/Code/Phantom/phantom/draw_rois/draw_rois.c \ No newline at end of file diff --git a/src/phantom/draw_rois/draw_rois.h b/src/phantom/draw_rois/draw_rois.h new file mode 120000 index 0000000..4646066 --- /dev/null +++ b/src/phantom/draw_rois/draw_rois.h @@ -0,0 +1 @@ +/home/tclose/Code/Phantom/phantom/draw_rois/draw_rois.h \ No newline at end of file diff --git a/src/phantom/interface.cpp b/src/phantom/interface.cpp new file mode 100644 index 0000000..5cdb2d8 --- /dev/null +++ b/src/phantom/interface.cpp @@ -0,0 +1,211 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + +#include + +//#include "bts/cmd.h" + +#include "bts/common.h" + +#include "phantom/interface.h" + +#include "bts/fibre/strand.h" +#include "bts/fibre/track.h" +#include "bts/fibre/track/set.h" + + + + +#include "bts/inline_functions.h" + +//extern "C" { +#include "phantom/shared/strand_collection.h" +//} + + +std::vector >& generate_pre_points(BTS::Fibre::Track::Set& tracks, std::vector >& pre_points) { + + + for (size_t tck_i = 0; tck_i < tracks.size(); ++tck_i) { + + BTS::Fibre::Track tck = tracks[tck_i]; + + if (tck.size() > 1) { + BTS::Triple pre_point = tck[0] - (tck[1] - tck[0]); + pre_points.push_back(pre_point); + } else { + std::cout << "Warning strand " << tck_i << " has been ommitted as it has less than two control points (" << tck.size() << ")" << std::endl; + } + + } + + return pre_points; + +} + + +std::vector >& generate_post_points(BTS::Fibre::Track::Set& tracks, std::vector >& post_points) { + + for (size_t tck_i = 0; tck_i < tracks.size(); ++tck_i) { + + BTS::Fibre::Track tck = tracks[tck_i]; + + if (tck.size() > 1) { + BTS::Triple post_point = tck[tck.size()-1] + (tck[tck.size() - 1] - tck[tck.size() - 2]); + post_points.push_back(post_point); + } else { + std::cout << "Warning strand " << tck_i << " has been ommitted as it has less than two control points (" << tck.size() << ")" << std::endl; + } + + } + + return post_points; +} + + +Strand_collection* convert_mr_to_nfg(Strand_collection* c, BTS::Fibre::Track::Set& tracks, std::vector >& pre_points, std::vector >& post_points) { + + if (tracks.size() == 0) + throw BTS::Exception("Track set supplied to BTSTrix to NFG conversion function does not have any tracks in it."); + + if (!tracks.has_extend_elem_prop(BTS::Fibre::Track::RADIUS_PROP)) + tracks.add_extend_elem_prop(BTS::Fibre::Track::RADIUS_PROP, "0.03"); + + size_t total_num_control_points = 0; + + for (size_t tck_i = 0; tck_i < tracks.size(); ++tck_i) + total_num_control_points += tracks[tck_i].size() - 2; + + + collection_alloc(c, tracks.size(), total_num_control_points, 0); + + size_t control_point_count = 0; + + for (size_t strand_i = 0; strand_i < tracks.size(); strand_i++) { + + BTS::Fibre::Track tck = tracks[strand_i]; + + c->num_strand_control_points[strand_i] = tck.size()-2; //Start and end points are not included. + + c->strand_r[strand_i] = atof(tracks.get_extend_elem_prop(BTS::Fibre::Track::RADIUS_PROP, strand_i).c_str()); + + size_t bundle_i; + if (tracks.has_extend_elem_prop(BTS::Fibre::Track::BUNDLE_INDEX_EPROP)) + bundle_i = atoi(tracks.get_extend_elem_prop(BTS::Fibre::Track::BUNDLE_INDEX_EPROP, strand_i).c_str()); + else + bundle_i = strand_i; + + c->bundle_i_of_strand[strand_i] = bundle_i; + + pre_points[strand_i].copy_to(&(c->pre_points[strand_i * 3])); + post_points[strand_i].copy_to(&(c->post_points[strand_i * 3])); + + tck[0].copy_to(&(c->start_points[strand_i * 3])); + + + size_t point_i; + + for (point_i = 1; point_i < (tck.size() - 1); point_i++) + tck[point_i].copy_to(&(c->control_points[(control_point_count + point_i - 1) * 3])); + + + tck[point_i].copy_to(&(c->end_points[strand_i * 3])); + + + construct_strand(&(c->strands[strand_i]), strand_i, bundle_i, &(c->control_points[control_point_count * 3]), &(c->start_points[strand_i * 3]), &(c->end_points[strand_i * 3]), &(c->pre_points[strand_i * 3]), &(c->post_points[strand_i * 3]), &(c->segments[control_point_count + 3 * strand_i]), c->num_strand_control_points[strand_i], 0.0, c->strand_r[strand_i]); + + + control_point_count += c->num_strand_control_points[strand_i]; + + } + + + + c->num_bundles = construct_bundles(c->bundles, c->bundle_i_of_strand, c->num_strands, c->strands); + + + + return c; +} + + +BTS::Fibre::Track::Set& convert_nfg_to_mr(BTS::Fibre::Track::Set& tracks, std::vector >& pre_points, std::vector >& post_points, Strand_collection* c) { + + + size_t total_num_control_points = 0; + + tracks.clear(); + pre_points.clear(); + post_points.clear(); + + tracks.add_extend_elem_prop(BTS::Fibre::Track::BUNDLE_INDEX_EPROP, "NaN"); + tracks.add_extend_elem_prop(BTS::Fibre::Track::RADIUS_PROP, "NaN"); + + + for (int strand_i = 0; strand_i < c->num_strands; strand_i++) { + + BTS::Fibre::Track tck; + + pre_points.push_back (BTS::Triple((double)c->pre_points[strand_i * 3 + X], (double)c->pre_points[strand_i * 3 + Y], (double)c->pre_points[strand_i * 3 + Z] )); + post_points.push_back (BTS::Triple((double)c->post_points[strand_i * 3 + X], (double)c->post_points[strand_i * 3 + Y], (double)c->post_points[strand_i * 3 + Z] )); + + tck.push_back(BTS::Coord((double)c->start_points[strand_i * 3 + X], (double)c->start_points[strand_i * 3 + Y], (double)c->start_points[strand_i * 3 + Z])); + + for (int point_i = 0; point_i < c->num_strand_control_points[strand_i]; point_i++) { + + tck.push_back(BTS::Coord((double)c->control_points[total_num_control_points * 3 + X], (double)c->control_points[total_num_control_points * 3 + Y], (double)c->control_points[total_num_control_points * 3 + Z])); + + total_num_control_points++; + + } + + + tck.push_back(BTS::Coord((double)c->end_points[strand_i * 3 + X], (double)c->end_points[strand_i * 3 + Y], (double)c->end_points[strand_i * 3 + Z])); + + + std::map properties_row; + properties_row[BTS::Fibre::Track::BUNDLE_INDEX_EPROP] = BTS::str(c->bundle_i_of_strand[strand_i]); + properties_row[BTS::Fibre::Track::RADIUS_PROP] = BTS::str(c->strand_r[strand_i]); + + tracks.push_back(tck, properties_row); + + + } + + + return tracks; + +} + + + + + + + + + + + + + + diff --git a/src/phantom/interface.h b/src/phantom/interface.h new file mode 100644 index 0000000..d6d2dd9 --- /dev/null +++ b/src/phantom/interface.h @@ -0,0 +1,48 @@ +/* + Copyright 2009 Brain Research Institute, Melbourne, Australia + + Created by Tom Close on 13/03/09. + + This file is part of Bayesian Tractlet Sampling (BTS). + + BTS 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. + + BTS 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 BTS. If not, see . + + */ + +#ifndef __phantom_interface_h__ +#define __phantom_interface_h__ + +#include "bts/fibre/strand/set.h" + +//#include "point.h" + +//extern "C" { +#include "phantom/shared/strand_collection.h" +//} + + +std::vector >& generate_pre_points(BTS::Fibre::Track::Set& strands, std::vector >& pre_points); + + +std::vector >& generate_post_points(BTS::Fibre::Track::Set& strands, std::vector >& post_points); + + +BTS::Fibre::Track::Set& convert_nfg_to_mr(BTS::Fibre::Track::Set& strands, std::vector >& pre_points, std::vector >& post_points, Strand_collection* c); + + +Strand_collection* convert_mr_to_nfg(Strand_collection* c, BTS::Fibre::Track::Set& strands, std::vector >& pre_points, std::vector >& post_points); + + + +#endif diff --git a/src/phantom/mri_sim/isotropic_region_register.cpp b/src/phantom/mri_sim/isotropic_region_register.cpp new file mode 120000 index 0000000..3ecc856 --- /dev/null +++ b/src/phantom/mri_sim/isotropic_region_register.cpp @@ -0,0 +1 @@ +/home/tclose/Code/Phantom/phantom/mri_sim/isotropic_region_register.c \ No newline at end of file diff --git a/src/phantom/mri_sim/isotropic_region_register.h b/src/phantom/mri_sim/isotropic_region_register.h new file mode 120000 index 0000000..2a44302 --- /dev/null +++ b/src/phantom/mri_sim/isotropic_region_register.h @@ -0,0 +1 @@ +/home/tclose/Code/Phantom/phantom/mri_sim/isotropic_region_register.h \ No newline at end of file diff --git a/src/phantom/mri_sim/mri_sim.cpp b/src/phantom/mri_sim/mri_sim.cpp new file mode 120000 index 0000000..d103925 --- /dev/null +++ b/src/phantom/mri_sim/mri_sim.cpp @@ -0,0 +1 @@ +/home/tclose/Code/Phantom/phantom/mri_sim/mri_sim.c \ No newline at end of file diff --git a/src/phantom/mri_sim/mri_sim.h b/src/phantom/mri_sim/mri_sim.h new file mode 120000 index 0000000..3548172 --- /dev/null +++ b/src/phantom/mri_sim/mri_sim.h @@ -0,0 +1 @@ +/home/tclose/Code/Phantom/phantom/mri_sim/mri_sim.h \ No newline at end of file diff --git a/src/phantom/mri_sim/overlap_strands.cpp b/src/phantom/mri_sim/overlap_strands.cpp new file mode 120000 index 0000000..d5565c9 --- /dev/null +++ b/src/phantom/mri_sim/overlap_strands.cpp @@ -0,0 +1 @@ +/home/tclose/Code/Phantom/phantom/mri_sim/overlap_strands.c \ No newline at end of file diff --git a/src/phantom/mri_sim/overlap_strands.h b/src/phantom/mri_sim/overlap_strands.h new file mode 120000 index 0000000..3887f3d --- /dev/null +++ b/src/phantom/mri_sim/overlap_strands.h @@ -0,0 +1 @@ +/home/tclose/Code/Phantom/phantom/mri_sim/overlap_strands.h \ No newline at end of file diff --git a/src/phantom/mri_sim/segment_register.cpp b/src/phantom/mri_sim/segment_register.cpp new file mode 120000 index 0000000..cfd79a1 --- /dev/null +++ b/src/phantom/mri_sim/segment_register.cpp @@ -0,0 +1 @@ +/home/tclose/Code/Phantom/phantom/mri_sim/segment_register.c \ No newline at end of file diff --git a/src/phantom/mri_sim/segment_register.h b/src/phantom/mri_sim/segment_register.h new file mode 120000 index 0000000..b9f7d3a --- /dev/null +++ b/src/phantom/mri_sim/segment_register.h @@ -0,0 +1 @@ +/home/tclose/Code/Phantom/phantom/mri_sim/segment_register.h \ No newline at end of file diff --git a/src/phantom/mri_sim/segment_stats.cpp b/src/phantom/mri_sim/segment_stats.cpp new file mode 120000 index 0000000..7b79a5b --- /dev/null +++ b/src/phantom/mri_sim/segment_stats.cpp @@ -0,0 +1 @@ +/home/tclose/Code/Phantom/phantom/mri_sim/segment_stats.c \ No newline at end of file diff --git a/src/phantom/mri_sim/segment_stats.h b/src/phantom/mri_sim/segment_stats.h new file mode 120000 index 0000000..efbad81 --- /dev/null +++ b/src/phantom/mri_sim/segment_stats.h @@ -0,0 +1 @@ +/home/tclose/Code/Phantom/phantom/mri_sim/segment_stats.h \ No newline at end of file diff --git a/src/phantom/mri_sim/sim_voxel_intensities.cpp b/src/phantom/mri_sim/sim_voxel_intensities.cpp new file mode 120000 index 0000000..57fd2e6 --- /dev/null +++ b/src/phantom/mri_sim/sim_voxel_intensities.cpp @@ -0,0 +1 @@ +/home/tclose/Code/Phantom/phantom/mri_sim/sim_voxel_intensities.c \ No newline at end of file diff --git a/src/phantom/mri_sim/sim_voxel_intensities.h b/src/phantom/mri_sim/sim_voxel_intensities.h new file mode 120000 index 0000000..bfdfb9e --- /dev/null +++ b/src/phantom/mri_sim/sim_voxel_intensities.h @@ -0,0 +1 @@ +/home/tclose/Code/Phantom/phantom/mri_sim/sim_voxel_intensities.h \ No newline at end of file diff --git a/src/phantom/mri_sim/strand_collection_stats.cpp b/src/phantom/mri_sim/strand_collection_stats.cpp new file mode 120000 index 0000000..1917d3f --- /dev/null +++ b/src/phantom/mri_sim/strand_collection_stats.cpp @@ -0,0 +1 @@ +/home/tclose/Code/Phantom/phantom/mri_sim/strand_collection_stats.c \ No newline at end of file diff --git a/src/phantom/mri_sim/strand_collection_stats.h b/src/phantom/mri_sim/strand_collection_stats.h new file mode 120000 index 0000000..a22c8aa --- /dev/null +++ b/src/phantom/mri_sim/strand_collection_stats.h @@ -0,0 +1 @@ +/home/tclose/Code/Phantom/phantom/mri_sim/strand_collection_stats.h \ No newline at end of file diff --git a/src/phantom/mri_sim/subvoxel.cpp b/src/phantom/mri_sim/subvoxel.cpp new file mode 120000 index 0000000..85a8ffb --- /dev/null +++ b/src/phantom/mri_sim/subvoxel.cpp @@ -0,0 +1 @@ +/home/tclose/Code/Phantom/phantom/mri_sim/subvoxel.c \ No newline at end of file diff --git a/src/phantom/mri_sim/subvoxel.h b/src/phantom/mri_sim/subvoxel.h new file mode 120000 index 0000000..b8b5d91 --- /dev/null +++ b/src/phantom/mri_sim/subvoxel.h @@ -0,0 +1 @@ +/home/tclose/Code/Phantom/phantom/mri_sim/subvoxel.h \ No newline at end of file diff --git a/src/phantom/mri_sim/voxel.cpp b/src/phantom/mri_sim/voxel.cpp new file mode 120000 index 0000000..1c6e3ef --- /dev/null +++ b/src/phantom/mri_sim/voxel.cpp @@ -0,0 +1 @@ +/home/tclose/Code/Phantom/phantom/mri_sim/voxel.c \ No newline at end of file diff --git a/src/phantom/mri_sim/voxel.h b/src/phantom/mri_sim/voxel.h new file mode 120000 index 0000000..30f4f50 --- /dev/null +++ b/src/phantom/mri_sim/voxel.h @@ -0,0 +1 @@ +/home/tclose/Code/Phantom/phantom/mri_sim/voxel.h \ No newline at end of file diff --git a/src/phantom/noisify/noisify.cpp b/src/phantom/noisify/noisify.cpp new file mode 120000 index 0000000..65d78d5 --- /dev/null +++ b/src/phantom/noisify/noisify.cpp @@ -0,0 +1 @@ +/home/tclose/Code/Phantom/phantom/noisify/noisify.c \ No newline at end of file diff --git a/src/phantom/noisify/noisify.h b/src/phantom/noisify/noisify.h new file mode 120000 index 0000000..dca2ffb --- /dev/null +++ b/src/phantom/noisify/noisify.h @@ -0,0 +1 @@ +/home/tclose/Code/Phantom/phantom/noisify/noisify.h \ No newline at end of file diff --git a/src/phantom/optimise/cost_function.cpp b/src/phantom/optimise/cost_function.cpp new file mode 120000 index 0000000..f3ac1e8 --- /dev/null +++ b/src/phantom/optimise/cost_function.cpp @@ -0,0 +1 @@ +/home/tclose/Code/Phantom/phantom/optimise/cost_function.c \ No newline at end of file diff --git a/src/phantom/optimise/cost_function.h b/src/phantom/optimise/cost_function.h new file mode 120000 index 0000000..11fcb2b --- /dev/null +++ b/src/phantom/optimise/cost_function.h @@ -0,0 +1 @@ +/home/tclose/Code/Phantom/phantom/optimise/cost_function.h \ No newline at end of file diff --git a/src/phantom/optimise/optimise.cpp b/src/phantom/optimise/optimise.cpp new file mode 120000 index 0000000..54d46b0 --- /dev/null +++ b/src/phantom/optimise/optimise.cpp @@ -0,0 +1 @@ +/home/tclose/Code/Phantom/phantom/optimise/optimise.c \ No newline at end of file diff --git a/src/phantom/optimise/optimise.h b/src/phantom/optimise/optimise.h new file mode 120000 index 0000000..304033d --- /dev/null +++ b/src/phantom/optimise/optimise.h @@ -0,0 +1 @@ +/home/tclose/Code/Phantom/phantom/optimise/optimise.h \ No newline at end of file diff --git a/src/phantom/optimise/reference_block.cpp b/src/phantom/optimise/reference_block.cpp new file mode 120000 index 0000000..a63090d --- /dev/null +++ b/src/phantom/optimise/reference_block.cpp @@ -0,0 +1 @@ +/home/tclose/Code/Phantom/phantom/optimise/reference_block.c \ No newline at end of file diff --git a/src/phantom/optimise/reference_block.h b/src/phantom/optimise/reference_block.h new file mode 120000 index 0000000..e58fd90 --- /dev/null +++ b/src/phantom/optimise/reference_block.h @@ -0,0 +1 @@ +/home/tclose/Code/Phantom/phantom/optimise/reference_block.h \ No newline at end of file diff --git a/src/phantom/optimise/sample.cpp b/src/phantom/optimise/sample.cpp new file mode 120000 index 0000000..55f2393 --- /dev/null +++ b/src/phantom/optimise/sample.cpp @@ -0,0 +1 @@ +/home/tclose/Code/Phantom/phantom/optimise/sample.c \ No newline at end of file diff --git a/src/phantom/optimise/sample.h b/src/phantom/optimise/sample.h new file mode 120000 index 0000000..b0221e7 --- /dev/null +++ b/src/phantom/optimise/sample.h @@ -0,0 +1 @@ +/home/tclose/Code/Phantom/phantom/optimise/sample.h \ No newline at end of file diff --git a/src/phantom/optimise/sample_block.cpp b/src/phantom/optimise/sample_block.cpp new file mode 120000 index 0000000..54c859d --- /dev/null +++ b/src/phantom/optimise/sample_block.cpp @@ -0,0 +1 @@ +/home/tclose/Code/Phantom/phantom/optimise/sample_block.c \ No newline at end of file diff --git a/src/phantom/optimise/sample_block.h b/src/phantom/optimise/sample_block.h new file mode 120000 index 0000000..5128b0c --- /dev/null +++ b/src/phantom/optimise/sample_block.h @@ -0,0 +1 @@ +/home/tclose/Code/Phantom/phantom/optimise/sample_block.h \ No newline at end of file diff --git a/src/phantom/rand_init/rand_init.cpp b/src/phantom/rand_init/rand_init.cpp new file mode 120000 index 0000000..8bfaa75 --- /dev/null +++ b/src/phantom/rand_init/rand_init.cpp @@ -0,0 +1 @@ +/home/tclose/Code/Phantom/phantom/rand_init/rand_init.c \ No newline at end of file diff --git a/src/phantom/rand_init/rand_init.h b/src/phantom/rand_init/rand_init.h new file mode 120000 index 0000000..336ad68 --- /dev/null +++ b/src/phantom/rand_init/rand_init.h @@ -0,0 +1 @@ +/home/tclose/Code/Phantom/phantom/rand_init/rand_init.h \ No newline at end of file diff --git a/src/phantom/resample/resample.cpp b/src/phantom/resample/resample.cpp new file mode 120000 index 0000000..847dbb3 --- /dev/null +++ b/src/phantom/resample/resample.cpp @@ -0,0 +1 @@ +/home/tclose/Code/Phantom/phantom/resample/resample.c \ No newline at end of file diff --git a/src/phantom/resample/resample.h b/src/phantom/resample/resample.h new file mode 120000 index 0000000..66a81ca --- /dev/null +++ b/src/phantom/resample/resample.h @@ -0,0 +1 @@ +/home/tclose/Code/Phantom/phantom/resample/resample.h \ No newline at end of file diff --git a/src/phantom/shared/bundle.cpp b/src/phantom/shared/bundle.cpp new file mode 120000 index 0000000..0826ca9 --- /dev/null +++ b/src/phantom/shared/bundle.cpp @@ -0,0 +1 @@ +/home/tclose/Code/Phantom/phantom/shared/bundle.c \ No newline at end of file diff --git a/src/phantom/shared/bundle.h b/src/phantom/shared/bundle.h new file mode 120000 index 0000000..31886fc --- /dev/null +++ b/src/phantom/shared/bundle.h @@ -0,0 +1 @@ +/home/tclose/Code/Phantom/phantom/shared/bundle.h \ No newline at end of file diff --git a/src/phantom/shared/control_point.cpp b/src/phantom/shared/control_point.cpp new file mode 120000 index 0000000..a61a915 --- /dev/null +++ b/src/phantom/shared/control_point.cpp @@ -0,0 +1 @@ +/home/tclose/Code/Phantom/phantom/shared/control_point.c \ No newline at end of file diff --git a/src/phantom/shared/control_point.h b/src/phantom/shared/control_point.h new file mode 120000 index 0000000..d064f33 --- /dev/null +++ b/src/phantom/shared/control_point.h @@ -0,0 +1 @@ +/home/tclose/Code/Phantom/phantom/shared/control_point.h \ No newline at end of file diff --git a/src/phantom/shared/isotropic_region.cpp b/src/phantom/shared/isotropic_region.cpp new file mode 120000 index 0000000..cd743fc --- /dev/null +++ b/src/phantom/shared/isotropic_region.cpp @@ -0,0 +1 @@ +/home/tclose/Code/Phantom/phantom/shared/isotropic_region.c \ No newline at end of file diff --git a/src/phantom/shared/isotropic_region.h b/src/phantom/shared/isotropic_region.h new file mode 120000 index 0000000..a6d7f7b --- /dev/null +++ b/src/phantom/shared/isotropic_region.h @@ -0,0 +1 @@ +/home/tclose/Code/Phantom/phantom/shared/isotropic_region.h \ No newline at end of file diff --git a/src/phantom/shared/segment.cpp b/src/phantom/shared/segment.cpp new file mode 120000 index 0000000..84adaf5 --- /dev/null +++ b/src/phantom/shared/segment.cpp @@ -0,0 +1 @@ +/home/tclose/Code/Phantom/phantom/shared/segment.c \ No newline at end of file diff --git a/src/phantom/shared/segment.h b/src/phantom/shared/segment.h new file mode 120000 index 0000000..0838dcd --- /dev/null +++ b/src/phantom/shared/segment.h @@ -0,0 +1 @@ +/home/tclose/Code/Phantom/phantom/shared/segment.h \ No newline at end of file diff --git a/src/phantom/shared/shared.cpp b/src/phantom/shared/shared.cpp new file mode 120000 index 0000000..6cbdd85 --- /dev/null +++ b/src/phantom/shared/shared.cpp @@ -0,0 +1 @@ +/home/tclose/Code/Phantom/phantom/shared/shared.c \ No newline at end of file diff --git a/src/phantom/shared/shared.h b/src/phantom/shared/shared.h new file mode 120000 index 0000000..1072a65 --- /dev/null +++ b/src/phantom/shared/shared.h @@ -0,0 +1 @@ +/home/tclose/Code/Phantom/phantom/shared/shared.h \ No newline at end of file diff --git a/src/phantom/shared/strand.cpp b/src/phantom/shared/strand.cpp new file mode 120000 index 0000000..e1bf015 --- /dev/null +++ b/src/phantom/shared/strand.cpp @@ -0,0 +1 @@ +/home/tclose/Code/Phantom/phantom/shared/strand.c \ No newline at end of file diff --git a/src/phantom/shared/strand.h b/src/phantom/shared/strand.h new file mode 120000 index 0000000..a0d45df --- /dev/null +++ b/src/phantom/shared/strand.h @@ -0,0 +1 @@ +/home/tclose/Code/Phantom/phantom/shared/strand.h \ No newline at end of file diff --git a/src/phantom/shared/strand_collection.cpp b/src/phantom/shared/strand_collection.cpp new file mode 120000 index 0000000..ff4376a --- /dev/null +++ b/src/phantom/shared/strand_collection.cpp @@ -0,0 +1 @@ +/home/tclose/Code/Phantom/phantom/shared/strand_collection.c \ No newline at end of file diff --git a/src/phantom/shared/strand_collection.h b/src/phantom/shared/strand_collection.h new file mode 120000 index 0000000..56b81c3 --- /dev/null +++ b/src/phantom/shared/strand_collection.h @@ -0,0 +1 @@ +/home/tclose/Code/Phantom/phantom/shared/strand_collection.h \ No newline at end of file diff --git a/src/phantom/subdiv/subdiv.cpp b/src/phantom/subdiv/subdiv.cpp new file mode 120000 index 0000000..5063a16 --- /dev/null +++ b/src/phantom/subdiv/subdiv.cpp @@ -0,0 +1 @@ +/home/tclose/Code/Phantom/phantom/subdiv/subdiv.c \ No newline at end of file diff --git a/src/phantom/subdiv/subdiv.h b/src/phantom/subdiv/subdiv.h new file mode 120000 index 0000000..8680157 --- /dev/null +++ b/src/phantom/subdiv/subdiv.h @@ -0,0 +1 @@ +/home/tclose/Code/Phantom/phantom/subdiv/subdiv.h \ No newline at end of file diff --git a/src/phantom/trim/strand_section.cpp b/src/phantom/trim/strand_section.cpp new file mode 120000 index 0000000..8e29815 --- /dev/null +++ b/src/phantom/trim/strand_section.cpp @@ -0,0 +1 @@ +/home/tclose/Code/Phantom/phantom/trim/strand_section.c \ No newline at end of file diff --git a/src/phantom/trim/strand_section.h b/src/phantom/trim/strand_section.h new file mode 120000 index 0000000..1442684 --- /dev/null +++ b/src/phantom/trim/strand_section.h @@ -0,0 +1 @@ +/home/tclose/Code/Phantom/phantom/trim/strand_section.h \ No newline at end of file diff --git a/src/phantom/trim/trim.cpp b/src/phantom/trim/trim.cpp new file mode 120000 index 0000000..9cbcaea --- /dev/null +++ b/src/phantom/trim/trim.cpp @@ -0,0 +1 @@ +/home/tclose/Code/Phantom/phantom/trim/trim.c \ No newline at end of file diff --git a/src/phantom/trim/trim.h b/src/phantom/trim/trim.h new file mode 120000 index 0000000..1f3afc4 --- /dev/null +++ b/src/phantom/trim/trim.h @@ -0,0 +1 @@ +/home/tclose/Code/Phantom/phantom/trim/trim.h \ No newline at end of file diff --git a/sysconf/__init__.py b/sysconf/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/sysconf/common.py b/sysconf/common.py new file mode 100644 index 0000000..353b587 --- /dev/null +++ b/sysconf/common.py @@ -0,0 +1,24 @@ +import os + +bin_dir = 'bin' +cmd_dir = 'cmd' +lib_dir = 'lib' +misc_dir = 'src' +doc_dir = 'doc' +dev_dir = 'dev' +gl = os.path.join ('src', 'opengl', 'gl.h') + +cpp_suffix = '.cpp' +h_suffix = '.h' + +libname = 'mrtrix' + +icon = 'icons/icon.o' +icon_dep = 'icons/icon.rc' + +# Qt4 settings: +moc = 'moc' +qt4_modules = [ 'Core', 'Gui', 'OpenGL' ] +qt4_lib_flags = [ '-lGLEW' ] +qt4_cflags = [ '-DQT_SHARED' ] + [ '-DQT_' + entry.upper() + '_LIB' for entry in qt4_modules ] + diff --git a/sysconf/darwin.py b/sysconf/darwin.py new file mode 100644 index 0000000..fce613b --- /dev/null +++ b/sysconf/darwin.py @@ -0,0 +1,42 @@ +from sysconf.common import * + +obj_suffix = '.o' +exe_suffix = '' +lib_prefix = 'lib' +lib_suffix = '.dylib' + +cpp = [ 'g++', '-c', '$flags$', '$path$', '$src$', '-o', '$obj$' ] +cpp_flags = [ '-Wall', '-DMACOSX', '-fPIC', '-I/data/home/tclose/Code/Tractography/mrtrix_bundle/include', '-mtune=G5' ] +cflags_thread = [] + +ld = [ 'g++', '$flags$', '$path$', '$obj$', '$mrtrix$', '-o', '$bin$' ] +ld_flags = [ '-lm', '-L/data/home/tclose/Code/Tractography/mrtrix_bundle/lib', '-latlas_mrtrix', '/usr/local/lib/libgslcblas.a', '/usr/local/lib/libgsl.a' ] +ld_flags_lib_prefix = '-l' +libs_thread = [ '-lpthread' ] + +ld_lib = [ 'g++', '-dynamiclib', '$flags$', '$obj$', '-o', '$lib$' ] +ld_lib_flags = ['-L/data/home/tclose/Code/Tractography/mrtrix_bundle/lib', '-latlas_mrtrix' ] + +cpp_flags_debug = cpp_flags + [ '-O0', '-g', '-D_GLIBCXX_DEBUG' ] +ld_flags_debug = ld_flags + [ '-g' ] +ld_lib_flags_debug = ld_lib_flags + [ '-g' ] + +cpp_flags += [ '-DNDEBUG', '-DOPTIMISED', '-DCALCULATE_GRADIENT' ] + +cpp_flags_profile = cpp_flags + [ '-g', '-pg' ] +ld_flags_profile = ld_flags + [ '-g', '-pg' ] +ld_lib_flags_profile = ld_lib_flags + [ '-g', '-pg' ] + +cpp_flags += [ '-O3' ] + +ld_flags_gl = [] + +pkgconfig = [ 'pkg-config' ] +pkgconfig_env = None + +# Qt4 settings: +qt4_path = '/Library/Frameworks' +qt4_include_path = [ qt4_path + '/Qt' + entry + '.framework/Headers' for entry in qt4_modules ] +qt4_lib_flags += [ '-L/Library/Frameworks', '-L/System/Library/Frameworks', '-framework', 'Carbon', '-framework', 'AppKit', '-framework', 'ApplicationServices', '-framework', 'OpenGL', '-lz', '-lGLEW' ] +for entry in qt4_modules: + qt4_lib_flags += [ '-framework', 'Qt'+entry ] diff --git a/sysconf/linux.py b/sysconf/linux.py new file mode 100644 index 0000000..2d2b25b --- /dev/null +++ b/sysconf/linux.py @@ -0,0 +1,42 @@ +from sysconf.common import * + +obj_suffix = '.o' +exe_suffix = '' +lib_prefix = 'lib' +lib_suffix = '.so' + + +cpp = [ 'g++', '-c', '$flags$', '$path$', '$src$', '-o', '$obj$' ] +cpp_flags = [ '-Wall', '-march=x86-64', '-fPIC', '-Wno-deprecated'] +cflags_thread = [] + +ld = [ 'g++', '$flags$', '$path$', '$obj$', '$mrtrix$', '-o', '$bin$' ] +ld_flags = [ '-lm', '-L/usr/lib/sse2', '-lcblas', '-latlas', '-llapack_atlas', '-lgfortran', '-L/usr/local/lib/' '-lgslcblas', '-lgsl' ] +ld_flags_lib_prefix = '-l' +libs_thread = [ '-lpthread' ] + +ld_lib = [ 'g++', '-shared', '$flags$', '$obj$', '-o', '$lib$' ] +ld_lib_flags = [] + +cpp_flags_debug = cpp_flags + [ '-O0', '-g3', '-D_GLIBCXX_DEBUG' ] +ld_flags_debug = ld_flags + [ '-g3' ] +ld_lib_flags_debug = ld_lib_flags + [ '-g3' ] + +cpp_flags += [ '-DNDEBUG', '-DOPTIMISED'] + +cpp_flags_profile = cpp_flags + [ '-g', '-pg' ] +ld_flags_profile = ld_flags + [ '-g', '-pg' ] +ld_lib_flags_profile = ld_lib_flags + [ '-g', '-pg' ] + +cpp_flags += [ '-O3' ] + +ld_flags_gl = [] + +pkgconfig = [ 'pkg-config' ] +pkgconfig_env = None + +# Qt4 settings: +qt4_path = '/usr/include/qt4' +qt4_include_path = [ qt4_path ] + [ qt4_path + '/Qt' + entry for entry in qt4_modules ] +qt4_lib_flags += [ '-lQt' + entry for entry in qt4_modules ] + diff --git a/sysconf/windows.py b/sysconf/windows.py new file mode 100644 index 0000000..1208355 --- /dev/null +++ b/sysconf/windows.py @@ -0,0 +1,38 @@ +from sysconf.common import * + +obj_suffix = '.o' +exe_suffix = '.exe' +lib_prefix = '' +lib_suffix = '.dll' + +cpp = [ 'g++', '-c', '$flags$', '$gtk$', '$path$', '$src$', '-o', '$obj$' ] +cpp_flags = [ '-Wall', '-march=i686', '-fno-strict-aliasing', '-DGL_GLEXT_PROTOTYPES', '-mno-cygwin', '-mms-bitfields' ] +windres = [ 'windres' ] + +ld = [ 'g++', '--no-undefined', '--enable-runtime-pseudo-reloc', '$flags$', '$obj$', '$path$', '$gsl$', '$gtk$', '$mrtrix$', '-o', '$bin$' ] +ld_flags = [ '-mno-cygwin' ] +ld_flags_lib_prefix = '-l' + +ld_lib = [ 'g++', '--no-undefined', '--enable-runtime-pseudo-reloc', '-shared', '$flags$', '$obj$', '-o', '$lib$' ] +ld_lib_flags = [ '-mno-cygwin' ] + +cpp_flags_debug = cpp_flags + [ '-g' ] +ld_flags_debug = ld_flags + [ '-g' ] +ld_lib_flags_debug = ld_lib_flags + [ '-g' ] + +cpp_flags_profile = [ '-pg' ] + cpp_flags_debug +ld_flags_profile = ld_flags_debug + [ '-pg' ] +ld_lib_flags_profile = ld_lib_flags_debug + [ '-pg' ] + +cpp_flags += [ '-O3', '-DOPTIMISED', '-DCALCULATE_GRADIENT' ] + +cpp_flags_release = cpp_flags + [ '-DNDEBUG', '-DOPTIMISED', '-DCALCULATE_GRADIENT' ] + +cpp_flags_gsl = [ '-IC:\dev\include', '-DGSL_DLL' ] +ld_flags_gsl = [ '-lgsl', '-lgslcblas' ] +ld_flags_gl = [ '-lopengl32', '-lglu32' ] +pkgconfig = [ 'pkg-config' ] +pkgconfig_env = None + + + diff --git a/sysconf/xmingw.py b/sysconf/xmingw.py new file mode 100644 index 0000000..0a85f36 --- /dev/null +++ b/sysconf/xmingw.py @@ -0,0 +1,39 @@ +from sysconf.common import * + +obj_suffix = '.o' +exe_suffix = '.exe' +lib_prefix = '' +lib_suffix = '.dll' + +cpp = [ 'i586-mingw32msvc-g++', '-c', '$flags$', '$gtk$', '$path$', '$src$', '-o', '$obj$' ] +cpp_flags = [ '-Wall', '-march=i686', '-fno-strict-aliasing', '-DGL_GLEXT_PROTOTYPES', '-mno-cygwin', '-mms-bitfields' ] +windres = [ 'i586-mingw32msvc-windres' ] + +ld_use_shell = True +ld = [ 'i586-mingw32msvc-g++', '--no-undefined', '--enable-runtime-pseudo-reloc', '$flags$', '$obj$', '$path$', '$gsl$', '$gtk$', '$mrtrix$', '-o', '$bin$' ] +ld_flags = [ '-mno-cygwin', '-Wl,-subsystem,windows' ] +ld_flags_lib_prefix = '-l' + +ld_lib = [ 'i586-mingw32msvc-g++', '--no-undefined', '--enable-runtime-pseudo-reloc', '-shared', '$flags$', '$obj$', '-o', '$lib$' ] +ld_lib_flags = [ '-mno-cygwin' ] + +cpp_flags_debug = cpp_flags + [ '-g' ] +ld_flags_debug = ld_flags + [ '-g' ] +ld_lib_flags_debug = ld_lib_flags + [ '-g' ] + +cpp_flags_profile = [ '-pg' ] + cpp_flags_debug +ld_flags_profile = ld_flags_debug + [ '-pg' ] +ld_lib_flags_profile = ld_lib_flags_debug + [ '-pg' ] + +cpp_flags += [ '-O3' ] + +cpp_flags_release = cpp_flags + [ '-DNDEBUG' ] + +cpp_flags_gsl = [ '-I/target/include', '-DGSL_DLL' ] +ld_flags_gsl = [ '-L/target/lib -lgsl', '-lgslcblas' ] +ld_flags_gl = [ '-lopengl32', '-lglu32' ] +pkgconfig = [ 'pkg-config' ] +pkgconfig_env = { 'PKG_CONFIG_PATH': '/target/lib/pkgconfig' } + + + diff --git a/test_output/cpp_output.txt b/test_output/cpp_output.txt new file mode 100644 index 0000000..3ca7f85 --- /dev/null +++ b/test_output/cpp_output.txt @@ -0,0 +1,19 @@ +set.prop_names(): [ PROP_1 PROP_2 PROP_3 PROP_4 PROP_5 ] +set.elem_prop_index(ELEM_PROP_1): 0 +set.num_elem_props(): 5 +set.has_prop(PROP_2): 1 +set.has_elem_prop(ELEM_PROP_7): 0 +set.prop_names(): [ PROP_1 PROP_2 PROP_3 PROP_4 PROP_5 ] +set.get_extend_elem_prop_header(): [ EXT_ELEM_PROP_1 EXT_ELEM_PROP_2 EXT_ELEM_PROP_3 EXT_ELEM_PROP_4 EXT_ELEM_PROP_5 ] +set.prop_names(): [ PROP_1 PROP_2 PROP_3 PROP_5 ] +set.get_extend_elem_prop(EXT_ELEM_PROP_2,0): Boogle 2-0 +set.prop_index(PROP_2): 1 +set.has_extend_elem_prop(EXT_ELEM_PROP_3): 1 +set.elem_prop_name(1): ELEM_PROP_2 +set.prop(PROP_5): 411 +set.prop_index(PROP_1): 0 +set.num_props(): 4 +set.size(): 2 +set.size(): 2 +set.num_extend_elem_props(): 6 +set.num_extend_elem_props(): 6 diff --git a/test_output/python_output.txt b/test_output/python_output.txt new file mode 100644 index 0000000..b050011 --- /dev/null +++ b/test_output/python_output.txt @@ -0,0 +1,55 @@ +set.prop_names(): ['PROP_1', 'PROP_2', 'PROP_3', 'PROP_4', 'PROP_5'] +set.elem_prop_index(ELEM_PROP_1): 0 +set.num_elem_props(): 5 +set.has_prop(PROP_2): True +set.has_elem_prop(ELEM_PROP_7): 0 +set.prop_names(): ['PROP_1', 'PROP_2', 'PROP_3', 'PROP_4', 'PROP_5'] +set.get_extend_elem_prop_header(): ['EXT_ELEM_PROP_5', 'EXT_ELEM_PROP_4', 'EXT_ELEM_PROP_1', 'EXT_ELEM_PROP_3', 'EXT_ELEM_PROP_2'] +set.prop_names(): ['PROP_1', 'PROP_2', 'PROP_3', 'PROP_5'] +set.get_extend_elem_prop(EXT_ELEM_PROP_2,0): Ooogle 2-0 +set.prop_index(PROP_2): 1 +set.has_extend_elem_prop(EXT_ELEM_PROP_3): 1 +set.elem_prop_name(1): ELEM_PROP_2 +set.prop(PROP_5): 5.5 +set.prop_index(PROP_1): 0 +set.num_props(): 4 +set.size(): 2 +set.size(): 2 +set.num_extend_elem_props(): 6 +set.num_extend_elem_props(): 6 +set.vsize(): 82 +set.num_props(): 4 +set.prop(PROP_5): 5.5 +set.num_elem_props(): 5 +set.prop_index(PROP_2): 1 +set.has_extend_elem_prop(EXT_ELEM_PROP_9): 0 +set.has_extend_elem_prop(EXT_ELEM_PROP_1): 1 +set.has_extend_elem_prop(EXT_ELEM_PROP_1): 1 +set.num_props(): 4 +set.has_prop(PROP_5): True +set.has_extend_elem_prop(EXT_ELEM_PROP_3): 1 +set.num_props(): 4 +set.has_prop(PROP_6): False +set.num_extend_elem_props(): 10 +set.prop_names(): ['PROP_1', 'PROP_2', 'PROP_3', 'PROP_5'] +set.has_elem_prop(ELEM_PROP_7): 0 +set.has_prop(PROP_3): True +set.bsize(): 75 +set.elem_prop_name(0): ELEM_PROP_1 +set.num_elem_props(): 4 +set.prop_index(PROP_5): 3 +set.prop_index(PROP_1): 0 +set.num_elem_props(): 4 +set.prop_index(PROP_2): 1 +set.vsize(): 4 + + +------------------------------------- + FINAL PRINT +------------------------------------- + +PROP_1: 1.1 +PROP_2: 2.2 +PROP_3: 3.3 +PROP_5: 5.5 +